@mpxjs/webpack-plugin 2.7.0-beta.6 → 2.7.0

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.
@@ -16,6 +16,8 @@ class AppEntryDependency extends NullDependency {
16
16
  const mpx = compilation.__mpx__
17
17
  const moduleGraph = compilation.moduleGraph
18
18
 
19
+ mpx.getEntryNode(module, 'app')
20
+
19
21
  if (mpx.appInfo.name) {
20
22
  const issuer = moduleGraph.getIssuer(module)
21
23
  const err = new Error(issuer
@@ -1,8 +1,9 @@
1
1
  const ModuleDependency = require('webpack/lib/dependencies/ModuleDependency')
2
2
  const makeSerializable = require('webpack/lib/util/makeSerializable')
3
+ const InitFragment = require('webpack/lib//InitFragment')
3
4
 
4
5
  class CommonJsVariableDependency extends ModuleDependency {
5
- constructor (request, name) {
6
+ constructor (request, name = '') {
6
7
  super(request)
7
8
  this.name = name
8
9
  }
@@ -44,10 +45,10 @@ CommonJsVariableDependency.Template = class CommonJsVariableDependencyTemplate e
44
45
  runtimeTemplate,
45
46
  moduleGraph,
46
47
  chunkGraph,
47
- runtimeRequirements
48
+ runtimeRequirements,
49
+ initFragments
48
50
  }
49
51
  ) {
50
- if (!dep.name) return
51
52
  const importedModule = moduleGraph.getModule(dep)
52
53
  let requireExpr = runtimeTemplate.moduleExports({
53
54
  module: importedModule,
@@ -57,7 +58,18 @@ CommonJsVariableDependency.Template = class CommonJsVariableDependencyTemplate e
57
58
  runtimeRequirements
58
59
  })
59
60
 
60
- source.insert(0, `/* mpx cjs variable */ var ${dep.name} = ${requireExpr};\n`)
61
+ let expr = '/* mpx cjs variable */ '
62
+ if (dep.name) expr += 'var ' + dep.name + ' = '
63
+ expr += requireExpr + ';\n'
64
+
65
+ initFragments.push(
66
+ new InitFragment(
67
+ expr,
68
+ InitFragment.STAGE_CONSTANTS,
69
+ 1,
70
+ dep.request
71
+ )
72
+ )
61
73
  }
62
74
  }
63
75
 
@@ -21,13 +21,13 @@ class DynamicEntryDependency extends NullDependency {
21
21
 
22
22
  get key () {
23
23
  const { resource, entryType, outputPath, packageRoot, relativePath, range } = this
24
- return [resource, entryType, outputPath, packageRoot, relativePath, ...range].join('|')
24
+ return toPosix([resource, entryType, outputPath, packageRoot, relativePath, ...range].join('|'))
25
25
  }
26
26
 
27
27
  addEntry (compilation, callback) {
28
28
  const mpx = compilation.__mpx__
29
29
  const publicPath = compilation.outputOptions.publicPath || ''
30
- let { resource, entryType, outputPath, relativePath } = this
30
+ let { resource, entryType, outputPath, relativePath, originEntryNode } = this
31
31
 
32
32
  const { packageRoot, outputPath: filename, alreadyOutputed } = mpx.getPackageInfo({
33
33
  resource,
@@ -59,7 +59,7 @@ class DynamicEntryDependency extends NullDependency {
59
59
  if (entryType === 'export') {
60
60
  mpx.exportModules.add(entryModule)
61
61
  }
62
- // todo entry的父子关系可以在这里建立
62
+ originEntryNode.addChild(mpx.getEntryNode(entryModule, entryType))
63
63
  return callback(null, {
64
64
  resultPath,
65
65
  entryModule
@@ -70,6 +70,7 @@ class DynamicEntryDependency extends NullDependency {
70
70
  mpxAction (module, compilation, callback) {
71
71
  const mpx = compilation.__mpx__
72
72
  const { packageRoot } = this
73
+ this.originEntryNode = mpx.getEntryNode(module)
73
74
  // 分包构建在需要在主包构建完成后在finishMake中处理,返回的资源路径先用key来占位,在合成extractedAssets时再进行最终替换
74
75
  if (packageRoot && mpx.currentPackageRoot !== packageRoot) {
75
76
  mpx.subpackagesEntriesMap[packageRoot] = mpx.subpackagesEntriesMap[packageRoot] || []
@@ -9,6 +9,7 @@ class FlagPluginDependency extends NullDependency {
9
9
  mpxAction (module, compilation, callback) {
10
10
  const mpx = compilation.__mpx__
11
11
  mpx.isPluginMode = true
12
+ mpx.getEntryNode(module, 'plugin')
12
13
  return callback()
13
14
  }
14
15
  }
@@ -0,0 +1,44 @@
1
+ const NullDependency = require('webpack/lib/dependencies/NullDependency')
2
+ const makeSerializable = require('webpack/lib/util/makeSerializable')
3
+
4
+ class RecordIndependentDependency extends NullDependency {
5
+ constructor (root, request) {
6
+ super()
7
+ this.root = root
8
+ this.request = request
9
+ }
10
+
11
+ get type () {
12
+ return 'mpx record independent'
13
+ }
14
+
15
+ mpxAction (module, compilation, callback) {
16
+ const mpx = compilation.__mpx__
17
+ const { root, request } = this
18
+ mpx.independentSubpackagesMap[root] = request
19
+ return callback()
20
+ }
21
+
22
+ serialize (context) {
23
+ const { write } = context
24
+ write(this.root)
25
+ write(this.request)
26
+ super.serialize(context)
27
+ }
28
+
29
+ deserialize (context) {
30
+ const { read } = context
31
+ this.root = read()
32
+ this.request = read()
33
+ super.deserialize(context)
34
+ }
35
+ }
36
+
37
+ RecordIndependentDependency.Template = class RecordIndependentDependencyTemplate {
38
+ apply () {
39
+ }
40
+ }
41
+
42
+ makeSerializable(RecordIndependentDependency, '@mpxjs/webpack-plugin/lib/dependencies/RecordIndependentDependency')
43
+
44
+ module.exports = RecordIndependentDependency
package/lib/extractor.js CHANGED
@@ -4,8 +4,8 @@ const parseRequest = require('./utils/parse-request')
4
4
  const toPosix = require('./utils/to-posix')
5
5
  const fixRelative = require('./utils/fix-relative')
6
6
  const addQuery = require('./utils/add-query')
7
+ const normalize = require('./utils/normalize')
7
8
  const { MPX_DISABLE_EXTRACTOR_CACHE, DEFAULT_RESULT_SOURCE } = require('./utils/const')
8
- const RecordResourceMapDependency = require('./dependencies/RecordResourceMapDependency')
9
9
 
10
10
  module.exports = content => content
11
11
 
@@ -37,10 +37,10 @@ module.exports.pitch = async function (remainingRequest) {
37
37
  })
38
38
 
39
39
  let request = remainingRequest
40
- // static的情况下需要记录相关静态资源的输出路径
40
+ // static的情况下需要用record-loader记录相关静态资源的输出路径,不能直接在这里记录,需要确保在子依赖开始构建前完成记录,因为子依赖构建时可能就需要访问当前资源的输出路径
41
41
  if (isStatic) {
42
- const packageRoot = queryObj.packageRoot || ''
43
- this._module.addPresentationalDependency(new RecordResourceMapDependency(resourcePath, 'staticResource', file, packageRoot))
42
+ const recordLoader = normalize.lib('record-loader')
43
+ request = `${recordLoader}!${remainingRequest}`
44
44
  }
45
45
 
46
46
  let content = await this.importModule(`!!${request}`)
@@ -51,6 +51,10 @@ module.exports.pitch = async function (remainingRequest) {
51
51
  }).join('\n')
52
52
  }
53
53
 
54
+ let resultSource = DEFAULT_RESULT_SOURCE
55
+
56
+ if (typeof content !== 'string') return resultSource
57
+
54
58
  const extractedInfo = {
55
59
  content,
56
60
  index
@@ -61,8 +65,6 @@ module.exports.pitch = async function (remainingRequest) {
61
65
  extractedInfo
62
66
  })
63
67
 
64
- let resultSource = DEFAULT_RESULT_SOURCE
65
-
66
68
  const { buildInfo } = this._module
67
69
 
68
70
  // 如果importModule子模块中包含动态特性,比如动态添加入口和静态资源输出路径,则当前extractor模块不可缓存
package/lib/helpers.js CHANGED
@@ -4,14 +4,6 @@ const selectorPath = normalize.lib('selector')
4
4
  const addQuery = require('./utils/add-query')
5
5
  const parseRequest = require('./utils/parse-request')
6
6
 
7
- function getRawRequest ({ resource, loaderIndex, loaders }, excludedPreLoaders = /eslint-loader/) {
8
- return loaderUtils.getRemainingRequest({
9
- resource: resource,
10
- loaderIndex: loaderIndex,
11
- loaders: loaders.filter(loader => !excludedPreLoaders.test(loader.path))
12
- })
13
- }
14
-
15
7
  const defaultLang = {
16
8
  template: 'wxml',
17
9
  styles: 'wxss',
@@ -21,7 +13,7 @@ const defaultLang = {
21
13
  }
22
14
 
23
15
  module.exports = function createHelpers (loaderContext) {
24
- const rawRequest = getRawRequest(loaderContext)
16
+ const rawRequest = loaderUtils.getRemainingRequest(loaderContext)
25
17
 
26
18
  function getRequire (type, part, extraOptions, index) {
27
19
  return 'require(' + getRequestString(type, part, extraOptions, index) + ')'
@@ -0,0 +1,59 @@
1
+ const parseComponent = require('./parser')
2
+ const createHelpers = require('./helpers')
3
+ const CommonJsVariableDependency = require('./dependencies/CommonJsVariableDependency')
4
+ const path = require('path')
5
+ const normalize = require('./utils/normalize')
6
+
7
+ module.exports = function (content) {
8
+ this.cacheable()
9
+ const mpx = this.getMpx()
10
+ if (!mpx) {
11
+ return content
12
+ }
13
+
14
+ const mode = mpx.mode
15
+ const env = mpx.env
16
+ const i18n = mpx.i18n
17
+ const filePath = this.resourcePath
18
+ const extname = path.extname(filePath)
19
+ if (extname === '.mpx') {
20
+ const parts = parseComponent(content, {
21
+ filePath,
22
+ needMap: this.sourceMap,
23
+ mode,
24
+ env
25
+ })
26
+ const {
27
+ getRequire
28
+ } = createHelpers(this)
29
+
30
+ if (parts.script) {
31
+ content = getRequire('script', parts.script)
32
+ } else {
33
+ content = ''
34
+ }
35
+ }
36
+
37
+ let output = 'global.isIndependent = true\n'
38
+ // 注入i18n
39
+ if (i18n) {
40
+ const i18nWxsPath = normalize.lib('runtime/i18n.wxs')
41
+ const i18nWxsLoaderPath = normalize.lib('wxs/i18n-loader.js')
42
+ const i18nWxsRequest = i18nWxsLoaderPath + '!' + i18nWxsPath
43
+ const i18nMethodsVar = 'i18nMethods'
44
+ this._module.addDependency(new CommonJsVariableDependency(i18nWxsRequest, i18nMethodsVar))
45
+
46
+ output += `if (!global.i18n) {
47
+ global.i18n = ${JSON.stringify({
48
+ locale: i18n.locale,
49
+ version: 0
50
+ })}
51
+ global.i18nMethods = ${i18nMethodsVar}
52
+ }\n`
53
+ }
54
+ output += content
55
+ output += '\n'
56
+ output += 'delete global.isIndependent\n'
57
+
58
+ return output
59
+ }
package/lib/index.js CHANGED
@@ -26,6 +26,7 @@ const PackageEntryPlugin = require('./resolver/PackageEntryPlugin')
26
26
  const AppEntryDependency = require('./dependencies/AppEntryDependency')
27
27
  const RecordResourceMapDependency = require('./dependencies/RecordResourceMapDependency')
28
28
  const RecordGlobalComponentsDependency = require('./dependencies/RecordGlobalComponentsDependency')
29
+ const RecordIndependentDependency = require('./dependencies/RecordIndependentDependency')
29
30
  const DynamicEntryDependency = require('./dependencies/DynamicEntryDependency')
30
31
  const FlagPluginDependency = require('./dependencies/FlagPluginDependency')
31
32
  const RemoveEntryDependency = require('./dependencies/RemoveEntryDependency')
@@ -49,6 +50,7 @@ const async = require('async')
49
50
  const stringifyLoadersAndResource = require('./utils/stringify-loaders-resource')
50
51
  const emitFile = require('./utils/emit-file')
51
52
  const { MPX_PROCESSED_FLAG, MPX_DISABLE_EXTRACTOR_CACHE } = require('./utils/const')
53
+ const isEmptyObject = require('./utils/is-empty-object')
52
54
 
53
55
  const isProductionLikeMode = options => {
54
56
  return options.mode === 'production' || !options.mode
@@ -76,30 +78,6 @@ const isChunkInPackage = (chunkName, packageName) => {
76
78
  return (new RegExp(`^${packageName}\\/`)).test(chunkName)
77
79
  }
78
80
 
79
- const getPackageCacheGroup = packageName => {
80
- if (packageName === 'main') {
81
- return {
82
- name: 'bundle',
83
- minChunks: 2,
84
- chunks: 'all'
85
- }
86
- } else {
87
- return {
88
- test: (module, { chunkGraph }) => {
89
- const chunks = chunkGraph.getModuleChunksIterable(module)
90
- return chunks.size && every(chunks, (chunk) => {
91
- return isChunkInPackage(chunk.name, packageName)
92
- })
93
- },
94
- name: `${packageName}/bundle`,
95
- minChunks: 2,
96
- minSize: 1000,
97
- priority: 100,
98
- chunks: 'all'
99
- }
100
- }
101
- }
102
-
103
81
  const externalsMap = {
104
82
  weui: /^weui-miniprogram/
105
83
  }
@@ -107,20 +85,19 @@ const externalsMap = {
107
85
  const warnings = []
108
86
  const errors = []
109
87
 
110
- // class EntryNode {
111
- // constructor (options) {
112
- // this.request = options.request
113
- // this.type = options.type
114
- // this.module = null
115
- // this.parents = new Set()
116
- // this.children = new Set()
117
- // }
118
- //
119
- // addChild (node) {
120
- // this.children.add(node)
121
- // node.parents.add(this)
122
- // }
123
- // }
88
+ class EntryNode {
89
+ constructor (module, type) {
90
+ this.module = module
91
+ this.type = type
92
+ this.parents = new Set()
93
+ this.children = new Set()
94
+ }
95
+
96
+ addChild (node) {
97
+ this.children.add(node)
98
+ node.parents.add(this)
99
+ }
100
+ }
124
101
 
125
102
  class MpxWebpackPlugin {
126
103
  constructor (options = {}) {
@@ -359,18 +336,53 @@ class MpxWebpackPlugin {
359
336
 
360
337
  let mpx
361
338
 
362
- // 构建分包队列,在finishMake钩子当中最先执行,stage传递-1000
363
- compiler.hooks.finishMake.tapAsync({
364
- name: 'MpxWebpackPlugin',
365
- stage: -1000
366
- }, (compilation, callback) => {
339
+ const getPackageCacheGroup = packageName => {
340
+ if (packageName === 'main') {
341
+ return {
342
+ // 对于独立分包模块不应用该cacheGroup
343
+ test: (module) => {
344
+ let isIndependent = false
345
+ if (module.resource) {
346
+ const { queryObj } = parseRequest(module.resource)
347
+ isIndependent = !!queryObj.independent
348
+ } else {
349
+ const identifier = module.identifier()
350
+ isIndependent = /\|independent=/.test(identifier)
351
+ }
352
+ return !isIndependent
353
+ },
354
+ name: 'bundle',
355
+ minChunks: 2,
356
+ chunks: 'all'
357
+ }
358
+ } else {
359
+ return {
360
+ test: (module, { chunkGraph }) => {
361
+ const chunks = chunkGraph.getModuleChunksIterable(module)
362
+ return chunks.size && every(chunks, (chunk) => {
363
+ return isChunkInPackage(chunk.name, packageName)
364
+ })
365
+ },
366
+ name: `${packageName}/bundle`,
367
+ minChunks: 2,
368
+ minSize: 1000,
369
+ priority: 100,
370
+ chunks: 'all'
371
+ }
372
+ }
373
+ }
374
+
375
+ const processSubpackagesEntriesMap = (compilation, callback) => {
367
376
  const mpx = compilation.__mpx__
368
- if (mpx && mpx.subpackagesEntriesMap) {
369
- async.eachOfSeries(mpx.subpackagesEntriesMap, (deps, packageRoot, callback) => {
377
+ if (mpx && !isEmptyObject(mpx.subpackagesEntriesMap)) {
378
+ const subpackagesEntriesMap = mpx.subpackagesEntriesMap
379
+ // 执行分包队列前清空mpx.subpackagesEntriesMap
380
+ mpx.subpackagesEntriesMap = {}
381
+ async.eachOfSeries(subpackagesEntriesMap, (deps, packageRoot, callback) => {
370
382
  mpx.currentPackageRoot = packageRoot
371
- mpx.componentsMap[packageRoot] = {}
372
- mpx.staticResourcesMap[packageRoot] = {}
373
- mpx.subpackageModulesMap[packageRoot] = {}
383
+ mpx.componentsMap[packageRoot] = mpx.componentsMap[packageRoot] || {}
384
+ mpx.staticResourcesMap[packageRoot] = mpx.staticResourcesMap[packageRoot] || {}
385
+ mpx.subpackageModulesMap[packageRoot] = mpx.subpackageModulesMap[packageRoot] || {}
374
386
  async.each(deps, (dep, callback) => {
375
387
  dep.addEntry(compilation, (err, { resultPath }) => {
376
388
  if (err) return callback(err)
@@ -378,10 +390,22 @@ class MpxWebpackPlugin {
378
390
  callback()
379
391
  })
380
392
  }, callback)
381
- }, callback)
393
+ }, (err) => {
394
+ if (err) return callback(err)
395
+ // 如果执行完当前队列后产生了新的分包执行队列(一般由异步分包组件造成),则继续执行
396
+ processSubpackagesEntriesMap(compilation, callback)
397
+ })
382
398
  } else {
383
399
  callback()
384
400
  }
401
+ }
402
+
403
+ // 构建分包队列,在finishMake钩子当中最先执行,stage传递-1000
404
+ compiler.hooks.finishMake.tapAsync({
405
+ name: 'MpxWebpackPlugin',
406
+ stage: -1000
407
+ }, (compilation, callback) => {
408
+ processSubpackagesEntriesMap(compilation, callback)
385
409
  })
386
410
 
387
411
  compiler.hooks.compilation.tap('MpxWebpackPlugin ', (compilation, { normalModuleFactory }) => {
@@ -422,6 +446,9 @@ class MpxWebpackPlugin {
422
446
  compilation.dependencyFactories.set(RecordGlobalComponentsDependency, new NullFactory())
423
447
  compilation.dependencyTemplates.set(RecordGlobalComponentsDependency, new RecordGlobalComponentsDependency.Template())
424
448
 
449
+ compilation.dependencyFactories.set(RecordIndependentDependency, new NullFactory())
450
+ compilation.dependencyTemplates.set(RecordIndependentDependency, new RecordIndependentDependency.Template())
451
+
425
452
  compilation.dependencyFactories.set(CommonJsVariableDependency, normalModuleFactory)
426
453
  compilation.dependencyTemplates.set(CommonJsVariableDependency, new CommonJsVariableDependency.Template())
427
454
  })
@@ -456,10 +483,8 @@ class MpxWebpackPlugin {
456
483
  subpackagesEntriesMap: {},
457
484
  replacePathMap: {},
458
485
  exportModules: new Set(),
459
- // 记录entry依赖关系,用于体积分析
460
- entryNodesMap: {},
461
486
  // 记录entryModule与entryNode的对应关系,用于体积分析
462
- entryModulesMap: new Map(),
487
+ entryNodeModulesMap: new Map(),
463
488
  extractedMap: {},
464
489
  usingComponents: {},
465
490
  // todo es6 map读写性能高于object,之后会逐步替换
@@ -503,6 +528,15 @@ class MpxWebpackPlugin {
503
528
  compilation.addEntry(compiler.context, dep, { name }, callback)
504
529
  return dep
505
530
  },
531
+ getEntryNode: (module, type) => {
532
+ const entryNodeModulesMap = mpx.entryNodeModulesMap
533
+ let entryNode = entryNodeModulesMap.get(module)
534
+ if (!entryNode) {
535
+ entryNode = new EntryNode(module, type)
536
+ entryNodeModulesMap.set(module, entryNode)
537
+ }
538
+ return entryNode
539
+ },
506
540
  getOutputPath: (resourcePath, type, { ext = '', conflictPath = '' } = {}) => {
507
541
  const name = path.parse(resourcePath).name
508
542
  const hash = mpx.pathHash(resourcePath)
@@ -552,7 +586,7 @@ class MpxWebpackPlugin {
552
586
  const { resourcePath } = parseRequest(resource)
553
587
  const currentPackageRoot = mpx.currentPackageRoot
554
588
  const currentPackageName = currentPackageRoot || 'main'
555
- const isIndependent = mpx.independentSubpackagesMap[currentPackageRoot]
589
+ const isIndependent = !!mpx.independentSubpackagesMap[currentPackageRoot]
556
590
  const resourceMap = mpx[`${resourceType}sMap`] || mpx.otherResourcesMap
557
591
 
558
592
  if (!resourceMap.main) {
@@ -597,6 +631,7 @@ class MpxWebpackPlugin {
597
631
  if (currentResourceMap[resourcePath] === outputPath) {
598
632
  alreadyOutputed = true
599
633
  } else {
634
+ // todo 用outputPathMap来检测冲突
600
635
  // 输出冲突检测,如果存在输出路径冲突,对输出路径进行重命名
601
636
  for (let key in currentResourceMap) {
602
637
  if (currentResourceMap[key] === outputPath && key !== resourcePath) {
@@ -654,12 +689,14 @@ class MpxWebpackPlugin {
654
689
  const rawAddModule = compilation.addModule
655
690
  compilation.addModule = (module, callback) => {
656
691
  const issuerResource = module.issuerResource
657
- // 避免context module报错
658
- if (module.request && module.resource) {
692
+ const currentPackageRoot = mpx.currentPackageRoot
693
+ const independent = mpx.independentSubpackagesMap[currentPackageRoot]
694
+
695
+ if (module.resource) {
696
+ // NormalModule
659
697
  const isStatic = isStaticModule(module)
660
- const isIndependent = mpx.independentSubpackagesMap[mpx.currentPackageRoot]
661
698
 
662
- let needPackageQuery = isStatic || isIndependent
699
+ let needPackageQuery = isStatic || independent
663
700
 
664
701
  if (!needPackageQuery) {
665
702
  const { resourcePath } = parseRequest(module.resource)
@@ -679,12 +716,23 @@ class MpxWebpackPlugin {
679
716
  }
680
717
  })
681
718
  if (packageRoot) {
682
- module.request = addQuery(module.request, { packageRoot })
683
- module.resource = addQuery(module.resource, { packageRoot })
719
+ const queryObj = {
720
+ packageRoot
721
+ }
722
+ if (independent) queryObj.independent = independent
723
+ module.request = addQuery(module.request, queryObj)
724
+ module.resource = addQuery(module.resource, queryObj)
684
725
  }
685
726
  }
727
+ } else if (independent) {
728
+ // ContextModule和RawModule只在独立分包的情况下添加分包标记,其余默认不添加
729
+ const postfix = `|independent=${independent}|${currentPackageRoot}`
730
+ if (module._identifier) {
731
+ module._identifier += postfix
732
+ } else if (module.identifierStr) {
733
+ module.identifierStr += postfix
734
+ }
686
735
  }
687
-
688
736
  return rawAddModule.call(compilation, module, callback)
689
737
  }
690
738
 
@@ -14,6 +14,7 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
14
14
  const publicPath = loaderContext._compilation.outputOptions.publicPath || ''
15
15
  const pathHash = mpx.pathHash
16
16
  const getOutputPath = mpx.getOutputPath
17
+ const mode = mpx.mode
17
18
 
18
19
  const isUrlRequest = r => isUrlRequestRaw(r, root, externals)
19
20
  const urlToRequest = r => loaderUtils.urlToRequest(r)
@@ -45,7 +46,9 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
45
46
 
46
47
  resolve(context, component, loaderContext, (err, resource, info) => {
47
48
  if (err) return callback(err)
48
- const resourcePath = parseRequest(resource).resourcePath
49
+ const { resourcePath, queryObj } = parseRequest(resource)
50
+ // 目前只有微信支持分包异步化
51
+ if (queryObj.root && mode === 'wx') tarRoot = queryObj.root
49
52
  const parsed = path.parse(resourcePath)
50
53
  const ext = parsed.ext
51
54
  const resourceName = path.join(parsed.dir, parsed.name)
@@ -12,6 +12,7 @@ const getJSONContent = require('../utils/get-json-content')
12
12
  const createHelpers = require('../helpers')
13
13
  const createJSONHelper = require('./helper')
14
14
  const RecordGlobalComponentsDependency = require('../dependencies/RecordGlobalComponentsDependency')
15
+ const RecordIndependentDependency = require('../dependencies/RecordIndependentDependency')
15
16
  const { MPX_DISABLE_EXTRACTOR_CACHE, RESOLVE_IGNORED_ERR, JSON_JS_EXT } = require('../utils/const')
16
17
  const resolve = require('../utils/resolve')
17
18
 
@@ -263,13 +264,17 @@ module.exports = function (content) {
263
264
  },
264
265
  (result, content, callback) => {
265
266
  const extName = path.extname(result)
266
- if (extName === '.mpx' || extName === '.vue') {
267
+ if (extName === '.mpx') {
267
268
  const parts = parseComponent(content, {
268
269
  filePath: result,
269
270
  needMap: this.sourceMap,
270
271
  mode,
271
272
  env
272
273
  })
274
+ // 对于通过.mpx文件声明的独立分包,默认将其自身的script block视为init module
275
+ if (parts.script && queryObj.independent === true) {
276
+ queryObj.independent = result
277
+ }
273
278
  getJSONContent(parts.json || {}, this, (err, content) => {
274
279
  callback(err, result, content)
275
280
  })
@@ -346,6 +351,31 @@ module.exports = function (content) {
346
351
  return result
347
352
  }
348
353
 
354
+ const recordIndependent = (root, request) => {
355
+ this._module.addPresentationalDependency(new RecordIndependentDependency(root, request))
356
+ }
357
+
358
+ const processIndependent = (otherConfig, context, tarRoot, callback) => {
359
+ // 支付宝不支持独立分包,无需处理
360
+ const independent = otherConfig.independent
361
+ if (!independent || mode === 'ali') {
362
+ delete otherConfig.independent
363
+ return callback()
364
+ }
365
+ // independent配置为字符串时视为init module
366
+ if (typeof independent === 'string') {
367
+ otherConfig.independent = true
368
+ resolve(context, independent, this, (err, result) => {
369
+ if (err) return callback(err)
370
+ recordIndependent(tarRoot, result)
371
+ callback()
372
+ })
373
+ } else {
374
+ recordIndependent(tarRoot, true)
375
+ callback()
376
+ }
377
+ }
378
+
349
379
  // 为了获取资源的所属子包,该函数需串行执行
350
380
  const processSubPackage = (subPackage, context, callback) => {
351
381
  if (subPackage) {
@@ -357,26 +387,27 @@ module.exports = function (content) {
357
387
  let srcRoot = subPackage.srcRoot || subPackage.root || ''
358
388
  if (!tarRoot || subPackagesCfg[tarRoot]) return callback()
359
389
 
390
+ context = path.join(context, srcRoot)
360
391
  const otherConfig = getOtherConfig(subPackage)
361
- // 支付宝不支持独立分包,无需处理
362
- if (otherConfig.independent && mode !== 'ali') {
363
- mpx.independentSubpackagesMap[tarRoot] = true
364
- }
365
-
366
392
  subPackagesCfg[tarRoot] = {
367
393
  root: tarRoot,
368
- pages: [],
369
- ...otherConfig
394
+ pages: []
370
395
  }
371
- context = path.join(context, srcRoot)
372
396
  async.parallel([
397
+ (callback) => {
398
+ processIndependent(otherConfig, context, tarRoot, callback)
399
+ },
373
400
  (callback) => {
374
401
  processPages(subPackage.pages, context, tarRoot, callback)
375
402
  },
376
403
  (callback) => {
377
404
  processPlugins(subPackage.plugins, context, tarRoot, callback)
378
405
  }
379
- ], callback)
406
+ ], (err) => {
407
+ if (err) return callback(err)
408
+ Object.assign(subPackagesCfg[tarRoot], otherConfig)
409
+ callback()
410
+ })
380
411
  } else {
381
412
  callback()
382
413
  }
package/lib/loader.js CHANGED
@@ -15,6 +15,8 @@ const getJSONContent = require('./utils/get-json-content')
15
15
  const normalize = require('./utils/normalize')
16
16
  const getEntryName = require('./utils/get-entry-name')
17
17
  const AppEntryDependency = require('./dependencies/AppEntryDependency')
18
+ const RecordResourceMapDependency = require('./dependencies/RecordResourceMapDependency')
19
+ const CommonJsVariableDependency = require('./dependencies/CommonJsVariableDependency')
18
20
  const { MPX_APP_MODULE_ID } = require('./utils/const')
19
21
 
20
22
  module.exports = function (content) {
@@ -25,7 +27,9 @@ module.exports = function (content) {
25
27
  return content
26
28
  }
27
29
  const { resourcePath, queryObj } = parseRequest(this.resource)
28
- const packageName = queryObj.packageRoot || mpx.currentPackageRoot || 'main'
30
+ const packageRoot = queryObj.packageRoot || mpx.currentPackageRoot
31
+ const packageName = packageRoot || 'main'
32
+ const independent = queryObj.independent
29
33
  const pagesMap = mpx.pagesMap
30
34
  const componentsMap = mpx.componentsMap[packageName]
31
35
  const mode = mpx.mode
@@ -37,16 +41,6 @@ module.exports = function (content) {
37
41
  const vueContentCache = mpx.vueContentCache
38
42
  const autoScope = matchCondition(resourcePath, mpx.autoScopeRules)
39
43
 
40
- // 支持资源query传入isPage或isComponent支持页面/组件单独编译
41
- if ((queryObj.isComponent && !componentsMap[resourcePath]) || (queryObj.isPage && !pagesMap[resourcePath])) {
42
- const entryName = getEntryName(this)
43
- if (queryObj.isComponent) {
44
- componentsMap[resourcePath] = entryName || 'noEntryComponent'
45
- } else {
46
- pagesMap[resourcePath] = entryName || 'noEntryPage'
47
- }
48
- }
49
-
50
44
  let ctorType = 'app'
51
45
  if (pagesMap[resourcePath]) {
52
46
  // page
@@ -56,10 +50,17 @@ module.exports = function (content) {
56
50
  ctorType = 'component'
57
51
  }
58
52
 
53
+ // 支持资源query传入isPage或isComponent支持页面/组件单独编译
54
+ if (queryObj.isComponent || queryObj.isPage) {
55
+ const entryName = getEntryName(this) || (queryObj.isComponent ? 'noEntryComponent' : 'noEntryPage')
56
+ ctorType = queryObj.isComponent ? 'component' : 'page'
57
+ this._module.addPresentationalDependency(new RecordResourceMapDependency(resourcePath, ctorType, entryName, packageRoot))
58
+ }
59
+
59
60
  const loaderContext = this
60
61
  const stringifyRequest = r => loaderUtils.stringifyRequest(loaderContext, r)
61
62
  const isProduction = this.minimize || process.env.NODE_ENV === 'production'
62
- const filePath = resourcePath
63
+ const filePath = this.resourcePath
63
64
  const moduleId = ctorType === 'app' ? MPX_APP_MODULE_ID : 'm' + mpx.pathHash(filePath)
64
65
 
65
66
  const parts = parseComponent(content, {
@@ -69,6 +70,10 @@ module.exports = function (content) {
69
70
  env
70
71
  })
71
72
 
73
+ const {
74
+ getRequire
75
+ } = createHelpers(loaderContext)
76
+
72
77
  let output = ''
73
78
  const callback = this.async()
74
79
 
@@ -195,29 +200,49 @@ module.exports = function (content) {
195
200
  })
196
201
  }
197
202
 
203
+ const moduleGraph = this._compilation.moduleGraph
204
+
205
+ const issuer = moduleGraph.getIssuer(this._module)
206
+
207
+ if (issuer) {
208
+ return callback(new Error(`Current ${ctorType} [${this.resourcePath}] is issued by [${issuer.resource}], which is not allowed!`))
209
+ }
210
+
198
211
  if (ctorType === 'app') {
199
212
  const appName = getEntryName(this)
200
213
  this._module.addPresentationalDependency(new AppEntryDependency(resourcePath, appName))
201
214
  }
202
215
 
203
- const {
204
- getRequire
205
- } = createHelpers(loaderContext)
206
-
207
216
  // 注入模块id及资源路径
208
217
  output += `global.currentModuleId = ${JSON.stringify(moduleId)}\n`
209
218
  if (!isProduction) {
210
219
  output += `global.currentResource = ${JSON.stringify(filePath)}\n`
211
220
  }
212
- if (ctorType === 'app' && i18n) {
213
- output += `global.i18n = ${JSON.stringify({ locale: i18n.locale, version: 0 })}\n`
214
221
 
222
+ // 为app注入i18n
223
+ if (i18n && ctorType === 'app') {
215
224
  const i18nWxsPath = normalize.lib('runtime/i18n.wxs')
216
225
  const i18nWxsLoaderPath = normalize.lib('wxs/i18n-loader.js')
217
226
  const i18nWxsRequest = i18nWxsLoaderPath + '!' + i18nWxsPath
227
+ const i18nMethodsVar = 'i18nMethods'
228
+ this._module.addDependency(new CommonJsVariableDependency(i18nWxsRequest, i18nMethodsVar))
229
+
230
+ output += `if (!global.i18n) {
231
+ global.i18n = ${JSON.stringify({
232
+ locale: i18n.locale,
233
+ version: 0
234
+ })}
235
+ global.i18nMethods = ${i18nMethodsVar}
236
+ }\n`
237
+ }
218
238
 
219
- output += `global.i18nMethods = require(${loaderUtils.stringifyRequest(loaderContext, i18nWxsRequest)})\n`
239
+ // 为独立分包注入init module
240
+ if (independent && typeof independent === 'string') {
241
+ const independentLoader = normalize.lib('independent-loader.js')
242
+ const independentInitRequest = `!!${independentLoader}!${independent}`
243
+ this._module.addDependency(new CommonJsVariableDependency(independentInitRequest))
220
244
  }
245
+
221
246
  // 注入构造函数
222
247
  let ctor = 'App'
223
248
  if (ctorType === 'page') {
@@ -287,28 +312,17 @@ module.exports = function (content) {
287
312
  // script
288
313
  output += '/* script */\n'
289
314
  let scriptSrcMode = srcMode
290
- const script = parts.script
315
+ // 给予script默认值, 确保生成js request以自动补全js
316
+ const script = parts.script || {}
291
317
  if (script) {
292
318
  scriptSrcMode = script.mode || scriptSrcMode
293
319
  if (scriptSrcMode) output += `global.currentSrcMode = ${JSON.stringify(scriptSrcMode)}\n`
294
- const extraOptions = {}
320
+ // 传递ctorType以补全js内容
321
+ const extraOptions = {
322
+ ctorType
323
+ }
295
324
  if (script.src) extraOptions.resourcePath = resourcePath
296
325
  output += getRequire('script', script, extraOptions) + '\n'
297
- } else {
298
- switch (ctorType) {
299
- case 'app':
300
- output += 'import {createApp} from "@mpxjs/core"\n' +
301
- 'createApp({})\n'
302
- break
303
- case 'page':
304
- output += 'import {createPage} from "@mpxjs/core"\n' +
305
- 'createPage({})\n'
306
- break
307
- case 'component':
308
- output += 'import {createComponent} from "@mpxjs/core"\n' +
309
- 'createComponent({})\n'
310
- }
311
- output += '\n'
312
326
  }
313
327
  callback(null, output)
314
328
  }
@@ -0,0 +1,11 @@
1
+ const parseRequest = require('./utils/parse-request')
2
+ const RecordResourceMapDependency = require('./dependencies/RecordResourceMapDependency')
3
+
4
+ module.exports = function (source) {
5
+ const mpx = this.getMpx()
6
+ const { resourcePath, queryObj } = parseRequest(this.resource)
7
+ const file = mpx.getExtractedFile(this.resource)
8
+ const packageRoot = queryObj.packageRoot || ''
9
+ this._module.addPresentationalDependency(new RecordResourceMapDependency(resourcePath, 'staticResource', file, packageRoot))
10
+ return source
11
+ }
package/lib/selector.js CHANGED
@@ -9,6 +9,7 @@ module.exports = function (content) {
9
9
  return content
10
10
  }
11
11
  const { queryObj } = parseRequest(this.resource)
12
+ const ctorType = queryObj.ctorType
12
13
  const type = queryObj.type
13
14
  const index = queryObj.index || 0
14
15
  const mode = mpx.mode
@@ -24,6 +25,26 @@ module.exports = function (content) {
24
25
  if (Array.isArray(part)) {
25
26
  part = part[index]
26
27
  }
28
+ if (!part) {
29
+ let content = ''
30
+ // 补全js内容
31
+ if (type === 'script') {
32
+ switch (ctorType) {
33
+ case 'app':
34
+ content += 'import {createApp} from "@mpxjs/core"\n' +
35
+ 'createApp({})\n'
36
+ break
37
+ case 'page':
38
+ content += 'import {createPage} from "@mpxjs/core"\n' +
39
+ 'createPage({})\n'
40
+ break
41
+ case 'component':
42
+ content += 'import {createComponent} from "@mpxjs/core"\n' +
43
+ 'createComponent({})\n'
44
+ }
45
+ }
46
+ part = { content }
47
+ }
27
48
  part = part || { content: '' }
28
49
  this.callback(null, part.content, part.map)
29
50
  }
@@ -38,15 +38,14 @@ module.exports = function (css, map) {
38
38
  },
39
39
  config.options
40
40
  )
41
- // ali环境处理host选择器
41
+ // ali平台下处理scoped和host选择器
42
42
  if (mode === 'ali') {
43
+ if (queryObj.scoped) {
44
+ plugins.push(scopeId({ id }))
45
+ }
43
46
  plugins.push(transSpecial({ id }))
44
47
  }
45
48
 
46
- if (queryObj.scoped) {
47
- plugins.push(scopeId({ id }))
48
- }
49
-
50
49
  plugins.push(pluginCondStrip({
51
50
  defs
52
51
  }))
@@ -2039,7 +2039,10 @@ function processElement (el, root, options, meta) {
2039
2039
 
2040
2040
  const pass = isNative || processTemplate(el) || processingTemplate
2041
2041
 
2042
- processScoped(el, options)
2042
+ // 仅ali平台需要scoped模拟样式隔离
2043
+ if (mode === 'ali') {
2044
+ processScoped(el, options)
2045
+ }
2043
2046
 
2044
2047
  if (transAli) {
2045
2048
  processAliExternalClassesHack(el, options)
@@ -132,7 +132,7 @@ module.exports = function (json, {
132
132
  },
133
133
  (result, content, callback) => {
134
134
  const extName = path.extname(result)
135
- if (extName === '.mpx' || extName === '.vue') {
135
+ if (extName === '.mpx') {
136
136
  const parts = parseComponent(content, {
137
137
  filePath: result,
138
138
  needMap: loaderContext.sourceMap,
@@ -113,12 +113,6 @@ module.exports = function (script, {
113
113
  import Vue from 'vue'
114
114
  import VueRouter from 'vue-router'
115
115
  Vue.use(VueRouter)
116
- import BScroll from '@better-scroll/core'
117
- import PullDown from '@better-scroll/pull-down'
118
- import ObserveDOM from '@better-scroll/observe-dom'
119
- BScroll.use(ObserveDOM)
120
- BScroll.use(PullDown)
121
- global.BScroll = BScroll
122
116
  global.getApp = function(){}
123
117
  global.getCurrentPages = function(){
124
118
  if(!global.__mpxRouter) return []
package/lib/wxs/loader.js CHANGED
@@ -47,7 +47,24 @@ module.exports = function () {
47
47
  }
48
48
 
49
49
  const outputOptions = {
50
- filename
50
+ filename,
51
+ // 避免输出的wxs中包含es语法
52
+ environment: {
53
+ // The environment supports arrow functions ('() => { ... }').
54
+ arrowFunction: false,
55
+ // The environment supports BigInt as literal (123n).
56
+ bigIntLiteral: false,
57
+ // The environment supports const and let for variable declarations.
58
+ const: false,
59
+ // The environment supports destructuring ('{ a, b } = obj').
60
+ destructuring: false,
61
+ // The environment supports an async import() function to import EcmaScript modules.
62
+ dynamicImport: false,
63
+ // The environment supports 'for of' iteration ('for (const x of array) { ... }').
64
+ forOf: false,
65
+ // The environment supports ECMAScript Module syntax to import ECMAScript modules (import ... from '...').
66
+ module: false
67
+ }
51
68
  }
52
69
  // wxs文件必须经过pre-loader
53
70
  const request = '!!' + this.remainingRequest
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpxjs/webpack-plugin",
3
- "version": "2.7.0-beta.6",
3
+ "version": "2.7.0",
4
4
  "description": "mpx compile core",
5
5
  "keywords": [
6
6
  "mpx"
@@ -77,5 +77,5 @@
77
77
  "@types/babel-traverse": "^6.25.4",
78
78
  "@types/babel-types": "^7.0.4"
79
79
  },
80
- "gitHead": "c04233503af0b1c7b4410fd03582d9dd883182d9"
80
+ "gitHead": "0f2454782bfca526bd281618b99b9aacb1ca2a75"
81
81
  }