@mpxjs/webpack-plugin 2.9.14 → 2.9.15

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/index.js CHANGED
@@ -169,7 +169,7 @@ class MpxWebpackPlugin {
169
169
  options.webConfig = options.webConfig || {}
170
170
  options.partialCompile = options.mode !== 'web' && options.partialCompile
171
171
  options.asyncSubpackageRules = options.asyncSubpackageRules || []
172
- options.optimizeRenderRules = options.optimizeRenderRules || {}
172
+ options.optimizeRenderRules = options.optimizeRenderRules ? (Array.isArray(options.optimizeRenderRules) ? options.optimizeRenderRules : [options.optimizeRenderRules]) : []
173
173
  options.retryRequireAsync = options.retryRequireAsync || false
174
174
  options.enableAliRequireAsync = options.enableAliRequireAsync || false
175
175
  options.optimizeSize = options.optimizeSize || false
@@ -102,7 +102,7 @@
102
102
  let asyncCallback = null
103
103
  switch (data.type) {
104
104
  case 'postMessage':
105
- this.messageList.push(value)
105
+ this.messageList.push(value.data || value)
106
106
  asyncCallback = Promise.resolve({
107
107
  errMsg: 'invokeWebappApi:ok'
108
108
  })
@@ -32,7 +32,7 @@ function checkBindThis (path) {
32
32
  }
33
33
 
34
34
  // 计算访问路径
35
- function calPropName (path) {
35
+ function getCollectPath (path) {
36
36
  let current = path.parentPath
37
37
  let last = path
38
38
  let keyPath = '' + path.node.name
@@ -75,7 +75,7 @@ function checkDelAndGetPath (path) {
75
75
  let replace = false
76
76
 
77
77
  // 确定删除路径
78
- while (!t.isBlockStatement(current)) {
78
+ while (!t.isBlockStatement(current) && !t.isProgram(current)) {
79
79
  // case: !!a
80
80
  if (t.isUnaryExpression(current.parent) && current.key === 'argument') {
81
81
  delPath = current.parentPath
@@ -113,7 +113,7 @@ function checkDelAndGetPath (path) {
113
113
  }
114
114
 
115
115
  // 确定是否可删除
116
- while (!t.isBlockStatement(current) && canDel) {
116
+ while (!t.isBlockStatement(current) && !t.isProgram(current)) {
117
117
  const { key, listKey, parent } = current
118
118
 
119
119
  if (t.isIfStatement(parent) && key === 'test') {
@@ -121,12 +121,12 @@ function checkDelAndGetPath (path) {
121
121
  break
122
122
  }
123
123
 
124
- if (listKey === 'arguments' && t.isCallExpression(parent)) {
124
+ if (t.isCallExpression(parent) && listKey === 'arguments') {
125
125
  canDel = false
126
126
  break
127
127
  }
128
128
 
129
- if (parent.computed && t.isMemberExpression(parent)) {
129
+ if (t.isMemberExpression(parent) && parent.computed) {
130
130
  if (key === 'property') {
131
131
  replace = true
132
132
  } else {
@@ -155,7 +155,7 @@ function checkDelAndGetPath (path) {
155
155
  replace = true // 不能break,case: if (a + b) {}
156
156
  }
157
157
 
158
- if (key === 'value' && t.isObjectProperty(parent)) { // ({ name: a })
158
+ if (t.isObjectProperty(parent) && key === 'value') { // ({ name: a })
159
159
  replace = true
160
160
  }
161
161
 
@@ -172,15 +172,16 @@ function checkDelAndGetPath (path) {
172
172
 
173
173
  // 判断前缀是否存在(只判断前缀,全等的情况,会返回false)
174
174
  function checkPrefix (keys, key) {
175
- for (let i = 0; i < keys.length; i++) {
176
- const str = keys[i]
177
- if (key === str) continue
178
- // 确保判断当前标识是完整的单词
179
- if (key.startsWith(str) && (key[str.length] === '.' || key[str.length] === '[')) return true
175
+ for (const item of keys) {
176
+ if (checkBIsPrefixOfA(key, item)) return true
180
177
  }
181
178
  return false
182
179
  }
183
180
 
181
+ function checkBIsPrefixOfA (a, b) {
182
+ return a.startsWith(b) && (a[b.length] === '.' || a[b.length] === '[')
183
+ }
184
+
184
185
  function dealRemove (path, replace) {
185
186
  try {
186
187
  if (replace) {
@@ -195,10 +196,75 @@ function dealRemove (path, replace) {
195
196
  }
196
197
  delete path.needBind
197
198
  delete path.collectInfo
198
- } catch (e) {}
199
+ } catch (e) {
200
+ }
201
+ }
202
+
203
+ function isSimpleKey (key) {
204
+ return !/[[.]/.test(key)
199
205
  }
200
206
 
201
207
  module.exports = {
208
+ transformSimple (code, {
209
+ ignoreMap = {}
210
+ }) {
211
+ const ast = babylon.parse(code, {
212
+ plugins: [
213
+ 'objectRestSpread'
214
+ ]
215
+ })
216
+ const collectKeySet = new Set()
217
+ const propKeySet = new Set()
218
+ let isProps = false
219
+ const visitor = {
220
+ // 标记收集props数据
221
+ CallExpression: {
222
+ enter (path) {
223
+ const callee = path.node.callee
224
+ if (
225
+ t.isMemberExpression(callee) &&
226
+ t.isThisExpression(callee.object) &&
227
+ (callee.property.name === '_p' || callee.property.value === '_p')
228
+ ) {
229
+ isProps = true
230
+ path.isProps = true
231
+ }
232
+ },
233
+ exit (path) {
234
+ if (path.isProps) {
235
+ isProps = false
236
+ delete path.isProps
237
+ }
238
+ }
239
+ },
240
+ Identifier (path) {
241
+ if (
242
+ checkBindThis(path) &&
243
+ !ignoreMap[path.node.name] &&
244
+ !path.scope.hasBinding(path.node.name)
245
+ ) {
246
+ if (isProps) {
247
+ propKeySet.add(path.node.name)
248
+ }
249
+ const { keyPath } = getCollectPath(path)
250
+ collectKeySet.add(keyPath)
251
+ }
252
+ }
253
+ }
254
+ traverse(ast, visitor)
255
+ const collectKeys = [...collectKeySet]
256
+ const pCollectKeys = collectKeys.filter((keyA) => {
257
+ return collectKeys.every((keyB) => {
258
+ return !checkBIsPrefixOfA(keyA, keyB)
259
+ })
260
+ })
261
+ return {
262
+ code: pCollectKeys.map((key) => {
263
+ return isSimpleKey(key) ? `_sc(${JSON.stringify(key)});` : `_c(${JSON.stringify(key)});`
264
+ }).join('\n'),
265
+ propKeys: [...propKeySet]
266
+ }
267
+ },
202
268
  transform (code, {
203
269
  needCollect = false,
204
270
  renderReduce = false,
@@ -213,22 +279,25 @@ module.exports = {
213
279
  let currentBlock = null
214
280
  const bindingsMap = new Map()
215
281
 
216
- const propKeys = []
282
+ const propKeySet = new Set()
217
283
  let isProps = false
218
284
 
219
- const collectVisitor = {
220
- BlockStatement: {
221
- enter (path) { // 收集作用域下所有变量(keyPath)
222
- bindingsMap.set(path, {
223
- parent: currentBlock,
224
- bindings: {}
225
- })
226
- currentBlock = path
227
- },
228
- exit (path) {
229
- currentBlock = bindingsMap.get(path).parent
230
- }
285
+ const blockCollectVisitor = {
286
+ enter (path) { // 收集作用域下所有变量(keyPath)
287
+ bindingsMap.set(path, {
288
+ parent: currentBlock,
289
+ bindings: {}
290
+ })
291
+ currentBlock = path
231
292
  },
293
+ exit (path) {
294
+ currentBlock = bindingsMap.get(path).parent
295
+ }
296
+ }
297
+
298
+ const collectVisitor = {
299
+ Program: blockCollectVisitor,
300
+ BlockStatement: blockCollectVisitor,
232
301
  Identifier (path) {
233
302
  if (
234
303
  checkBindThis(path) &&
@@ -248,12 +317,12 @@ module.exports = {
248
317
  }
249
318
  return
250
319
  }
251
- const { last, keyPath } = calPropName(path)
252
320
  path.needBind = true
321
+ const { last, keyPath } = getCollectPath(path)
253
322
  if (needCollect) {
254
323
  last.collectInfo = {
255
324
  key: t.stringLiteral(keyPath),
256
- isSimple: !/[[.]/.test(keyPath)
325
+ isSimple: isSimpleKey(keyPath)
257
326
  }
258
327
  }
259
328
 
@@ -281,18 +350,21 @@ module.exports = {
281
350
  }
282
351
  }
283
352
 
284
- const bindThisVisitor = {
285
- BlockStatement: {
286
- enter (path) {
287
- const scope = bindingsMap.get(path)
288
- const parentScope = bindingsMap.get(scope.parent)
289
- scope.pBindings = parentScope ? Object.assign({}, parentScope.bindings, parentScope.pBindings) : {}
290
- currentBlock = path
291
- },
292
- exit (path) {
293
- currentBlock = bindingsMap.get(path).parent
294
- }
353
+ const blockBindVisitor = {
354
+ enter (path) {
355
+ const scope = bindingsMap.get(path)
356
+ const parentScope = bindingsMap.get(scope.parent)
357
+ scope.pBindings = parentScope ? Object.assign({}, parentScope.bindings, parentScope.pBindings) : {}
358
+ currentBlock = path
295
359
  },
360
+ exit (path) {
361
+ currentBlock = bindingsMap.get(path).parent
362
+ }
363
+ }
364
+
365
+ const bindVisitor = {
366
+ Program: blockBindVisitor,
367
+ BlockStatement: blockBindVisitor,
296
368
  // 标记收集props数据
297
369
  CallExpression: {
298
370
  enter (path) {
@@ -350,7 +422,7 @@ module.exports = {
350
422
  const name = path.node.name
351
423
  if (name) { // 确保path没有被删除 且 没有被替换成字符串
352
424
  if (isProps) {
353
- propKeys.push(name)
425
+ propKeySet.add(name)
354
426
  }
355
427
  path.replaceWith(t.memberExpression(t.thisExpression(), path.node))
356
428
  }
@@ -373,11 +445,11 @@ module.exports = {
373
445
  }
374
446
 
375
447
  traverse(ast, collectVisitor)
376
- traverse(ast, bindThisVisitor)
448
+ traverse(ast, bindVisitor)
377
449
 
378
450
  return {
379
451
  code: generate(ast).code,
380
- propKeys
452
+ propKeys: [...propKeySet]
381
453
  }
382
454
  }
383
455
  }
@@ -1933,12 +1933,17 @@ function postProcessTemplate (el) {
1933
1933
 
1934
1934
  const isValidMode = makeMap('wx,ali,swan,tt,qq,web,qa,jd,dd,tenon,noMode')
1935
1935
 
1936
+ function isValidModeP (i) {
1937
+ return isValidMode(i[0] === '_' ? i.slice(1) : i)
1938
+ }
1939
+
1936
1940
  const wrapRE = /^\((.*)\)$/
1937
1941
 
1938
1942
  function processAtMode (el) {
1939
- if (el.parent && el.parent._atModeStatus) {
1940
- el._atModeStatus = el.parent._atModeStatus
1941
- }
1943
+ // 父节点的atMode匹配状态不应该影响子节点,atMode的影响范围应该限制在当前节点本身
1944
+ // if (el.parent && el.parent._atModeStatus) {
1945
+ // el._atModeStatus = el.parent._atModeStatus
1946
+ // }
1942
1947
 
1943
1948
  const attrsListClone = cloneAttrsList(el.attrsList)
1944
1949
  attrsListClone.forEach(item => {
@@ -1972,24 +1977,31 @@ function processAtMode (el) {
1972
1977
 
1973
1978
  const modeArr = [...conditionMap.keys()]
1974
1979
 
1975
- if (modeArr.every(i => isValidMode(i))) {
1980
+ if (modeArr.every(i => isValidModeP(i))) {
1976
1981
  const attrValue = getAndRemoveAttr(el, attrName).val
1977
1982
  const replacedAttrName = attrArr.join('@')
1978
1983
  const processedAttr = { name: replacedAttrName, value: attrValue }
1979
1984
 
1980
- for (const [defineMode, defineEnvArr] of conditionMap.entries()) {
1985
+ for (let [defineMode, defineEnvArr] of conditionMap.entries()) {
1986
+ const isImplicitMode = defineMode[0] === '_'
1987
+ if (isImplicitMode) defineMode = defineMode.slice(1)
1981
1988
  if (defineMode === 'noMode' || defineMode === mode) {
1982
1989
  // 命中 env 规则(没有定义env 或者定义的envArr包含当前env)
1983
1990
  if (!defineEnvArr.length || defineEnvArr.includes(env)) {
1984
- el._atModeStatus = ''
1985
1991
  if (!replacedAttrName) {
1986
- // defineMode noMode,则不论是element,还是attr,都需要经过规则转换
1987
- if (defineMode !== 'noMode') {
1992
+ if (defineMode === 'noMode' || isImplicitMode) {
1993
+ // defineMode noMode 或 implicitMode,则 element 都需要进行规则转换
1994
+ } else {
1988
1995
  el._atModeStatus = 'match'
1989
1996
  }
1990
1997
  } else {
1991
- // 如果命中了指定的mode,则先存在el上,等跑完转换后再挂回去
1992
- el.noTransAttrs ? el.noTransAttrs.push(processedAttr) : el.noTransAttrs = [processedAttr]
1998
+ if (defineMode === 'noMode' || isImplicitMode) {
1999
+ // 若defineMode noMode implicitMode,则直接将 attr 挂载回 el,进行规则转换
2000
+ addAttrs(el, [processedAttr])
2001
+ } else {
2002
+ // 如果命中了指定的mode,且当前 mode 不为 noMode 或 implicitMode,则把不需要转换的 attrs 暂存在 noTransAttrs 上,等规则转换后再挂载回去
2003
+ el.noTransAttrs ? el.noTransAttrs.push(processedAttr) : el.noTransAttrs = [processedAttr]
2004
+ }
1993
2005
  }
1994
2006
  // 命中mode,命中env,完成匹配,直接退出
1995
2007
  break
@@ -1,5 +1,5 @@
1
1
  const compiler = require('./compiler')
2
- const bindThis = require('./bind-this').transform
2
+ 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')
@@ -29,6 +29,13 @@ module.exports = function (raw) {
29
29
  const hasScoped = queryObj.hasScoped
30
30
  const moduleId = queryObj.moduleId || 'm' + mpx.pathHash(resourcePath)
31
31
 
32
+ let optimizeRenderLevel = 0
33
+ for (const rule of optimizeRenderRules) {
34
+ if (matchCondition(resourcePath, rule)) {
35
+ optimizeRenderLevel = rule.level || 1
36
+ break
37
+ }
38
+ }
32
39
  const warn = (msg) => {
33
40
  this.emitWarning(
34
41
  new Error('[template compiler][' + this.resource + ']: ' + msg)
@@ -93,22 +100,27 @@ global.currentInject = {
93
100
 
94
101
  const rawCode = compiler.genNode(ast)
95
102
  if (rawCode) {
96
- const renderCode = `
103
+ try {
104
+ const ignoreMap = Object.assign({
105
+ _i: true,
106
+ _c: true,
107
+ _sc: true,
108
+ _r: true
109
+ }, meta.wxsModuleMap)
110
+ const bindResult = optimizeRenderLevel === 2
111
+ ? bindThis.transformSimple(rawCode, {
112
+ ignoreMap
113
+ })
114
+ : bindThis.transform(rawCode, {
115
+ needCollect: true,
116
+ renderReduce: optimizeRenderLevel === 1,
117
+ ignoreMap
118
+ })
119
+ resultSource += `
97
120
  global.currentInject.render = function (_i, _c, _r, _sc) {
98
- ${rawCode}
99
- _r();
121
+ ${bindResult.code}
122
+ _r(${optimizeRenderLevel === 2 ? 'true' : ''});
100
123
  };\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
124
  if ((mode === 'tt' || mode === 'swan') && bindResult.propKeys) {
113
125
  resultSource += `global.currentInject.propKeys = ${JSON.stringify(bindResult.propKeys)};\n`
114
126
  }
@@ -118,7 +130,7 @@ Invalid render function generated by the template, please check!\n
118
130
  Template result:
119
131
  ${result}\n
120
132
  Error code:
121
- ${renderCode}
133
+ ${rawCode}
122
134
  Error Detail:
123
135
  ${e.stack}`)
124
136
  return result
@@ -126,7 +138,7 @@ ${e.stack}`)
126
138
  }
127
139
 
128
140
  if (meta.computed) {
129
- resultSource += bindThis(`
141
+ resultSource += bindThis.transform(`
130
142
  global.currentInject.injectComputed = {
131
143
  ${meta.computed.join(',')}
132
144
  };`).code + '\n'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpxjs/webpack-plugin",
3
- "version": "2.9.14",
3
+ "version": "2.9.15",
4
4
  "description": "mpx compile core",
5
5
  "keywords": [
6
6
  "mpx"
@@ -83,5 +83,5 @@
83
83
  "engines": {
84
84
  "node": ">=14.14.0"
85
85
  },
86
- "gitHead": "e8ab845a544d2db0619a6a7d6c04d9d384d1a6ca"
86
+ "gitHead": "f3dcf3425dc3e0ad2378b2f35ca020aa9cdd1fb2"
87
87
  }