@mpxjs/webpack-plugin 2.7.0-beta.1 → 2.7.0-beta.10

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 (48) hide show
  1. package/lib/dependencies/CommonJsVariableDependency.js +2 -7
  2. package/lib/dependencies/DynamicEntryDependency.js +5 -1
  3. package/lib/dependencies/{RecordStaticResourceDependency.js → RecordResourceMapDependency.js} +12 -7
  4. package/lib/dependencies/RemoveEntryDependency.js +40 -0
  5. package/lib/dependencies/ResolveDependency.js +8 -7
  6. package/lib/extractor.js +3 -2
  7. package/lib/file-loader.js +2 -2
  8. package/lib/helpers.js +1 -0
  9. package/lib/index.js +171 -127
  10. package/lib/json-compiler/helper.js +21 -25
  11. package/lib/json-compiler/index.js +68 -53
  12. package/lib/json-compiler/plugin.js +21 -5
  13. package/lib/loader.js +42 -54
  14. package/lib/native-loader.js +28 -65
  15. package/lib/parser.js +1 -2
  16. package/lib/platform/json/wx/index.js +7 -2
  17. package/lib/platform/template/wx/component-config/button.js +3 -3
  18. package/lib/platform/template/wx/component-config/navigator.js +1 -1
  19. package/lib/record-loader.js +2 -2
  20. package/lib/resolver/AddEnvPlugin.js +3 -2
  21. package/lib/resolver/AddModePlugin.js +3 -2
  22. package/lib/runtime/base.styl +5 -0
  23. package/lib/runtime/components/web/getInnerListeners.js +51 -45
  24. package/lib/runtime/components/web/mpx-keep-alive.vue +4 -1
  25. package/lib/runtime/components/web/mpx-tab-bar-container.vue +2 -2
  26. package/lib/runtime/optionProcessor.js +5 -20
  27. package/lib/runtime/stringify.wxs +3 -3
  28. package/lib/selector.js +3 -6
  29. package/lib/style-compiler/index.js +4 -5
  30. package/lib/template-compiler/bind-this.js +4 -4
  31. package/lib/template-compiler/compiler.js +105 -45
  32. package/lib/template-compiler/index.js +3 -6
  33. package/lib/template-compiler/trans-dynamic-class-expr.js +3 -3
  34. package/lib/utils/const.js +5 -1
  35. package/lib/utils/eval-json-js.js +31 -0
  36. package/lib/utils/get-json-content.js +41 -0
  37. package/lib/utils/resolve.js +13 -0
  38. package/lib/web/processJSON.js +113 -142
  39. package/lib/web/processScript.js +30 -24
  40. package/lib/web/processTemplate.js +56 -40
  41. package/lib/wxs/i18n-loader.js +1 -3
  42. package/lib/wxs/loader.js +24 -27
  43. package/lib/wxs/pre-loader.js +7 -8
  44. package/lib/wxss/processCss.js +44 -44
  45. package/package.json +8 -8
  46. package/lib/built-in-loader.js +0 -49
  47. package/lib/utils/get-main-compilation.js +0 -6
  48. package/lib/utils/read-json-for-src.js +0 -34
package/lib/index.js CHANGED
@@ -24,10 +24,11 @@ const PackageEntryPlugin = require('./resolver/PackageEntryPlugin')
24
24
  // const RequireHeaderDependency = require('webpack/lib/dependencies/RequireHeaderDependency')
25
25
  // const RemovedModuleDependency = require('./dependencies/RemovedModuleDependency')
26
26
  const AppEntryDependency = require('./dependencies/AppEntryDependency')
27
- const RecordStaticResourceDependency = require('./dependencies/RecordStaticResourceDependency')
27
+ const RecordResourceMapDependency = require('./dependencies/RecordResourceMapDependency')
28
28
  const RecordGlobalComponentsDependency = require('./dependencies/RecordGlobalComponentsDependency')
29
29
  const DynamicEntryDependency = require('./dependencies/DynamicEntryDependency')
30
30
  const FlagPluginDependency = require('./dependencies/FlagPluginDependency')
31
+ const RemoveEntryDependency = require('./dependencies/RemoveEntryDependency')
31
32
  const SplitChunksPlugin = require('webpack/lib/optimize/SplitChunksPlugin')
32
33
  const fixRelative = require('./utils/fix-relative')
33
34
  const parseRequest = require('./utils/parse-request')
@@ -48,6 +49,7 @@ const async = require('async')
48
49
  const stringifyLoadersAndResource = require('./utils/stringify-loaders-resource')
49
50
  const emitFile = require('./utils/emit-file')
50
51
  const { MPX_PROCESSED_FLAG, MPX_DISABLE_EXTRACTOR_CACHE } = require('./utils/const')
52
+ const isEmptyObject = require('./utils/is-empty-object')
51
53
 
52
54
  const isProductionLikeMode = options => {
53
55
  return options.mode === 'production' || !options.mode
@@ -78,6 +80,11 @@ const isChunkInPackage = (chunkName, packageName) => {
78
80
  const getPackageCacheGroup = packageName => {
79
81
  if (packageName === 'main') {
80
82
  return {
83
+ // 对于独立分包模块不应用该cacheGroup
84
+ test: (module) => {
85
+ const { queryObj } = parseRequest(module.resource)
86
+ return !queryObj.isIndependent
87
+ },
81
88
  name: 'bundle',
82
89
  minChunks: 2,
83
90
  chunks: 'all'
@@ -106,20 +113,20 @@ const externalsMap = {
106
113
  const warnings = []
107
114
  const errors = []
108
115
 
109
- class EntryNode {
110
- constructor (options) {
111
- this.request = options.request
112
- this.type = options.type
113
- this.module = null
114
- this.parents = new Set()
115
- this.children = new Set()
116
- }
117
-
118
- addChild (node) {
119
- this.children.add(node)
120
- node.parents.add(this)
121
- }
122
- }
116
+ // class EntryNode {
117
+ // constructor (options) {
118
+ // this.request = options.request
119
+ // this.type = options.type
120
+ // this.module = null
121
+ // this.parents = new Set()
122
+ // this.children = new Set()
123
+ // }
124
+ //
125
+ // addChild (node) {
126
+ // this.children.add(node)
127
+ // node.parents.add(this)
128
+ // }
129
+ // }
123
130
 
124
131
  class MpxWebpackPlugin {
125
132
  constructor (options = {}) {
@@ -177,6 +184,7 @@ class MpxWebpackPlugin {
177
184
  options.fileConditionRules = options.fileConditionRules || {
178
185
  include: () => true
179
186
  }
187
+ options.customOutputPath = options.customOutputPath || null
180
188
  this.options = options
181
189
  }
182
190
 
@@ -184,35 +192,59 @@ class MpxWebpackPlugin {
184
192
  if (options.transRpx) {
185
193
  warnings.push('Mpx loader option [transRpx] is deprecated now, please use mpx webpack plugin config [transRpxRules] instead!')
186
194
  }
187
- return { loader: normalize.lib('loader'), options }
195
+ return {
196
+ loader: normalize.lib('loader'),
197
+ options
198
+ }
188
199
  }
189
200
 
190
201
  static nativeLoader (options = {}) {
191
- return { loader: normalize.lib('native-loader'), options }
202
+ return {
203
+ loader: normalize.lib('native-loader'),
204
+ options
205
+ }
192
206
  }
193
207
 
194
208
  static wxssLoader (options) {
195
- return { loader: normalize.lib('wxss/loader'), options }
209
+ return {
210
+ loader: normalize.lib('wxss/loader'),
211
+ options
212
+ }
196
213
  }
197
214
 
198
215
  static wxmlLoader (options) {
199
- return { loader: normalize.lib('wxml/loader'), options }
216
+ return {
217
+ loader: normalize.lib('wxml/loader'),
218
+ options
219
+ }
200
220
  }
201
221
 
202
222
  static pluginLoader (options = {}) {
203
- return { loader: normalize.lib('json-compiler/plugin'), options }
223
+ return {
224
+ loader: normalize.lib('json-compiler/plugin'),
225
+ options
226
+ }
204
227
  }
205
228
 
206
229
  static wxsPreLoader (options = {}) {
207
- return { loader: normalize.lib('wxs/pre-loader'), options }
230
+ return {
231
+ loader: normalize.lib('wxs/pre-loader'),
232
+ options
233
+ }
208
234
  }
209
235
 
210
236
  static urlLoader (options = {}) {
211
- return { loader: normalize.lib('url-loader'), options }
237
+ return {
238
+ loader: normalize.lib('url-loader'),
239
+ options
240
+ }
212
241
  }
213
242
 
214
243
  static fileLoader (options = {}) {
215
- return { loader: normalize.lib('file-loader'), options }
244
+ return {
245
+ loader: normalize.lib('file-loader'),
246
+ options
247
+ }
216
248
  }
217
249
 
218
250
  runModeRules (data) {
@@ -333,18 +365,17 @@ class MpxWebpackPlugin {
333
365
 
334
366
  let mpx
335
367
 
336
- // 构建分包队列,在finishMake钩子当中最先执行,stage传递-1000
337
- compiler.hooks.finishMake.tapAsync({
338
- name: 'MpxWebpackPlugin',
339
- stage: -1000
340
- }, (compilation, callback) => {
368
+ const processSubpackagesEntriesMap = (compilation, callback) => {
341
369
  const mpx = compilation.__mpx__
342
- if (mpx && mpx.subpackagesEntriesMap) {
343
- async.eachOfSeries(mpx.subpackagesEntriesMap, (deps, packageRoot, callback) => {
370
+ if (mpx && !isEmptyObject(mpx.subpackagesEntriesMap)) {
371
+ const subpackagesEntriesMap = mpx.subpackagesEntriesMap
372
+ // 执行分包队列前清空mpx.subpackagesEntriesMap
373
+ mpx.subpackagesEntriesMap = {}
374
+ async.eachOfSeries(subpackagesEntriesMap, (deps, packageRoot, callback) => {
344
375
  mpx.currentPackageRoot = packageRoot
345
- mpx.componentsMap[packageRoot] = {}
346
- mpx.staticResourcesMap[packageRoot] = {}
347
- mpx.subpackageModulesMap[packageRoot] = {}
376
+ mpx.componentsMap[packageRoot] = mpx.componentsMap[packageRoot] || {}
377
+ mpx.staticResourcesMap[packageRoot] = mpx.staticResourcesMap[packageRoot] || {}
378
+ mpx.subpackageModulesMap[packageRoot] = mpx.subpackageModulesMap[packageRoot] || {}
348
379
  async.each(deps, (dep, callback) => {
349
380
  dep.addEntry(compilation, (err, { resultPath }) => {
350
381
  if (err) return callback(err)
@@ -352,14 +383,26 @@ class MpxWebpackPlugin {
352
383
  callback()
353
384
  })
354
385
  }, callback)
355
- }, callback)
386
+ }, (err) => {
387
+ if (err) return callback(err)
388
+ // 如果执行完当前队列后产生了新的分包执行队列(一般由异步分包组件造成),则继续执行
389
+ processSubpackagesEntriesMap(compilation, callback)
390
+ })
356
391
  } else {
357
392
  callback()
358
393
  }
394
+ }
395
+
396
+ // 构建分包队列,在finishMake钩子当中最先执行,stage传递-1000
397
+ compiler.hooks.finishMake.tapAsync({
398
+ name: 'MpxWebpackPlugin',
399
+ stage: -1000
400
+ }, (compilation, callback) => {
401
+ processSubpackagesEntriesMap(compilation, callback)
359
402
  })
360
403
 
361
404
  compiler.hooks.compilation.tap('MpxWebpackPlugin ', (compilation, { normalModuleFactory }) => {
362
- NormalModule.getCompilationHooks(compilation).loader.tap('MpxWebpackPlugin', (loaderContext, module) => {
405
+ NormalModule.getCompilationHooks(compilation).loader.tap('MpxWebpackPlugin', (loaderContext) => {
363
406
  // 设置loaderContext的minimize
364
407
  if (isProductionLikeMode(compiler.options)) {
365
408
  loaderContext.minimize = true
@@ -387,8 +430,11 @@ class MpxWebpackPlugin {
387
430
  compilation.dependencyFactories.set(FlagPluginDependency, new NullFactory())
388
431
  compilation.dependencyTemplates.set(FlagPluginDependency, new FlagPluginDependency.Template())
389
432
 
390
- compilation.dependencyFactories.set(RecordStaticResourceDependency, new NullFactory())
391
- compilation.dependencyTemplates.set(RecordStaticResourceDependency, new RecordStaticResourceDependency.Template())
433
+ compilation.dependencyFactories.set(RemoveEntryDependency, new NullFactory())
434
+ compilation.dependencyTemplates.set(RemoveEntryDependency, new RemoveEntryDependency.Template())
435
+
436
+ compilation.dependencyFactories.set(RecordResourceMapDependency, new NullFactory())
437
+ compilation.dependencyTemplates.set(RecordResourceMapDependency, new RecordResourceMapDependency.Template())
392
438
 
393
439
  compilation.dependencyFactories.set(RecordGlobalComponentsDependency, new NullFactory())
394
440
  compilation.dependencyTemplates.set(RecordGlobalComponentsDependency, new RecordGlobalComponentsDependency.Template())
@@ -436,7 +482,6 @@ class MpxWebpackPlugin {
436
482
  // todo es6 map读写性能高于object,之后会逐步替换
437
483
  vueContentCache: new Map(),
438
484
  currentPackageRoot: '',
439
- wxsMap: {},
440
485
  wxsContentMap: {},
441
486
  assetsInfo: new Map(),
442
487
  forceUsePageCtor: this.options.forceUsePageCtor,
@@ -464,25 +509,6 @@ class MpxWebpackPlugin {
464
509
  useRelativePath: this.options.useRelativePath,
465
510
  removedChunks: [],
466
511
  forceProxyEventRules: this.options.forceProxyEventRules,
467
- getEntryNode: (request, type, module) => {
468
- const entryNodesMap = mpx.entryNodesMap
469
- const entryModulesMap = mpx.entryModulesMap
470
- if (!entryNodesMap[request]) {
471
- entryNodesMap[request] = new EntryNode({
472
- type,
473
- request
474
- })
475
- }
476
- const currentEntry = entryNodesMap[request]
477
- if (currentEntry.type !== type) {
478
- compilation.errors.push(`获取request为${request}的entryNode时类型与已有节点冲突, 当前获取的type为${type}, 已有节点的type为${currentEntry.type}!`)
479
- }
480
- if (module) {
481
- currentEntry.module = module
482
- entryModulesMap.set(module, currentEntry)
483
- }
484
- return currentEntry
485
- },
486
512
  pathHash: (resourcePath) => {
487
513
  if (this.options.pathHashMode === 'relative' && this.options.projectRoot) {
488
514
  return hash(path.relative(this.options.projectRoot, resourcePath))
@@ -494,21 +520,27 @@ class MpxWebpackPlugin {
494
520
  compilation.addEntry(compiler.context, dep, { name }, callback)
495
521
  return dep
496
522
  },
523
+ getOutputPath: (resourcePath, type, { ext = '', conflictPath = '' } = {}) => {
524
+ const name = path.parse(resourcePath).name
525
+ const hash = mpx.pathHash(resourcePath)
526
+ const customOutputPath = this.options.customOutputPath
527
+ if (conflictPath) return conflictPath.replace(/(\.[^\\/]+)?$/, match => hash + match)
528
+ if (typeof customOutputPath === 'function') return customOutputPath(type, name, hash, ext)
529
+ if (type === 'component' || type === 'page') return path.join(type + 's', name + hash, 'index' + ext)
530
+ return path.join(type, name + hash + ext)
531
+ },
497
532
  extractedFilesCache: new Map(),
498
533
  getExtractedFile: (resource, { error } = {}) => {
499
534
  const cache = mpx.extractedFilesCache.get(resource)
500
535
  if (cache) return cache
501
536
  const { resourcePath, queryObj } = parseRequest(resource)
502
- const type = queryObj.type
503
- const isStatic = queryObj.isStatic
504
- const isPlugin = queryObj.isPlugin
537
+ const { type, isStatic, isPlugin } = queryObj
505
538
  let file
506
539
  if (isPlugin) {
507
540
  file = 'plugin.json'
508
541
  } else if (isStatic) {
509
542
  const packageRoot = queryObj.packageRoot || ''
510
- const resourceName = path.parse(resourcePath).name
511
- file = toPosix(path.join(packageRoot, type, resourceName + mpx.pathHash(resourcePath) + typeExtMap[type]))
543
+ file = toPosix(path.join(packageRoot, mpx.getOutputPath(resourcePath, type, { ext: typeExtMap[type] })))
512
544
  } else {
513
545
  const appInfo = mpx.appInfo
514
546
  const pagesMap = mpx.pagesMap
@@ -582,16 +614,16 @@ class MpxWebpackPlugin {
582
614
  if (currentResourceMap[resourcePath] === outputPath) {
583
615
  alreadyOutputed = true
584
616
  } else {
585
- currentResourceMap[resourcePath] = outputPath
586
- // 输出冲突检测只有page需要
587
- if (resourceType === 'page') {
588
- for (let key in currentResourceMap) {
589
- if (currentResourceMap[key] === outputPath && key !== resourcePath) {
590
- error && error(new Error(`Current ${resourceType} [${resourcePath}] registers a same output path [${outputPath}] with existed ${resourceType} [${key}], which is not allowed!`))
591
- break
592
- }
617
+ // todo 用outputPathMap来检测冲突
618
+ // 输出冲突检测,如果存在输出路径冲突,对输出路径进行重命名
619
+ for (let key in currentResourceMap) {
620
+ if (currentResourceMap[key] === outputPath && key !== resourcePath) {
621
+ outputPath = toPosix(path.join(packageRoot, mpx.getOutputPath(resourcePath, resourceType, { conflictPath: outputPath })))
622
+ warn && warn(new Error(`Current ${resourceType} [${resourcePath}] is registered with a conflict outputPath [${currentResourceMap[key]}] which is already existed in system, will be renamed with [${outputPath}], use ?resolve to get the real outputPath!`))
623
+ break
593
624
  }
594
625
  }
626
+ currentResourceMap[resourcePath] = outputPath
595
627
  }
596
628
  } else if (!currentResourceMap[resourcePath]) {
597
629
  currentResourceMap[resourcePath] = true
@@ -613,8 +645,9 @@ class MpxWebpackPlugin {
613
645
  async.forEach(presentationalDependencies.filter((dep) => dep.mpxAction), (dep, callback) => {
614
646
  dep.mpxAction(module, compilation, callback)
615
647
  }, (err) => {
616
- if (err) return callback(err)
617
- rawProcessModuleDependencies.call(compilation, module, callback)
648
+ rawProcessModuleDependencies.call(compilation, module, (innerErr) => {
649
+ return callback(err || innerErr)
650
+ })
618
651
  })
619
652
  }
620
653
 
@@ -663,10 +696,12 @@ class MpxWebpackPlugin {
663
696
  compilation.errors.push(e)
664
697
  }
665
698
  })
666
- if (packageRoot) {
667
- module.request = addQuery(module.request, { packageRoot })
668
- module.resource = addQuery(module.resource, { packageRoot })
669
- }
699
+ const queryObj = {}
700
+ if (packageRoot) queryObj.packageRoot = packageRoot
701
+ // todo 后续可以考虑用module.layer来隔离独立分包的模块
702
+ if (isIndependent) queryObj.isIndependent = true
703
+ module.request = addQuery(module.request, queryObj)
704
+ module.resource = addQuery(module.resource, queryObj)
670
705
  }
671
706
  }
672
707
 
@@ -687,17 +722,6 @@ class MpxWebpackPlugin {
687
722
  }
688
723
  })
689
724
 
690
- // todo 统一通过dep+mpx actions处理
691
- compilation.hooks.stillValidModule.tap('MpxWebpackPlugin', (module) => {
692
- const buildInfo = module.buildInfo
693
- if (buildInfo.pagesMap) {
694
- Object.assign(mpx.pagesMap, buildInfo.pagesMap)
695
- }
696
- if (buildInfo.componentsMap && buildInfo.packageName) {
697
- Object.assign(mpx.componentsMap[buildInfo.packageName], buildInfo.componentsMap)
698
- }
699
- })
700
-
701
725
  compilation.hooks.finishModules.tap('MpxWebpackPlugin', (modules) => {
702
726
  // 自动跟进分包配置修改splitChunksPlugin配置
703
727
  if (splitChunksPlugin) {
@@ -728,6 +752,14 @@ class MpxWebpackPlugin {
728
752
  return source
729
753
  })
730
754
 
755
+ JavascriptModulesPlugin.getCompilationHooks(compilation).renderStartup.tap('MpxWebpackPlugin', (source, module) => {
756
+ if (module && mpx.exportModules.has(module)) {
757
+ source = new ConcatSource(source)
758
+ source.add('module.exports = __webpack_exports__;\n')
759
+ }
760
+ return source
761
+ })
762
+
731
763
  compilation.hooks.beforeModuleAssets.tap('MpxWebpackPlugin', () => {
732
764
  const extractedAssetsMap = new Map()
733
765
  for (const module of compilation.modules) {
@@ -958,8 +990,6 @@ class MpxWebpackPlugin {
958
990
  chunkLoadingGlobal
959
991
  } = compilation.outputOptions
960
992
 
961
- const { chunkGraph } = compilation
962
-
963
993
  function getTargetFile (file) {
964
994
  let targetFile = file
965
995
  const queryStringIdx = targetFile.indexOf('?')
@@ -1025,6 +1055,7 @@ try {
1025
1055
  context.setTimeout = setTimeout;
1026
1056
  context.JSON = JSON;
1027
1057
  context.Math = Math;
1058
+ context.Date = Date;
1028
1059
  context.RegExp = RegExp;
1029
1060
  context.Infinity = Infinity;
1030
1061
  context.isFinite = isFinite;
@@ -1039,17 +1070,28 @@ try {
1039
1070
  context.ArrayBuffer = ArrayBuffer;
1040
1071
  context.Symbol = Symbol;
1041
1072
  context.Reflect = Reflect;
1073
+ context.Object = Object;
1074
+ context.Error = Error;
1075
+ context.Array = Array;
1076
+ context.Float32Array = Float32Array;
1077
+ context.Float64Array = Float64Array;
1078
+ context.Int16Array = Int16Array;
1079
+ context.Int32Array = Int32Array;
1080
+ context.Int8Array = Int8Array;
1081
+ context.Uint16Array = Uint16Array;
1082
+ context.Uint32Array = Uint32Array;
1083
+ context.Uint8ClampedArray = Uint8ClampedArray;
1084
+ context.String = String;
1085
+ context.Function = Function;
1086
+ context.SyntaxError = SyntaxError;
1087
+ context.decodeURIComponent = decodeURIComponent;
1088
+ context.encodeURIComponent = encodeURIComponent;
1042
1089
  }
1043
1090
  } catch(e){
1044
1091
  }\n`)
1045
1092
  source.add(originalSource)
1046
1093
  source.add(`\nmodule.exports = ${globalObject}[${JSON.stringify(chunkLoadingGlobal)}];\n`)
1047
1094
  } else {
1048
- const entryModules = chunkGraph.getChunkEntryModulesIterable(chunk)
1049
- const entryModule = entryModules && entryModules[0]
1050
- if (entryModule && mpx.exportModules.has(entryModule)) {
1051
- source.add('module.exports =\n')
1052
- }
1053
1095
  source.add(originalSource)
1054
1096
  }
1055
1097
 
@@ -1126,7 +1168,7 @@ try {
1126
1168
  if (loader.loader.includes(info[0])) {
1127
1169
  loader.loader = info[1]
1128
1170
  }
1129
- if (loader.loader === info[1]) {
1171
+ if (loader.loader.includes(info[1])) {
1130
1172
  insertBeforeIndex = index
1131
1173
  }
1132
1174
  })
@@ -1161,41 +1203,43 @@ try {
1161
1203
  loader: extractorPath
1162
1204
  })
1163
1205
  }
1164
-
1165
1206
  createData.resource = addQuery(createData.resource, { mpx: MPX_PROCESSED_FLAG }, true)
1166
- createData.request = stringifyLoadersAndResource(loaders, createData.resource)
1167
1207
  }
1168
1208
 
1169
- // const mpxStyleOptions = queryObj.mpxStyleOptions
1170
- // const firstLoader = (data.loaders[0] && data.loaders[0].loader) || ''
1171
- // const isPitcherRequest = firstLoader.includes('vue-loader/lib/loaders/pitcher.js')
1172
- // let cssLoaderIndex = -1
1173
- // let vueStyleLoaderIndex = -1
1174
- // let mpxStyleLoaderIndex = -1
1175
- // data.loaders.forEach((loader, index) => {
1176
- // const currentLoader = loader.loader
1177
- // if (currentLoader.includes('css-loader')) {
1178
- // cssLoaderIndex = index
1179
- // } else if (currentLoader.includes('vue-loader/lib/loaders/stylePostLoader.js')) {
1180
- // vueStyleLoaderIndex = index
1181
- // } else if (currentLoader.includes('@mpxjs/webpack-plugin/lib/style-compiler/index.js')) {
1182
- // mpxStyleLoaderIndex = index
1183
- // }
1184
- // })
1185
- // if (mpxStyleLoaderIndex === -1) {
1186
- // let loaderIndex = -1
1187
- // if (cssLoaderIndex > -1 && vueStyleLoaderIndex === -1) {
1188
- // loaderIndex = cssLoaderIndex
1189
- // } else if (cssLoaderIndex > -1 && vueStyleLoaderIndex > -1 && !isPitcherRequest) {
1190
- // loaderIndex = vueStyleLoaderIndex
1191
- // }
1192
- // if (loaderIndex > -1) {
1193
- // data.loaders.splice(loaderIndex + 1, 0, {
1194
- // loader: normalize.lib('style-compiler/index.js'),
1195
- // options: (mpxStyleOptions && JSON.parse(mpxStyleOptions)) || {}
1196
- // })
1197
- // }
1198
- // }
1209
+ if (mpx.mode === 'web') {
1210
+ const mpxStyleOptions = queryObj.mpxStyleOptions
1211
+ const firstLoader = (loaders[0] && loaders[0].loader) || ''
1212
+ const isPitcherRequest = firstLoader.includes('vue-loader/lib/loaders/pitcher')
1213
+ let cssLoaderIndex = -1
1214
+ let vueStyleLoaderIndex = -1
1215
+ let mpxStyleLoaderIndex = -1
1216
+ loaders.forEach((loader, index) => {
1217
+ const currentLoader = loader.loader
1218
+ if (currentLoader.includes('css-loader')) {
1219
+ cssLoaderIndex = index
1220
+ } else if (currentLoader.includes('vue-loader/lib/loaders/stylePostLoader')) {
1221
+ vueStyleLoaderIndex = index
1222
+ } else if (currentLoader.includes(styleCompilerPath)) {
1223
+ mpxStyleLoaderIndex = index
1224
+ }
1225
+ })
1226
+ if (mpxStyleLoaderIndex === -1) {
1227
+ let loaderIndex = -1
1228
+ if (cssLoaderIndex > -1 && vueStyleLoaderIndex === -1) {
1229
+ loaderIndex = cssLoaderIndex
1230
+ } else if (cssLoaderIndex > -1 && vueStyleLoaderIndex > -1 && !isPitcherRequest) {
1231
+ loaderIndex = vueStyleLoaderIndex
1232
+ }
1233
+ if (loaderIndex > -1) {
1234
+ loaders.splice(loaderIndex + 1, 0, {
1235
+ loader: styleCompilerPath,
1236
+ options: (mpxStyleOptions && JSON.parse(mpxStyleOptions)) || {}
1237
+ })
1238
+ }
1239
+ }
1240
+ }
1241
+
1242
+ createData.request = stringifyLoadersAndResource(loaders, createData.resource)
1199
1243
  // 根据用户传入的modeRules对特定资源添加mode query
1200
1244
  this.runModeRules(createData)
1201
1245
  })
@@ -4,30 +4,27 @@ const nativeLoaderPath = normalize.lib('native-loader')
4
4
  const isUrlRequestRaw = require('../utils/is-url-request')
5
5
  const parseRequest = require('../utils/parse-request')
6
6
  const loaderUtils = require('loader-utils')
7
+ const resolve = require('../utils/resolve')
7
8
 
8
- module.exports = function createJSONHelper ({ loaderContext, emitWarning }) {
9
+ module.exports = function createJSONHelper ({ loaderContext, emitWarning, customGetDynamicEntry }) {
9
10
  const mpx = loaderContext.getMpx()
10
11
  const resolveMode = mpx.resolveMode
11
12
  const externals = mpx.externals
12
13
  const root = mpx.projectRoot
13
14
  const publicPath = loaderContext._compilation.outputOptions.publicPath || ''
14
15
  const pathHash = mpx.pathHash
16
+ const getOutputPath = mpx.getOutputPath
17
+ const mode = mpx.mode
15
18
 
16
19
  const isUrlRequest = r => isUrlRequestRaw(r, root, externals)
17
20
  const urlToRequest = r => loaderUtils.urlToRequest(r)
18
21
 
19
- // todo 提供不记录dependency的resolve方法,非必要的情况下不记录dependency,提升缓存利用率
20
- const resolve = (context, request, callback) => {
21
- const { queryObj } = parseRequest(request)
22
- context = queryObj.context || context
23
- return loaderContext.resolve(context, request, callback)
24
- }
25
-
26
22
  const dynamicEntryMap = new Map()
27
23
 
28
24
  let dynamicEntryCount = 0
29
25
 
30
26
  const getDynamicEntry = (resource, type, outputPath = '', packageRoot = '', relativePath = '') => {
27
+ if (typeof customGetDynamicEntry === 'function') return customGetDynamicEntry(resource, type, outputPath, packageRoot, relativePath)
31
28
  const key = `mpx_dynamic_entry_${dynamicEntryCount++}`
32
29
  const value = `__mpx_dynamic_entry__( ${JSON.stringify(resource)},${JSON.stringify(type)},${JSON.stringify(outputPath)},${JSON.stringify(packageRoot)},${JSON.stringify(relativePath)})`
33
30
  dynamicEntryMap.set(key, value)
@@ -42,14 +39,16 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning }) {
42
39
  }
43
40
 
44
41
  const processComponent = (component, context, { tarRoot = '', outputPath = '', relativePath = '' }, callback) => {
45
- if (!isUrlRequest(component)) return callback()
42
+ if (!isUrlRequest(component)) return callback(null, component)
46
43
  if (resolveMode === 'native') {
47
44
  component = urlToRequest(component)
48
45
  }
49
46
 
50
- resolve(context, component, (err, resource, info) => {
47
+ resolve(context, component, loaderContext, (err, resource, info) => {
51
48
  if (err) return callback(err)
52
- const resourcePath = parseRequest(resource).resourcePath
49
+ const { resourcePath, queryObj } = parseRequest(resource)
50
+ // 目前只有微信支持分包异步化
51
+ if (queryObj.root && mode === 'wx') tarRoot = queryObj.root
53
52
  const parsed = path.parse(resourcePath)
54
53
  const ext = parsed.ext
55
54
  const resourceName = path.join(parsed.dir, parsed.name)
@@ -70,8 +69,7 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning }) {
70
69
  let relative = path.relative(root, resourceName)
71
70
  outputPath = path.join('components', name + pathHash(root), relative)
72
71
  } else {
73
- let componentName = parsed.name
74
- outputPath = path.join('components', componentName + pathHash(resourcePath), componentName)
72
+ outputPath = getOutputPath(resourcePath, 'component')
75
73
  }
76
74
  }
77
75
  if (ext === '.js') {
@@ -83,24 +81,19 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning }) {
83
81
  })
84
82
  }
85
83
 
86
- const getPageName = (resourcePath, ext) => {
87
- const baseName = path.basename(resourcePath, ext)
88
- return path.join('pages', baseName + pathHash(resourcePath), baseName)
89
- }
90
-
91
84
  const processPage = (page, context, tarRoot = '', callback) => {
92
85
  let aliasPath = ''
93
86
  if (typeof page !== 'string') {
94
87
  aliasPath = page.path
95
88
  page = page.src
96
89
  }
97
- if (!isUrlRequest(page)) return callback()
90
+ if (!isUrlRequest(page)) return callback(null, page)
98
91
  if (resolveMode === 'native') {
99
92
  page = urlToRequest(page)
100
93
  }
101
- resolve(context, page, (err, resource) => {
94
+ resolve(context, page, loaderContext, (err, resource) => {
102
95
  if (err) return callback(err)
103
- const { resourcePath } = parseRequest(resource)
96
+ const { resourcePath, queryObj: { isFirst } } = parseRequest(resource)
104
97
  const ext = path.extname(resourcePath)
105
98
  let outputPath
106
99
  if (aliasPath) {
@@ -109,7 +102,7 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning }) {
109
102
  const relative = path.relative(context, resourcePath)
110
103
  if (/^\./.test(relative)) {
111
104
  // 如果当前page不存在于context中,对其进行重命名
112
- outputPath = getPageName(resourcePath, ext)
105
+ outputPath = getOutputPath(resourcePath, 'page')
113
106
  emitWarning(`Current page [${resourcePath}] is not in current pages directory [${context}], the page path will be replaced with [${outputPath}], use ?resolve to get the page path and navigate to it!`)
114
107
  } else {
115
108
  outputPath = /^(.*?)(\.[^.]*)?$/.exec(relative)[1]
@@ -119,7 +112,11 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning }) {
119
112
  resource = `!!${nativeLoaderPath}!${resource}`
120
113
  }
121
114
  const entry = getDynamicEntry(resource, 'page', outputPath, tarRoot, publicPath + tarRoot)
122
- callback(null, entry)
115
+ const key = [resourcePath, outputPath, tarRoot].join('|')
116
+ callback(null, entry, {
117
+ isFirst,
118
+ key
119
+ })
123
120
  })
124
121
  }
125
122
 
@@ -127,7 +124,7 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning }) {
127
124
  if (resolveMode === 'native') {
128
125
  js = urlToRequest(js)
129
126
  }
130
- resolve(context, js, (err, resource) => {
127
+ resolve(context, js, loaderContext, (err, resource) => {
131
128
  if (err) return callback(err)
132
129
  const { resourcePath } = parseRequest(resource)
133
130
  const relative = path.relative(context, resourcePath)
@@ -145,7 +142,6 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning }) {
145
142
  processDynamicEntry,
146
143
  processPage,
147
144
  processJsExport,
148
- resolve,
149
145
  isUrlRequest,
150
146
  urlToRequest
151
147
  }