@mpxjs/webpack-plugin 2.8.39 → 2.8.40-test

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.
Files changed (51) hide show
  1. package/lib/dependencies/CommonJsExtractDependency.js +51 -0
  2. package/lib/dependencies/ResolveDependency.js +11 -9
  3. package/lib/extractor.js +1 -0
  4. package/lib/helpers.js +9 -1
  5. package/lib/index.js +173 -72
  6. package/lib/json-compiler/helper.js +25 -9
  7. package/lib/json-compiler/index.js +77 -28
  8. package/lib/loader.js +3 -10
  9. package/lib/native-loader.js +21 -14
  10. package/lib/platform/json/wx/index.js +65 -2
  11. package/lib/platform/run-rules.js +2 -1
  12. package/lib/platform/template/normalize-component-rules.js +2 -0
  13. package/lib/platform/template/wx/component-config/README.md +1 -1
  14. package/lib/platform/template/wx/component-config/fix-html-tag.js +17 -0
  15. package/lib/platform/template/wx/component-config/hypen-tag-name.js +2 -6
  16. package/lib/platform/template/wx/component-config/index.js +4 -2
  17. package/lib/platform/template/wx/component-config/view.js +0 -11
  18. package/lib/platform/template/wx/index.js +65 -18
  19. package/lib/runtime/base.styl +0 -5
  20. package/lib/runtime/components/web/filterTag.js +9 -30
  21. package/lib/runtime/components/web/getInnerListeners.js +2 -14
  22. package/lib/runtime/components/web/mpx-keep-alive.vue +10 -17
  23. package/lib/runtime/components/web/mpx-movable-view.vue +105 -23
  24. package/lib/runtime/components/web/mpx-picker-view.vue +1 -1
  25. package/lib/runtime/components/web/mpx-scroll-view.vue +69 -23
  26. package/lib/runtime/components/web/mpx-swiper.vue +152 -62
  27. package/lib/runtime/components/web/mpx-video.vue +123 -89
  28. package/lib/runtime/components/web/mpx-web-view.vue +120 -81
  29. package/lib/runtime/components/web/promisify.js +19 -0
  30. package/lib/runtime/components/wx/default-page.mpx +27 -0
  31. package/lib/runtime/optionProcessor.js +12 -18
  32. package/lib/style-compiler/index.js +5 -1
  33. package/lib/template-compiler/bind-this.js +280 -49
  34. package/lib/template-compiler/compiler.js +54 -58
  35. package/lib/template-compiler/index.js +35 -23
  36. package/lib/utils/dom-tag-config.js +115 -0
  37. package/lib/utils/make-map.js +12 -0
  38. package/lib/utils/string.js +7 -1
  39. package/lib/utils/ts-loader-watch-run-loader-filter.js +4 -5
  40. package/lib/web/processJSON.js +35 -0
  41. package/lib/web/processScript.js +7 -4
  42. package/lib/web/processTemplate.js +7 -34
  43. package/package.json +4 -4
  44. package/lib/partial-compile/index.js +0 -35
  45. package/lib/template-compiler/preprocessor.js +0 -29
  46. package/lib/wxss/compile-exports.js +0 -52
  47. package/lib/wxss/createResolver.js +0 -36
  48. package/lib/wxss/css-base.js +0 -79
  49. package/lib/wxss/getLocalIdent.js +0 -25
  50. package/lib/wxss/localsLoader.js +0 -44
  51. package/lib/wxss/processCss.js +0 -274
@@ -19,9 +19,166 @@ dangerousKeys.split(',').forEach((key) => {
19
19
  dangerousKeyMap[key] = true
20
20
  })
21
21
 
22
+ // 判断 Identifier 是否需要处理
23
+ function checkBindThis (path) {
24
+ return !(t.isDeclaration(path.parent) && path.parentKey === 'id') &&
25
+ !(t.isFunction(path.parent) && path.listKey === 'params') &&
26
+ !(t.isMethod(path.parent) && path.parentKey === 'key' && !path.parent.computed) &&
27
+ !(t.isProperty(path.parent) && path.parentKey === 'key' && !path.parent.computed) &&
28
+ !(t.isMemberExpression(path.parent) && path.parentKey === 'property' && !path.parent.computed) &&
29
+ !t.isArrayPattern(path.parent) &&
30
+ !t.isObjectPattern(path.parent) &&
31
+ !hash[path.node.name]
32
+ }
33
+
34
+ // 计算访问路径
35
+ function calPropName (path) {
36
+ let current = path.parentPath
37
+ let last = path
38
+ let keyPath = '' + path.node.name
39
+
40
+ while (current.isMemberExpression() && last.parentKey !== 'property') {
41
+ if (current.node.computed) {
42
+ if (t.isLiteral(current.node.property)) {
43
+ if (t.isStringLiteral(current.node.property)) {
44
+ if (dangerousKeyMap[current.node.property.value]) {
45
+ break
46
+ }
47
+ keyPath += `.${current.node.property.value}`
48
+ } else {
49
+ keyPath += `[${current.node.property.value}]`
50
+ }
51
+ } else {
52
+ break
53
+ }
54
+ } else {
55
+ if (dangerousKeyMap[current.node.property.name]) {
56
+ break
57
+ }
58
+ keyPath += `.${current.node.property.name}`
59
+ }
60
+ last = current
61
+ current = current.parentPath
62
+ }
63
+
64
+ return {
65
+ last,
66
+ keyPath
67
+ }
68
+ }
69
+
70
+ function checkDelAndGetPath (path) {
71
+ let current = path
72
+ let delPath = path
73
+ let canDel = true
74
+ let ignore = false
75
+ let replace = false
76
+
77
+ // 确定删除路径
78
+ while (!t.isBlockStatement(current)) {
79
+ // case: !!a
80
+ if (t.isUnaryExpression(current.parent) && current.key === 'argument') {
81
+ delPath = current.parentPath
82
+ } else if (t.isCallExpression(current.parent)) {
83
+ // case: String(a) || this._p(a)
84
+ const args = current.node.arguments || current.parent.arguments || []
85
+ if (args.length === 1) {
86
+ delPath = current.parentPath
87
+ } else {
88
+ // case: _i(a, function() {})
89
+ canDel = false
90
+ break
91
+ }
92
+ } else if (t.isMemberExpression(current.parent)) { // case: String(a,'123').b.c
93
+ if (current.parent.computed && !t.isLiteral(current.parent.property)) { // case: a[b] or a.b[c.d]
94
+ canDel = false
95
+ break
96
+ } else {
97
+ delPath = current.parentPath
98
+ }
99
+ } else if (t.isLogicalExpression(current.container)) { // case: a || ''
100
+ const key = current.key === 'left' ? 'right' : 'left'
101
+ if (t.isLiteral(current.parent[key])) {
102
+ delPath = current.parentPath
103
+ } else {
104
+ canDel = false
105
+ break
106
+ }
107
+ } else if (current.key === 'expression' && t.isExpressionStatement(current.parentPath)) { // dealRemove删除节点时需要
108
+ delPath = current.parentPath
109
+ } else {
110
+ break
111
+ }
112
+
113
+ current = current.parentPath
114
+ }
115
+
116
+ // 确定是否可删除
117
+ while (!t.isBlockStatement(current) && canDel) {
118
+ const { key, container } = current
119
+ if (
120
+ t.isLogicalExpression(container) || // a && b
121
+ (t.isIfStatement(container) && key === 'test') // if (a) {}
122
+ ) {
123
+ canDel = false
124
+ break
125
+ }
126
+
127
+ if (t.isConditionalExpression(container)) {
128
+ if (key === 'test') canDel = false
129
+ else ignore = true
130
+ break
131
+ }
132
+
133
+ if (
134
+ t.isBinaryExpression(container) || // 运算 a + b
135
+ (key === 'value' && t.isObjectProperty(container) && canDel) // ({ name: a })
136
+ ) {
137
+ canDel = true
138
+ replace = true
139
+ // 不能break,case: if (a + b) {}
140
+ }
141
+
142
+ current = current.parentPath
143
+ }
144
+
145
+ return {
146
+ delPath,
147
+ canDel,
148
+ ignore,
149
+ replace
150
+ }
151
+ }
152
+
153
+ // 判断前缀是否存在(只判断前缀,全等的情况,会返回false)
154
+ function checkPrefix (keys, key) {
155
+ for (let i = 0; i < keys.length; i++) {
156
+ const str = keys[i]
157
+ if (key === str) continue
158
+ // 确保判断当前标识是完整的单词
159
+ if (key.startsWith(str) && (key[str.length] === '.' || key[str.length] === '[')) return true
160
+ }
161
+ return false
162
+ }
163
+
164
+ function dealRemove (path, replace) {
165
+ try {
166
+ if (replace) {
167
+ path.replaceWith(t.stringLiteral(''))
168
+ } else {
169
+ t.validate(path, path.key, null)
170
+ path.remove()
171
+ }
172
+ delete path.needBind
173
+ delete path.collectInfo
174
+ } catch (e) {
175
+ }
176
+ }
177
+
22
178
  module.exports = {
23
179
  transform (code, {
24
180
  needCollect = false,
181
+ renderReduce = false,
25
182
  ignoreMap = {}
26
183
  } = {}) {
27
184
  const ast = babylon.parse(code, {
@@ -30,10 +187,88 @@ module.exports = {
30
187
  ]
31
188
  })
32
189
 
190
+ let currentBlock = null
191
+ const bindingsMap = new Map()
192
+
33
193
  const propKeys = []
34
194
  let isProps = false
35
195
 
196
+ const collectVisitor = {
197
+ BlockStatement: {
198
+ enter (path) { // 收集作用域下所有变量(keyPath)
199
+ bindingsMap.set(path, {
200
+ parent: currentBlock,
201
+ bindings: {}
202
+ })
203
+ currentBlock = path
204
+ },
205
+ exit (path) {
206
+ currentBlock = bindingsMap.get(path).parent
207
+ }
208
+ },
209
+ Identifier (path) {
210
+ if (
211
+ checkBindThis(path) &&
212
+ !ignoreMap[path.node.name]
213
+ ) {
214
+ const scopeBinding = path.scope.hasBinding(path.node.name)
215
+ // 删除局部作用域的变量
216
+ if (scopeBinding) {
217
+ if (renderReduce) {
218
+ const { delPath, canDel, ignore, replace } = checkDelAndGetPath(path)
219
+ if (canDel && !ignore) {
220
+ delPath.delInfo = {
221
+ isLocal: true,
222
+ canDel,
223
+ replace
224
+ }
225
+ }
226
+ }
227
+ return
228
+ }
229
+ const { last, keyPath } = calPropName(path)
230
+ path.needBind = true
231
+ if (needCollect) {
232
+ last.collectInfo = {
233
+ key: t.stringLiteral(keyPath),
234
+ isSimple: !/[[.]/.test(keyPath)
235
+ }
236
+ }
237
+
238
+ if (!renderReduce) return
239
+
240
+ const { delPath, canDel, ignore, replace } = checkDelAndGetPath(path)
241
+ if (ignore) return
242
+
243
+ delPath.delInfo = {
244
+ keyPath,
245
+ canDel,
246
+ replace
247
+ }
248
+
249
+ const { bindings } = bindingsMap.get(currentBlock)
250
+ const target = bindings[keyPath] || []
251
+ target.push({
252
+ path: delPath,
253
+ canDel
254
+ })
255
+ bindings[keyPath] = target
256
+ }
257
+ }
258
+ }
259
+
36
260
  const bindThisVisitor = {
261
+ BlockStatement: {
262
+ enter (path) {
263
+ const scope = bindingsMap.get(path)
264
+ const parentScope = bindingsMap.get(scope.parent)
265
+ scope.pBindings = parentScope ? Object.assign({}, parentScope.bindings, parentScope.pBindings) : {}
266
+ currentBlock = path
267
+ },
268
+ exit (path) {
269
+ currentBlock = bindingsMap.get(path).parent
270
+ }
271
+ },
37
272
  // 标记收集props数据
38
273
  CallExpression: {
39
274
  enter (path) {
@@ -50,76 +285,72 @@ module.exports = {
50
285
  exit (path) {
51
286
  if (path.isProps) {
52
287
  // 移除无意义的__props调用
53
- path.replaceWith(path.node.arguments[0])
288
+ const args = path.node.arguments[0]
289
+ path.replaceWith(args)
54
290
  isProps = false
55
291
  delete path.isProps
56
292
  }
57
293
  }
58
294
  },
59
- Identifier (path) {
60
- if (
61
- !(t.isDeclaration(path.parent) && path.parentKey === 'id') &&
62
- !(t.isFunction(path.parent) && path.listKey === 'params') &&
63
- !(t.isMethod(path.parent) && path.parentKey === 'key' && !path.parent.computed) &&
64
- !(t.isProperty(path.parent) && path.parentKey === 'key' && !path.parent.computed) &&
65
- !(t.isMemberExpression(path.parent) && path.parentKey === 'property' && !path.parent.computed) &&
66
- !t.isArrayPattern(path.parent) &&
67
- !t.isObjectPattern(path.parent) &&
68
- !hash[path.node.name]
69
- ) {
70
- let current
71
- let last
72
- if (!path.scope.hasBinding(path.node.name) && !ignoreMap[path.node.name]) {
73
- // bind this
74
- path.replaceWith(t.memberExpression(t.thisExpression(), path.node))
295
+ // enter 先于特定标识执行
296
+ enter (path) {
297
+ // 删除重复变量
298
+ if (path.delInfo) {
299
+ const { keyPath, canDel, isLocal, replace } = path.delInfo
300
+ delete path.delInfo
75
301
 
76
- if (isProps) {
77
- propKeys.push(path.node.property.name)
302
+ if (canDel) {
303
+ if (isLocal) { // 局部作用域里的变量,可直接删除
304
+ dealRemove(path, replace)
305
+ return
78
306
  }
307
+ const data = bindingsMap.get(currentBlock)
308
+ const { bindings, pBindings } = data
309
+ const allBindings = Object.assign({}, pBindings, bindings)
79
310
 
80
- if (needCollect) {
81
- // 找到访问路径
82
- current = path.parentPath
83
- last = path
84
- let keyPath = '' + path.node.property.name
85
- while (current.isMemberExpression() && last.parentKey !== 'property') {
86
- if (current.node.computed) {
87
- if (t.isLiteral(current.node.property)) {
88
- if (t.isStringLiteral(current.node.property)) {
89
- if (dangerousKeyMap[current.node.property.value]) {
90
- break
91
- }
92
- keyPath += `.${current.node.property.value}`
93
- } else {
94
- keyPath += `[${current.node.property.value}]`
95
- }
96
- } else {
97
- break
98
- }
99
- } else {
100
- if (dangerousKeyMap[current.node.property.name]) {
101
- break
102
- }
103
- keyPath += `.${current.node.property.name}`
311
+ // 优先判断前缀,再判断全等
312
+ if (checkPrefix(Object.keys(allBindings), keyPath) || pBindings[keyPath]) {
313
+ dealRemove(path, replace)
314
+ } else {
315
+ const currentBlockVars = bindings[keyPath]
316
+ if (currentBlockVars.length > 1) {
317
+ const index = currentBlockVars.findIndex(item => !item.canDel)
318
+ if (index !== -1 || currentBlockVars[0].path !== path) { // 当前block中存在不可删除的变量 || 不是第一个可删除变量,即可删除该变量
319
+ dealRemove(path, replace)
104
320
  }
105
- last = current
106
- current = current.parentPath
107
321
  }
108
- last.collectPath = t.stringLiteral(keyPath)
109
322
  }
110
323
  }
111
324
  }
325
+
326
+ // bind this 将 a 转换成 this.a
327
+ if (path.needBind) {
328
+ const name = path.node.name
329
+ if (name) { // 确保path没有被删除 且 没有被替换成字符串
330
+ if (isProps) {
331
+ propKeys.push(name)
332
+ }
333
+ path.replaceWith(t.memberExpression(t.thisExpression(), path.node))
334
+ }
335
+ delete path.needBind
336
+ }
112
337
  },
113
338
  MemberExpression: {
114
339
  exit (path) {
115
- if (path.collectPath) {
116
- path.replaceWith(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier('_c')), [path.collectPath, path.node]))
117
- delete path.collectPath
340
+ if (path.collectInfo) {
341
+ const { isSimple, key } = path.collectInfo
342
+ const callee = isSimple ? t.identifier('_sc') : t.identifier('_c')
343
+ const replaceNode = renderReduce
344
+ ? t.callExpression(callee, [key])
345
+ : t.callExpression(callee, [key, path.node])
346
+ path.node && path.replaceWith(replaceNode)
347
+ delete path.collectInfo
118
348
  }
119
349
  }
120
350
  }
121
351
  }
122
352
 
353
+ traverse(ast, collectVisitor)
123
354
  traverse(ast, bindThisVisitor)
124
355
 
125
356
  return {
@@ -10,40 +10,13 @@ const getRulesRunner = require('../platform/index')
10
10
  const addQuery = require('../utils/add-query')
11
11
  const transDynamicClassExpr = require('./trans-dynamic-class-expr')
12
12
  const dash2hump = require('../utils/hump-dash').dash2hump
13
-
14
- /**
15
- * Make a map and return a function for checking if a key
16
- * is in that map.
17
- */
18
- function makeMap (str, expectsLowerCase) {
19
- const map = Object.create(null)
20
- const list = str.split(',')
21
- for (let i = 0; i < list.length; i++) {
22
- map[list[i]] = true
23
- }
24
- return expectsLowerCase
25
- ? function (val) {
26
- return map[val.toLowerCase()]
27
- }
28
- : function (val) {
29
- return map[val]
30
- }
31
- }
13
+ const makeMap = require('../utils/make-map')
14
+ const { isNonPhrasingTag } = require('../utils/dom-tag-config')
32
15
 
33
16
  const no = function () {
34
17
  return false
35
18
  }
36
19
 
37
- // HTML5 tags https://html.spec.whatwg.org/multipage/indices.html#elements-3
38
- // Phrasing Content https://html.spec.whatwg.org/multipage/dom.html#phrasing-content
39
- const isNonPhrasingTag = makeMap(
40
- 'address,article,aside,base,blockquote,body,caption,col,colgroup,dd,' +
41
- 'details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,' +
42
- 'h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,' +
43
- 'optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,' +
44
- 'title,tr,track'
45
- )
46
-
47
20
  /*!
48
21
  * HTML Parser By John Resig (ejohn.org)
49
22
  * Modified by Juriy "kangax" Zaytsev
@@ -653,6 +626,9 @@ function parse (template, options) {
653
626
  srcMode,
654
627
  type: 'template',
655
628
  testKey: 'tag',
629
+ data: {
630
+ usingComponents: options.usingComponents
631
+ },
656
632
  warn: _warn,
657
633
  error: _error
658
634
  })
@@ -878,6 +854,7 @@ function moveBaseDirective (target, from, isDelete = true) {
878
854
  }
879
855
 
880
856
  function stringify (str) {
857
+ if (mode === 'web') str = str.replace(/'/g, '"')
881
858
  return JSON.stringify(str)
882
859
  }
883
860
 
@@ -988,7 +965,7 @@ function parseFuncStr2 (str) {
988
965
  if (subIndex) {
989
966
  const index1 = ret.index + subIndex
990
967
  const index2 = index1 + 6
991
- args = args.substring(0, index1) + JSON.stringify(eventIdentifier) + args.substring(index2)
968
+ args = args.substring(0, index1) + stringify(eventIdentifier) + args.substring(index2)
992
969
  }
993
970
  }
994
971
  return {
@@ -1016,7 +993,7 @@ function stringifyWithResolveComputed (modelValue) {
1016
993
  computedStack.push(char)
1017
994
  if (computedStack.length === 1) {
1018
995
  fragment += '.'
1019
- result.push(JSON.stringify(fragment))
996
+ result.push(stringify(fragment))
1020
997
  fragment = ''
1021
998
  continue
1022
999
  }
@@ -1033,7 +1010,7 @@ function stringifyWithResolveComputed (modelValue) {
1033
1010
  fragment += char
1034
1011
  }
1035
1012
  if (fragment !== '') {
1036
- result.push(JSON.stringify(fragment))
1013
+ result.push(stringify(fragment))
1037
1014
  }
1038
1015
  return result.join('+')
1039
1016
  }
@@ -1114,6 +1091,7 @@ function processBindEvent (el, options) {
1114
1091
  for (const type in eventConfigMap) {
1115
1092
  let needBind = false
1116
1093
  let { configs, rawName, proxy } = eventConfigMap[type]
1094
+ delete eventConfigMap[type]
1117
1095
  if (proxy) {
1118
1096
  needBind = true
1119
1097
  } else if (configs.length > 1) {
@@ -1121,11 +1099,14 @@ function processBindEvent (el, options) {
1121
1099
  } else if (configs.length === 1) {
1122
1100
  needBind = !!configs[0].hasArgs
1123
1101
  }
1102
+
1103
+ const escapedType = dash2hump(type)
1124
1104
  // 排除特殊情况
1125
- if (needBind && !isValidIdentifierStr(type)) {
1105
+ if (!isValidIdentifierStr(escapedType)) {
1126
1106
  warn$1(`EventName ${type} which need be framework proxy processed must be a valid identifier!`)
1127
1107
  needBind = false
1128
1108
  }
1109
+
1129
1110
  if (needBind) {
1130
1111
  if (rawName) {
1131
1112
  // 清空原始事件绑定
@@ -1143,11 +1124,9 @@ function processBindEvent (el, options) {
1143
1124
  value: '__invoke'
1144
1125
  }
1145
1126
  ])
1146
- eventConfigMap[type] = configs.map((item) => {
1127
+ eventConfigMap[escapedType] = configs.map((item) => {
1147
1128
  return item.expStr
1148
1129
  })
1149
- } else {
1150
- delete eventConfigMap[type]
1151
1130
  }
1152
1131
  }
1153
1132
 
@@ -1696,7 +1675,7 @@ function processWebExternalClassesHack (el, options) {
1696
1675
  options.externalClasses.forEach((className) => {
1697
1676
  const index = classNames.indexOf(className)
1698
1677
  if (index > -1) {
1699
- replacements.push(`$attrs[${JSON.stringify(className)}]`)
1678
+ replacements.push(`$attrs[${stringify(className)}]`)
1700
1679
  classNames.splice(index, 1)
1701
1680
  }
1702
1681
  })
@@ -1730,13 +1709,13 @@ function processWebExternalClassesHack (el, options) {
1730
1709
  options.externalClasses.forEach((className) => {
1731
1710
  const index = classNames.indexOf(className)
1732
1711
  if (index > -1) {
1733
- replacements.push(`$attrs[${JSON.stringify(className)}]`)
1712
+ replacements.push(`$attrs[${stringify(className)}]`)
1734
1713
  classNames.splice(index, 1)
1735
1714
  }
1736
1715
  })
1737
1716
 
1738
1717
  if (classNames.length) {
1739
- replacements.unshift(JSON.stringify(classNames.join(' ')))
1718
+ replacements.unshift(stringify(classNames.join(' ')))
1740
1719
  }
1741
1720
 
1742
1721
  addAttrs(el, [{
@@ -1783,6 +1762,7 @@ function processAliAddComponentRootView (el, options) {
1783
1762
  { condition: /^(on|catch)TouchCancel$/, action: 'clone' },
1784
1763
  { condition: /^(on|catch)LongTap$/, action: 'clone' },
1785
1764
  { condition: /^data-/, action: 'clone' },
1765
+ { condition: /^id$/, action: 'clone' },
1786
1766
  { condition: /^style$/, action: 'move' },
1787
1767
  { condition: /^slot$/, action: 'move' }
1788
1768
  ]
@@ -1839,24 +1819,40 @@ function processAliAddComponentRootView (el, options) {
1839
1819
 
1840
1820
  // 有virtualHost情况wx组件注入virtualHost。无virtualHost阿里组件注入root-view。其他跳过。
1841
1821
  function getVirtualHostRoot (options, meta) {
1842
- if (options.isComponent) {
1843
- // 处理组件时
1844
- if (mode === 'wx' && options.hasVirtualHost) {
1845
- // wx组件注入virtualHost配置
1846
- !meta.options && (meta.options = {})
1847
- meta.options.virtualHost = true
1848
- }
1849
- // if (mode === 'ali' && !options.hasVirtualHost) {
1850
- // // ali组件根节点实体化
1851
- // let rootView = createASTElement('view', [
1852
- // {
1853
- // name: 'class',
1854
- // value: `${MPX_ROOT_VIEW} host-${options.moduleId}`
1855
- // }
1856
- // ])
1857
- // processElement(rootView, rootView, options, meta)
1858
- // return rootView
1859
- // }
1822
+ if (srcMode === 'wx') {
1823
+ if (options.isComponent) {
1824
+ if ((mode === 'wx') && options.hasVirtualHost) {
1825
+ // wx组件注入virtualHost配置
1826
+ !meta.options && (meta.options = {})
1827
+ meta.options.virtualHost = true
1828
+ }
1829
+ if ((mode === 'web') && !options.hasVirtualHost) {
1830
+ // ali组件根节点实体化
1831
+ const rootView = createASTElement('view', [
1832
+ {
1833
+ name: 'class',
1834
+ value: `${MPX_ROOT_VIEW} host-${options.moduleId}`
1835
+ },
1836
+ {
1837
+ name: 'v-on',
1838
+ value: '$listeners'
1839
+ }
1840
+ ])
1841
+ rootView.hasEvent = true
1842
+ processElement(rootView, rootView, options, meta)
1843
+ return rootView
1844
+ }
1845
+ }
1846
+ if (options.isPage) {
1847
+ if (mode === 'web') {
1848
+ return createASTElement('div', [
1849
+ {
1850
+ name: 'class',
1851
+ value: 'page'
1852
+ }
1853
+ ])
1854
+ }
1855
+ }
1860
1856
  }
1861
1857
  return getTempNode()
1862
1858
  }
@@ -2327,7 +2323,7 @@ function genFor (node) {
2327
2323
  node.forProcessed = true
2328
2324
  const index = node.for.index || 'index'
2329
2325
  const item = node.for.item || 'item'
2330
- return `this._i(${node.for.exp}, function(${item},${index}){\n${genNode(node)}});\n`
2326
+ return `_i(${node.for.exp}, function(${item},${index}){\n${genNode(node)}});\n`
2331
2327
  }
2332
2328
 
2333
2329
  function genNode (node) {
@@ -19,7 +19,9 @@ module.exports = function (raw) {
19
19
  const localSrcMode = queryObj.mode
20
20
  const packageName = queryObj.packageRoot || mpx.currentPackageRoot || 'main'
21
21
  const componentsMap = mpx.componentsMap[packageName]
22
+ const pagesMap = mpx.pagesMap
22
23
  const wxsContentMap = mpx.wxsContentMap
24
+ const optimizeRenderRules = mpx.optimizeRenderRules
23
25
  const usingComponents = queryObj.usingComponents || []
24
26
  const componentPlaceholder = queryObj.componentPlaceholder || []
25
27
  const hasComment = queryObj.hasComment
@@ -47,6 +49,7 @@ module.exports = function (raw) {
47
49
  hasComment,
48
50
  isNative,
49
51
  isComponent: !!componentsMap[resourcePath],
52
+ isPage: !!pagesMap[resourcePath],
50
53
  mode,
51
54
  env,
52
55
  srcMode: localSrcMode || globalSrcMode,
@@ -83,38 +86,43 @@ module.exports = function (raw) {
83
86
  return result
84
87
  }
85
88
 
86
- const rawCode = `
89
+ resultSource += `
87
90
  global.currentInject = {
88
- moduleId: ${JSON.stringify(moduleId)},
89
- render: function () {
90
- ${compiler.genNode(ast)}
91
- this._r();
92
- }
91
+ moduleId: ${JSON.stringify(moduleId)}
93
92
  };\n`
94
93
 
95
- let bindResult
96
-
97
- try {
98
- bindResult = bindThis(rawCode, {
99
- needCollect: true,
100
- ignoreMap: meta.wxsModuleMap
101
- })
102
- } catch (e) {
103
- error(`
94
+ const rawCode = compiler.genNode(ast)
95
+ if (rawCode) {
96
+ const renderCode = `
97
+ global.currentInject.render = function (_i, _c, _r, _sc) {
98
+ ${rawCode}
99
+ _r();
100
+ };\n`
101
+ try {
102
+ const bindResult = bindThis(renderCode, {
103
+ needCollect: true,
104
+ renderReduce: matchCondition(resourcePath, optimizeRenderRules),
105
+ ignoreMap: Object.assign({
106
+ _i: true,
107
+ _c: true,
108
+ _r: true
109
+ }, meta.wxsModuleMap)
110
+ })
111
+ resultSource += bindResult.code
112
+ if ((mode === 'tt' || mode === 'swan') && bindResult.propKeys) {
113
+ resultSource += `global.currentInject.propKeys = ${JSON.stringify(bindResult.propKeys)};\n`
114
+ }
115
+ } catch (e) {
116
+ error(`
104
117
  Invalid render function generated by the template, please check!\n
105
118
  Template result:
106
119
  ${result}\n
107
120
  Error code:
108
- ${rawCode}
121
+ ${renderCode}
109
122
  Error Detail:
110
123
  ${e.stack}`)
111
- return result
112
- }
113
-
114
- resultSource += bindResult.code + '\n'
115
-
116
- if ((mode === 'tt' || mode === 'swan') && bindResult.propKeys) {
117
- resultSource += `global.currentInject.propKeys = ${JSON.stringify(bindResult.propKeys)};\n`
124
+ return result
125
+ }
118
126
  }
119
127
 
120
128
  if (meta.computed) {
@@ -131,6 +139,10 @@ global.currentInject.getRefsData = function () {
131
139
  };\n`
132
140
  }
133
141
 
142
+ if (meta.options) {
143
+ resultSource += `global.currentInject.injectOptions = ${JSON.stringify(meta.options)};` + '\n'
144
+ }
145
+
134
146
  this.emitFile(resourcePath, '', undefined, {
135
147
  skipEmit: true,
136
148
  extractedResultSource: resultSource