@mpxjs/webpack-plugin 2.7.50-alpha.2 → 2.7.50

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.
@@ -68,24 +68,35 @@ class DynamicEntryDependency extends NullDependency {
68
68
  // export类型的resultPath需要添加.js后缀
69
69
  if (entryType === 'export') resultPath += '.js'
70
70
 
71
- if (alreadyOutputted) return callback(null, { resultPath })
72
-
73
71
  // 对于常规js模块不应添加packageRoot避免冗余
74
72
  if (packageRoot && entryType !== 'export') {
75
73
  resource = addQuery(resource, { packageRoot }, true)
76
74
  }
77
75
 
78
- mpx.addEntry(resource, filename, (err, entryModule) => {
79
- if (err) return callback(err)
80
- if (entryType === 'export') {
81
- mpx.exportModules.add(entryModule)
82
- }
83
- originEntryNode.addChild(mpx.getEntryNode(entryModule, entryType))
84
- return callback(null, {
85
- resultPath,
86
- entryModule
76
+ const key = resource + filename
77
+ let addEntryPromise
78
+
79
+ if (alreadyOutputted) {
80
+ addEntryPromise = mpx.addEntryPromiseMap.get(key) || Promise.resolve()
81
+ } else {
82
+ addEntryPromise = new Promise((resolve, reject) => {
83
+ mpx.addEntry(resource, filename, (err, entryModule) => {
84
+ if (err) return reject(err)
85
+ if (entryType === 'export') {
86
+ mpx.exportModules.add(entryModule)
87
+ }
88
+ resolve(entryModule)
89
+ })
87
90
  })
88
- })
91
+ mpx.addEntryPromiseMap.set(key, addEntryPromise)
92
+ }
93
+
94
+ addEntryPromise
95
+ .then(entryModule => {
96
+ if (entryModule) originEntryNode.addChild(mpx.getEntryNode(entryModule, entryType))
97
+ callback(null, { resultPath })
98
+ })
99
+ .catch(err => callback(err))
89
100
  }
90
101
  ], callback)
91
102
  }
@@ -0,0 +1,43 @@
1
+ const NullDependency = require('webpack/lib/dependencies/NullDependency')
2
+ const makeSerializable = require('webpack/lib/util/makeSerializable')
3
+
4
+ class RecordVueContentDependency extends NullDependency {
5
+ constructor (resourcePath, content) {
6
+ super()
7
+ this.resourcePath = resourcePath
8
+ this.content = content
9
+ }
10
+
11
+ get type () {
12
+ return 'mpx record vue content'
13
+ }
14
+
15
+ mpxAction (module, compilation, callback) {
16
+ const mpx = compilation.__mpx__
17
+ mpx.vueContentCache.set(this.resourcePath, this.content)
18
+ return callback()
19
+ }
20
+
21
+ serialize (context) {
22
+ const { write } = context
23
+ write(this.resourcePath)
24
+ write(this.content)
25
+ super.serialize(context)
26
+ }
27
+
28
+ deserialize (context) {
29
+ const { read } = context
30
+ this.resourcePath = read()
31
+ this.content = read()
32
+ super.deserialize(context)
33
+ }
34
+ }
35
+
36
+ RecordVueContentDependency.Template = class RecordVueContentDependencyTemplate {
37
+ apply () {
38
+ }
39
+ }
40
+
41
+ makeSerializable(RecordVueContentDependency, '@mpxjs/webpack-plugin/lib/dependencies/RecordVueContentDependency')
42
+
43
+ module.exports = RecordVueContentDependency
package/lib/index.js CHANGED
@@ -35,6 +35,7 @@ const RecordIndependentDependency = require('./dependencies/RecordIndependentDep
35
35
  const DynamicEntryDependency = require('./dependencies/DynamicEntryDependency')
36
36
  const FlagPluginDependency = require('./dependencies/FlagPluginDependency')
37
37
  const RemoveEntryDependency = require('./dependencies/RemoveEntryDependency')
38
+ const RecordVueContentDependency = require('./dependencies/RecordVueContentDependency')
38
39
  const SplitChunksPlugin = require('webpack/lib/optimize/SplitChunksPlugin')
39
40
  const PartialCompilePlugin = require('./partial-compile/index')
40
41
  const fixRelative = require('./utils/fix-relative')
@@ -498,6 +499,9 @@ class MpxWebpackPlugin {
498
499
 
499
500
  compilation.dependencyFactories.set(CommonJsAsyncDependency, normalModuleFactory)
500
501
  compilation.dependencyTemplates.set(CommonJsAsyncDependency, new CommonJsAsyncDependency.Template())
502
+
503
+ compilation.dependencyFactories.set(RecordVueContentDependency, new NullFactory())
504
+ compilation.dependencyTemplates.set(RecordVueContentDependency, new RecordVueContentDependency.Template())
501
505
  })
502
506
 
503
507
  compiler.hooks.thisCompilation.tap('MpxWebpackPlugin', (compilation, { normalModuleFactory }) => {
@@ -539,6 +543,7 @@ class MpxWebpackPlugin {
539
543
  usingComponents: {},
540
544
  // todo es6 map读写性能高于object,之后会逐步替换
541
545
  wxsAssetsCache: new Map(),
546
+ addEntryPromiseMap: new Map(),
542
547
  currentPackageRoot: '',
543
548
  wxsContentMap: {},
544
549
  forceUsePageCtor: this.options.forceUsePageCtor,
@@ -557,6 +562,7 @@ class MpxWebpackPlugin {
557
562
  nativeConfig: this.options.nativeConfig,
558
563
  // 输出web专用配置
559
564
  webConfig: this.options.webConfig,
565
+ vueContentCache: new Map(),
560
566
  tabBarMap: {},
561
567
  defs: preProcessDefs(this.options.defs),
562
568
  i18n: this.options.i18n,
package/lib/loader.js CHANGED
@@ -16,6 +16,7 @@ const normalize = require('./utils/normalize')
16
16
  const getEntryName = require('./utils/get-entry-name')
17
17
  const AppEntryDependency = require('./dependencies/AppEntryDependency')
18
18
  const RecordResourceMapDependency = require('./dependencies/RecordResourceMapDependency')
19
+ const RecordVueContentDependency = require('./dependencies/RecordVueContentDependency')
19
20
  const CommonJsVariableDependency = require('./dependencies/CommonJsVariableDependency')
20
21
  const { MPX_APP_MODULE_ID } = require('./utils/const')
21
22
  const path = require('path')
@@ -137,6 +138,10 @@ module.exports = function (content) {
137
138
  return callback(null, output)
138
139
  }
139
140
 
141
+ // 通过RecordVueContentDependency和vueContentCache确保子request不再重复生成vueContent
142
+ const cacheContent = mpx.vueContentCache.get(filePath)
143
+ if (cacheContent) return callback(null, cacheContent)
144
+
140
145
  return async.waterfall([
141
146
  (callback) => {
142
147
  async.parallel([
@@ -183,6 +188,7 @@ module.exports = function (content) {
183
188
  loaderContext,
184
189
  ctorType,
185
190
  srcMode,
191
+ moduleId,
186
192
  isProduction,
187
193
  componentGenerics,
188
194
  jsonConfig: jsonRes.jsonObj,
@@ -199,6 +205,7 @@ module.exports = function (content) {
199
205
  ], (err, scriptRes) => {
200
206
  if (err) return callback(err)
201
207
  output += scriptRes.output
208
+ this._module.addPresentationalDependency(new RecordVueContentDependency(filePath, output))
202
209
  callback(null, output)
203
210
  })
204
211
  }
@@ -265,10 +272,9 @@ module.exports = function (content) {
265
272
 
266
273
  if (template) {
267
274
  const extraOptions = {
268
- ...template.src ? {
269
- ...queryObj,
270
- resourcePath
271
- } : null,
275
+ ...template.src
276
+ ? { ...queryObj, resourcePath }
277
+ : null,
272
278
  hasScoped,
273
279
  hasComment,
274
280
  isNative,
@@ -290,11 +296,9 @@ module.exports = function (content) {
290
296
  const scoped = style.scoped || autoScope
291
297
  const extraOptions = {
292
298
  // style src会被特殊处理为全局复用样式,不添加resourcePath,添加isStatic及issuerFile
293
- ...style.src ? {
294
- ...queryObj,
295
- isStatic: true,
296
- issuerResource: addQuery(this.resource, { type: 'styles' }, true)
297
- } : null,
299
+ ...style.src
300
+ ? { ...queryObj, isStatic: true, issuerResource: addQuery(this.resource, { type: 'styles' }, true) }
301
+ : null,
298
302
  moduleId,
299
303
  scoped
300
304
  }
@@ -311,10 +315,7 @@ module.exports = function (content) {
311
315
  output += '/* json */\n'
312
316
  // 给予json默认值, 确保生成json request以自动补全json
313
317
  const json = parts.json || {}
314
- output += getRequire('json', json, json.src && {
315
- ...queryObj,
316
- resourcePath
317
- }) + '\n'
318
+ output += getRequire('json', json, json.src && { ...queryObj, resourcePath }) + '\n'
318
319
 
319
320
  // script
320
321
  output += '/* script */\n'
@@ -326,10 +327,9 @@ module.exports = function (content) {
326
327
  if (scriptSrcMode) output += `global.currentSrcMode = ${JSON.stringify(scriptSrcMode)}\n`
327
328
  // 传递ctorType以补全js内容
328
329
  const extraOptions = {
329
- ...script.src ? {
330
- ...queryObj,
331
- resourcePath
332
- } : null,
330
+ ...script.src
331
+ ? { ...queryObj, resourcePath }
332
+ : null,
333
333
  ctorType
334
334
  }
335
335
  output += getRequire('script', script, extraOptions) + '\n'
@@ -1989,11 +1989,12 @@ function processAtMode (el) {
1989
1989
  return
1990
1990
  }
1991
1991
 
1992
- const conditionMap = new Map()
1992
+ const conditionMap = {}
1993
+
1993
1994
  modeStr.split('|').forEach(item => {
1994
1995
  const arr = item.split(':')
1995
- const key = arr[0] || 'noMode'
1996
- conditionMap.set(key, arr.slice(1))
1996
+ const key = arr[0] || mode
1997
+ conditionMap[key] = arr.slice(1)
1997
1998
  })
1998
1999
 
1999
2000
  const modeArr = Object.keys(conditionMap)
@@ -2001,33 +2002,19 @@ function processAtMode (el) {
2001
2002
  if (modeArr.every(i => isValidMode(i))) {
2002
2003
  const attrValue = getAndRemoveAttr(el, attrName).val
2003
2004
  const replacedAttrName = attrArr.join('@')
2004
- const processedAttr = { name: replacedAttrName, value: attrValue }
2005
2005
 
2006
- for (let [defineMode, defineEnvArr] of conditionMap.entries()) {
2007
- if (defineMode === 'noMode' || defineMode === mode) {
2008
- // 命中 env 规则(没有定义env 或者定义的envArr包含当前env)
2009
- if (!defineEnvArr.length || defineEnvArr.includes(env)) {
2010
- if (!replacedAttrName) {
2011
- // 若defineMode 为 noMode,则不论是element,还是attr,都需要经过规则转换
2012
- if (defineMode !== 'noMode') {
2013
- el._atModeStatus = 'match'
2014
- }
2015
- } else {
2016
- // 如果命中了指定的mode,则先存在el上,等跑完转换后再挂回去
2017
- el.noTransAttrs ? el.noTransAttrs.push(processedAttr) : el.noTransAttrs = [processedAttr]
2018
- }
2019
- // 命中mode,命中env,完成匹配,直接退出
2020
- break
2021
- } else if (!replacedAttrName) {
2022
- // 命中mode规则,没有命中当前env规则,设置为 'mismatch'
2023
- el._atModeStatus = 'mismatch'
2024
- }
2025
- } else if (!replacedAttrName) {
2026
- // 没有命中当前mode规则,设置为 'mismatch'
2027
- el._atModeStatus = 'mismatch'
2006
+ const processedAttr = { name: replacedAttrName, value: attrValue }
2007
+ if (modeArr.includes(mode) && (!conditionMap[mode].length || conditionMap[mode].includes(env))) {
2008
+ if (!replacedAttrName) {
2009
+ el._atModeStatus = 'match'
2028
2010
  } else {
2029
- // 如果没命中指定的mode,则该属性删除
2011
+ // 如果命中了指定的mode,则先存在el上,等跑完转换后再挂回去
2012
+ el.noTransAttrs ? el.noTransAttrs.push(processedAttr) : el.noTransAttrs = [processedAttr]
2030
2013
  }
2014
+ } else if (!replacedAttrName) {
2015
+ el._atModeStatus = 'mismatch'
2016
+ } else {
2017
+ // 如果没命中指定的mode,则该属性删除
2031
2018
  }
2032
2019
  }
2033
2020
  })
@@ -2,7 +2,7 @@ const genComponentTag = require('../utils/gen-component-tag')
2
2
  const loaderUtils = require('loader-utils')
3
3
  const addQuery = require('../utils/add-query')
4
4
  const normalize = require('../utils/normalize')
5
- const parseRequest = require('../utils/parse-request')
5
+ const createHelpers = require('../helpers')
6
6
  const optionProcessorPath = normalize.lib('runtime/optionProcessor')
7
7
  const tabBarContainerPath = normalize.lib('runtime/components/web/mpx-tab-bar-container.vue')
8
8
  const tabBarPath = normalize.lib('runtime/components/web/mpx-tab-bar.vue')
@@ -32,6 +32,7 @@ module.exports = function (script, {
32
32
  loaderContext,
33
33
  ctorType,
34
34
  srcMode,
35
+ moduleId,
35
36
  isProduction,
36
37
  componentGenerics,
37
38
  jsonConfig,
@@ -44,13 +45,13 @@ module.exports = function (script, {
44
45
  localComponentsMap,
45
46
  localPagesMap
46
47
  }, callback) {
47
- const mpx = loaderContext.getMpx()
48
48
  const {
49
49
  i18n,
50
- projectRoot
51
- } = mpx
50
+ projectRoot,
51
+ webConfig
52
+ } = loaderContext.getMpx()
52
53
 
53
- const { queryObj } = parseRequest(loaderContext.resource)
54
+ const { getRequire } = createHelpers(loaderContext)
54
55
  const tabBar = jsonConfig.tabBar
55
56
 
56
57
  const emitWarning = (msg) => {
@@ -87,23 +88,7 @@ module.exports = function (script, {
87
88
  if (script) {
88
89
  scriptSrcMode = script.mode || scriptSrcMode
89
90
  } else {
90
- script = {
91
- tag: 'script',
92
- content: ''
93
- }
94
- switch (ctorType) {
95
- case 'app':
96
- script.content = 'import {createApp} from "@mpxjs/core"\n' +
97
- 'createApp({})\n'
98
- break
99
- case 'page':
100
- script.content = 'import {createPage} from "@mpxjs/core"\n' +
101
- 'createPage({})\n'
102
- break
103
- case 'component':
104
- script.content = 'import {createComponent} from "@mpxjs/core"\n' +
105
- 'createComponent({})\n'
106
- }
91
+ script = { tag: 'script' }
107
92
  }
108
93
  output += genComponentTag(script, {
109
94
  attrs (script) {
@@ -138,9 +123,10 @@ module.exports = function (script, {
138
123
  }
139
124
  global.__networkTimeout = ${JSON.stringify(jsonConfig.networkTimeout)}
140
125
  global.__mpxGenericsMap = {}
126
+ global.__mpxOptionsMap = {}
141
127
  global.__style = ${JSON.stringify(jsonConfig.style || 'v1')}
142
128
  global.__mpxPageConfig = ${JSON.stringify(jsonConfig.window)}
143
- global.__mpxTransRpxFn = ${mpx.webConfig.transRpxFn}\n`
129
+ global.__mpxTransRpxFn = ${webConfig.transRpxFn}\n`
144
130
  if (i18n) {
145
131
  const i18nObj = Object.assign({}, i18n)
146
132
  content += ` import VueI18n from 'vue-i18n'
@@ -214,19 +200,23 @@ module.exports = function (script, {
214
200
  componentsMap[componentName] = `getComponent(require(${componentRequest}), { __mpxBuiltIn: true })`
215
201
  })
216
202
 
203
+ content += ` global.currentModuleId = ${JSON.stringify(moduleId)}\n`
217
204
  content += ` global.currentSrcMode = ${JSON.stringify(scriptSrcMode)}\n`
218
205
  if (!isProduction) {
219
206
  content += ` global.currentResource = ${JSON.stringify(loaderContext.resourcePath)}\n`
220
207
  }
221
- // 为了正确获取currentSrcMode便于运行时进行转换,对于src引入的组件script采用require方式引入(由于webpack会将import的执行顺序上升至最顶),这意味着对于src引入脚本中的named export将不会生效,不过鉴于mpx和小程序中本身也没有在组件script中声明export的用法,所以应该没有影响
222
- content += '\n\n\n/** Source start **/\n'
223
- content += script.src
224
- // 继承单文件组件query避免多个单文件模块实例引用一个src模块,因模块缓存导致createComponent不执行的问题
225
- ? `require(${stringifyRequest(addQuery(script.src, queryObj))})\n`
226
- : script.content
227
- content += '\n/** Source end **/\n\n\n'
208
+
209
+ content += ' /** script content **/\n'
210
+
211
+ // 传递ctorType以补全js内容
212
+ const extraOptions = {
213
+ ctorType
214
+ }
215
+ // todo 仅靠vueContentCache保障模块唯一性还是不够严谨,后续需要考虑去除原始query后构建request
216
+ content += ` ${getRequire('script', script, extraOptions)}\n`
217
+
228
218
  // createApp/Page/Component执行完成后立刻获取当前的option并暂存
229
- content += ` const currentOption = global.currentOption\n`
219
+ content += ` const currentOption = global.__mpxOptionsMap[${JSON.stringify(moduleId)}]\n`
230
220
  // 获取pageConfig
231
221
  const pageConfig = {}
232
222
  if (ctorType === 'page') {
@@ -265,7 +255,6 @@ module.exports = function (script, {
265
255
  ${JSON.stringify(componentGenerics)},
266
256
  ${JSON.stringify(genericsInfo)},
267
257
  getWxsMixin(wxsModules)`
268
-
269
258
  if (ctorType === 'app') {
270
259
  content += `,
271
260
  Vue,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpxjs/webpack-plugin",
3
- "version": "2.7.50-alpha.2",
3
+ "version": "2.7.50",
4
4
  "description": "mpx compile core",
5
5
  "keywords": [
6
6
  "mpx"
@@ -80,5 +80,5 @@
80
80
  "engines": {
81
81
  "node": ">=14.14.0"
82
82
  },
83
- "gitHead": "1f11736feeec1ad1eace01c32f8b70b296a6896b"
83
+ "gitHead": "f1fe0f7381ee7e153b0eb7994f25ade5c9f4f0ef"
84
84
  }