@mpxjs/webpack-plugin 2.9.38 → 2.9.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/dependencies/DynamicEntryDependency.js +9 -1
- package/lib/dependencies/RecordRuntimeInfoDependency.js +66 -0
- package/lib/index.js +181 -8
- package/lib/json-compiler/helper.js +3 -1
- package/lib/json-compiler/index.js +40 -2
- package/lib/loader.js +10 -0
- package/lib/native-loader.js +1 -0
- package/lib/resolver/DynamicPlugin.js +18 -0
- package/lib/runtime-render/base-wxml.js +75 -0
- package/lib/runtime-render/custom-element-json.js +4 -0
- package/lib/runtime-render/custom-element-script.js +32 -0
- package/lib/runtime-render/gen-dynamic-template.js +6 -0
- package/lib/runtime-render/gen-mpx-custom-element.js +13 -0
- package/lib/runtime-render/mpx-custom-element-main.mpx +18 -0
- package/lib/runtime-render/mpx-custom-element.mpx +18 -0
- package/lib/style-compiler/index.js +18 -1
- package/lib/style-compiler/plugins/css-array-list.js +26 -0
- package/lib/template-compiler/compiler.js +516 -324
- package/lib/template-compiler/dynamic.js +13 -0
- package/lib/template-compiler/index.js +36 -7
- package/lib/template-compiler/parse-exps.js +148 -0
- package/lib/utils/resolve-mpx-custom-element-path.js +7 -0
- package/lib/utils/shallow-stringify.js +17 -0
- package/lib/web/processTemplate.js +1 -2
- package/lib/wxml/loader.js +9 -2
- package/package.json +4 -2
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const uselessAttrs = ['parent', 'exps', 'unary', 'attrsMap']
|
|
2
|
+
const uselessArrAttrs = ['children', 'attrsList']
|
|
3
|
+
|
|
4
|
+
function stringify (ast) {
|
|
5
|
+
return JSON.stringify(ast, (k, v) => {
|
|
6
|
+
if (uselessAttrs.includes(k)) return undefined
|
|
7
|
+
if (uselessArrAttrs.includes(k) && v && !v.length) return undefined
|
|
8
|
+
if (k === 'tag' && v === 'temp-node') return 'block'
|
|
9
|
+
return v
|
|
10
|
+
})
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports.stringify = stringify
|
|
@@ -3,6 +3,10 @@ const bindThis = require('./bind-this')
|
|
|
3
3
|
const parseRequest = require('../utils/parse-request')
|
|
4
4
|
const { matchCondition } = require('../utils/match-condition')
|
|
5
5
|
const loaderUtils = require('loader-utils')
|
|
6
|
+
const { MPX_DISABLE_EXTRACTOR_CACHE } = require('../utils/const')
|
|
7
|
+
const RecordRuntimeInfoDependency = require('../dependencies/RecordRuntimeInfoDependency')
|
|
8
|
+
const { createTemplateEngine, createSetupTemplate } = require('@mpxjs/template-engine')
|
|
9
|
+
const { stringify } = require('./dynamic')
|
|
6
10
|
|
|
7
11
|
module.exports = function (raw) {
|
|
8
12
|
this.cacheable()
|
|
@@ -18,15 +22,15 @@ module.exports = function (raw) {
|
|
|
18
22
|
const globalSrcMode = mpx.srcMode
|
|
19
23
|
const localSrcMode = queryObj.mode
|
|
20
24
|
const packageName = queryObj.packageRoot || mpx.currentPackageRoot || 'main'
|
|
21
|
-
const componentsMap = mpx.componentsMap[packageName]
|
|
22
|
-
const pagesMap = mpx.pagesMap
|
|
23
25
|
const wxsContentMap = mpx.wxsContentMap
|
|
24
26
|
const optimizeRenderRules = mpx.optimizeRenderRules
|
|
25
27
|
const usingComponents = queryObj.usingComponents || []
|
|
26
28
|
const componentPlaceholder = queryObj.componentPlaceholder || []
|
|
27
29
|
const hasComment = queryObj.hasComment
|
|
28
30
|
const isNative = queryObj.isNative
|
|
31
|
+
const ctorType = queryObj.ctorType
|
|
29
32
|
const hasScoped = queryObj.hasScoped
|
|
33
|
+
const runtimeCompile = queryObj.isDynamic
|
|
30
34
|
const moduleId = queryObj.moduleId || '_' + mpx.pathHash(resourcePath)
|
|
31
35
|
|
|
32
36
|
let optimizeRenderLevel = 0
|
|
@@ -51,12 +55,12 @@ module.exports = function (raw) {
|
|
|
51
55
|
const { root: ast, meta } = compiler.parse(raw, {
|
|
52
56
|
warn,
|
|
53
57
|
error,
|
|
58
|
+
runtimeCompile,
|
|
54
59
|
usingComponents,
|
|
55
60
|
componentPlaceholder,
|
|
56
61
|
hasComment,
|
|
57
62
|
isNative,
|
|
58
|
-
|
|
59
|
-
isPage: !!pagesMap[resourcePath],
|
|
63
|
+
ctorType,
|
|
60
64
|
mode,
|
|
61
65
|
env,
|
|
62
66
|
srcMode: localSrcMode || globalSrcMode,
|
|
@@ -70,7 +74,7 @@ module.exports = function (raw) {
|
|
|
70
74
|
i18n,
|
|
71
75
|
checkUsingComponents: matchCondition(resourcePath, mpx.checkUsingComponentsRules),
|
|
72
76
|
globalComponents: Object.keys(mpx.usingComponents),
|
|
73
|
-
forceProxyEvent: matchCondition(resourcePath, mpx.forceProxyEventRules),
|
|
77
|
+
forceProxyEvent: matchCondition(resourcePath, mpx.forceProxyEventRules) || runtimeCompile,
|
|
74
78
|
hasVirtualHost: matchCondition(resourcePath, mpx.autoVirtualHostRules)
|
|
75
79
|
})
|
|
76
80
|
|
|
@@ -80,7 +84,7 @@ module.exports = function (raw) {
|
|
|
80
84
|
}
|
|
81
85
|
}
|
|
82
86
|
|
|
83
|
-
|
|
87
|
+
let result = runtimeCompile ? '' : compiler.serialize(ast)
|
|
84
88
|
|
|
85
89
|
if (isNative) {
|
|
86
90
|
return result
|
|
@@ -98,7 +102,11 @@ global.currentInject = {
|
|
|
98
102
|
moduleId: ${JSON.stringify(moduleId)}
|
|
99
103
|
};\n`
|
|
100
104
|
|
|
101
|
-
|
|
105
|
+
if (runtimeCompile || queryObj.dynamicRuntime) {
|
|
106
|
+
resultSource += 'global.currentInject.dynamic = true;\n'
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const rawCode = runtimeCompile ? '' : compiler.genNode(ast)
|
|
102
110
|
if (rawCode) {
|
|
103
111
|
try {
|
|
104
112
|
const ignoreMap = Object.assign({
|
|
@@ -160,5 +168,26 @@ global.currentInject.getRefsData = function () {
|
|
|
160
168
|
extractedResultSource: resultSource
|
|
161
169
|
})
|
|
162
170
|
|
|
171
|
+
if (queryObj.mpxCustomElement) {
|
|
172
|
+
this.cacheable(false)
|
|
173
|
+
const templateEngine = createTemplateEngine(mpx.mode)
|
|
174
|
+
result += `${createSetupTemplate()}\n` + templateEngine.buildTemplate(mpx.getPackageInjectedTemplateConfig(packageName))
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 运行时编译的组件直接返回基础模板的内容,并产出动态文本内容
|
|
178
|
+
if (runtimeCompile) {
|
|
179
|
+
// 包含了运行时组件的template模块必须每次都创建(但并不是每次都需要build),用于收集组件节点信息,传递信息以禁用父级extractor的缓存
|
|
180
|
+
this.emitFile(MPX_DISABLE_EXTRACTOR_CACHE, '', undefined, { skipEmit: true })
|
|
181
|
+
|
|
182
|
+
const templateInfo = {
|
|
183
|
+
templateAst: stringify(ast),
|
|
184
|
+
...meta.runtimeInfo
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// 以 package 为维度存储,meta 上的数据也只是存储了这个组件的 template 上获取的信息,需要在 dependency 里面再次进行合并操作
|
|
188
|
+
this._module.addPresentationalDependency(new RecordRuntimeInfoDependency(packageName, resourcePath, { type: 'template', info: templateInfo }))
|
|
189
|
+
// 运行时组件的模版直接返回空,在生成模版静态文件的时候(beforeModuleAssets)再动态注入
|
|
190
|
+
}
|
|
191
|
+
|
|
163
192
|
return result
|
|
164
193
|
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// todo 待讨论 parser + interpreter 的部分是否需要单独抽个 package 出去
|
|
2
|
+
const acorn = require('acorn')
|
|
3
|
+
const walk = require('acorn-walk')
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 基于目前小程序所支持的模版语法实现,对于不支持的语法在编译阶段直接报错
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const NODE_TYPE = {
|
|
10
|
+
Program: 1,
|
|
11
|
+
Identifier: 2,
|
|
12
|
+
Literal: 3,
|
|
13
|
+
ArrayExpression: 28,
|
|
14
|
+
ObjectExpression: 29,
|
|
15
|
+
Property: 31,
|
|
16
|
+
UnaryExpression: 33,
|
|
17
|
+
// UpdateExpression: 34,
|
|
18
|
+
BinaryExpression: 35,
|
|
19
|
+
LogicalExpression: 37,
|
|
20
|
+
MemberExpression: 38,
|
|
21
|
+
ConditionalExpression: 39,
|
|
22
|
+
ExpressionStatement: 40
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const error = function (msg) {
|
|
26
|
+
throw new Error(`[Mpx dynamic expression parser error]: ${msg}`)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
walk.full = function full (node, baseVisitor, state, override) {
|
|
30
|
+
const stack = []
|
|
31
|
+
; (function c (node, st, override, s) {
|
|
32
|
+
const type = override || node.type
|
|
33
|
+
if (!baseVisitor[type]) {
|
|
34
|
+
error(`${type} grammar is not supported in the template`)
|
|
35
|
+
}
|
|
36
|
+
baseVisitor[type](node, st, c, s)
|
|
37
|
+
})(node, state, override, stack)
|
|
38
|
+
|
|
39
|
+
// 限定 bodyStack 长度,仅支持单表达式的写法
|
|
40
|
+
const bodyStackIndex = 1
|
|
41
|
+
if (stack[bodyStackIndex].length > 1) {
|
|
42
|
+
error('only support one expression in the template')
|
|
43
|
+
}
|
|
44
|
+
return stack
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const baseVisitor = {}
|
|
48
|
+
|
|
49
|
+
baseVisitor.UnaryExpression = function (node, st, c, s) {
|
|
50
|
+
// const nodeType = node.type === 'UnaryExpression' ? NODE_TYPE.UnaryExpression : NODE_TYPE.UpdateExpression
|
|
51
|
+
const nodeType = NODE_TYPE.UnaryExpression
|
|
52
|
+
const argumentNodeStack = []
|
|
53
|
+
s.push(nodeType, node.operator, argumentNodeStack, node.prefix)
|
|
54
|
+
c(node.argument, st, 'Expression', argumentNodeStack)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
baseVisitor.BinaryExpression = baseVisitor.LogicalExpression = function (node, st, c, s) {
|
|
58
|
+
const nodeType = node.type === 'BinaryExpression' ? NODE_TYPE.BinaryExpression : NODE_TYPE.LogicalExpression
|
|
59
|
+
const leftNodeStack = []
|
|
60
|
+
const rightNodeStack = []
|
|
61
|
+
// todo operator 可以严格按照小程序模版能力进行限制
|
|
62
|
+
s.push(nodeType, node.operator, leftNodeStack, rightNodeStack)
|
|
63
|
+
c(node.left, st, 'Expression', leftNodeStack)
|
|
64
|
+
c(node.right, st, 'Expression', rightNodeStack)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
baseVisitor.ConditionalExpression = (node, st, c, s) => {
|
|
68
|
+
const testNodeStack = []
|
|
69
|
+
const consequentNodeStack = []
|
|
70
|
+
const alternateNodeStack = []
|
|
71
|
+
s.push(NODE_TYPE.ConditionalExpression, testNodeStack, consequentNodeStack, alternateNodeStack)
|
|
72
|
+
c(node.test, st, 'Expression', testNodeStack)
|
|
73
|
+
c(node.consequent, st, 'Expression', consequentNodeStack)
|
|
74
|
+
c(node.alternate, st, 'Expression', alternateNodeStack)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const visitor = walk.make({
|
|
78
|
+
Program (node, st, c, s) {
|
|
79
|
+
const bodyStack = []
|
|
80
|
+
s.push(NODE_TYPE.Program, bodyStack)
|
|
81
|
+
for (let i = 0, list = node.body; i < list.length; i += 1) {
|
|
82
|
+
const stmt = list[i]
|
|
83
|
+
bodyStack[i] = []
|
|
84
|
+
c(stmt, st, 'Statement', bodyStack[i])
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
ExpressionStatement (node, st, c, s) {
|
|
88
|
+
const expressionStack = []
|
|
89
|
+
s.push(NODE_TYPE.ExpressionStatement, expressionStack)
|
|
90
|
+
c(node.expression, st, null, expressionStack)
|
|
91
|
+
},
|
|
92
|
+
MemberExpression (node, st, c, s) {
|
|
93
|
+
const objectNodeStack = []
|
|
94
|
+
const propertyNodeStack = []
|
|
95
|
+
s.push(NODE_TYPE.MemberExpression, objectNodeStack, propertyNodeStack, node.computed)
|
|
96
|
+
c(node.object, st, 'Expression', objectNodeStack)
|
|
97
|
+
c(node.property, st, 'Expression', propertyNodeStack)
|
|
98
|
+
},
|
|
99
|
+
ArrayExpression (node, st, c, s) {
|
|
100
|
+
const elementsStack = []
|
|
101
|
+
s.push(NODE_TYPE.ArrayExpression, elementsStack)
|
|
102
|
+
node.elements.forEach((elt, index) => {
|
|
103
|
+
if (elt) {
|
|
104
|
+
elementsStack[index] = []
|
|
105
|
+
c(elt, st, 'Expression', elementsStack[index])
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
},
|
|
109
|
+
ObjectExpression (node, st, c, s) {
|
|
110
|
+
const propertiesStack = []
|
|
111
|
+
s.push(NODE_TYPE.ObjectExpression, propertiesStack)
|
|
112
|
+
node.properties.forEach((prop, index) => {
|
|
113
|
+
propertiesStack[index] = []
|
|
114
|
+
c(prop, st, null, propertiesStack[index])
|
|
115
|
+
})
|
|
116
|
+
},
|
|
117
|
+
Property (node, st, c, s) {
|
|
118
|
+
const keyNodeStack = []
|
|
119
|
+
const valueNodeStack = []
|
|
120
|
+
s.push(NODE_TYPE.Property, keyNodeStack, valueNodeStack, node.kind)
|
|
121
|
+
c(node.key, st, 'Expression', keyNodeStack)
|
|
122
|
+
c(node.value, st, 'Expression', valueNodeStack)
|
|
123
|
+
},
|
|
124
|
+
Literal (node, st, c, s) {
|
|
125
|
+
// todo node.raw/-1 目前应该都用不到,后续可以优化
|
|
126
|
+
s.push(NODE_TYPE.Literal, node.value, node.raw, -1) // -1?
|
|
127
|
+
},
|
|
128
|
+
Identifier (node, st, c, s) {
|
|
129
|
+
s.push(NODE_TYPE.Identifier, node.name)
|
|
130
|
+
},
|
|
131
|
+
Expression (node, st, c, s) {
|
|
132
|
+
c(node, st, null, s)
|
|
133
|
+
},
|
|
134
|
+
Statement (node, st, c, s) {
|
|
135
|
+
c(node, st, null, s)
|
|
136
|
+
}
|
|
137
|
+
}, baseVisitor)
|
|
138
|
+
|
|
139
|
+
module.exports = {
|
|
140
|
+
parseExp (str) {
|
|
141
|
+
// 确保 str 都是为 expressionStatement
|
|
142
|
+
if (!/^\(*\)$/.test(str)) {
|
|
143
|
+
str = `(${str})`
|
|
144
|
+
}
|
|
145
|
+
return walk.full(acorn.parse(str, { ecmaVersion: 5 }), visitor)
|
|
146
|
+
},
|
|
147
|
+
NODE_TYPE
|
|
148
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const hasOwn = require('./has-own')
|
|
2
|
+
|
|
3
|
+
module.exports = function shallowStringify (obj, isTemplateExp) {
|
|
4
|
+
const arr = []
|
|
5
|
+
for (const key in obj) {
|
|
6
|
+
if (hasOwn(obj, key)) {
|
|
7
|
+
let value = obj[key]
|
|
8
|
+
if (Array.isArray(value)) {
|
|
9
|
+
value = `[${value.join(',')}]`
|
|
10
|
+
} else if (typeof value === 'object') {
|
|
11
|
+
value = shallowStringify(value, isTemplateExp)
|
|
12
|
+
}
|
|
13
|
+
arr.push(isTemplateExp ? `${key}:${value}` : `'${key}':${value}`)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return isTemplateExp ? `({${arr.join(',')}})` : `{${arr.join(',')}}`
|
|
17
|
+
}
|
package/lib/wxml/loader.js
CHANGED
|
@@ -5,6 +5,7 @@ const config = require('../config')
|
|
|
5
5
|
const createHelpers = require('../helpers')
|
|
6
6
|
const isUrlRequest = require('../utils/is-url-request')
|
|
7
7
|
const parseRequest = require('../utils/parse-request')
|
|
8
|
+
const genDynamicTemplate = require('../runtime-render/gen-dynamic-template')
|
|
8
9
|
|
|
9
10
|
let count = 0
|
|
10
11
|
|
|
@@ -26,6 +27,14 @@ module.exports = function (content) {
|
|
|
26
27
|
const mode = mpx.mode
|
|
27
28
|
const localSrcMode = queryObj.mode
|
|
28
29
|
const customAttributes = options.attributes || mpx.attributes || []
|
|
30
|
+
const packageName = queryObj.packageRoot || mpx.currentPackageRoot || 'main'
|
|
31
|
+
const isDynamic = queryObj.isDynamic
|
|
32
|
+
|
|
33
|
+
const exportsString = 'module.exports = '
|
|
34
|
+
|
|
35
|
+
if (isDynamic) {
|
|
36
|
+
return exportsString + JSON.stringify(genDynamicTemplate(packageName)) + ';'
|
|
37
|
+
}
|
|
29
38
|
|
|
30
39
|
const { getRequestString } = createHelpers(this)
|
|
31
40
|
|
|
@@ -71,8 +80,6 @@ module.exports = function (content) {
|
|
|
71
80
|
content = content.join('')
|
|
72
81
|
content = JSON.stringify(content)
|
|
73
82
|
|
|
74
|
-
const exportsString = 'module.exports = '
|
|
75
|
-
|
|
76
83
|
return exportsString + content.replace(/__HTMLLINK__\d+__/g, (match) => {
|
|
77
84
|
if (!data[match]) return match
|
|
78
85
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpxjs/webpack-plugin",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.40",
|
|
4
4
|
"description": "mpx compile core",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mpx"
|
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
"@better-scroll/slide": "^2.5.1",
|
|
28
28
|
"@better-scroll/wheel": "^2.5.1",
|
|
29
29
|
"@better-scroll/zoom": "^2.5.1",
|
|
30
|
+
"@mpxjs/template-engine": "^2.8.7",
|
|
31
|
+
"acorn": "^8.11.3",
|
|
30
32
|
"acorn-walk": "^7.2.0",
|
|
31
33
|
"async": "^2.6.0",
|
|
32
34
|
"css": "^2.2.1",
|
|
@@ -82,5 +84,5 @@
|
|
|
82
84
|
"engines": {
|
|
83
85
|
"node": ">=14.14.0"
|
|
84
86
|
},
|
|
85
|
-
"gitHead": "
|
|
87
|
+
"gitHead": "af534454668449ab020db3566cc5af98049286fb"
|
|
86
88
|
}
|