@mpxjs/webpack-plugin 2.9.0-beta.0 → 2.9.0-beta.2
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/dependencies/DynamicEntryDependency.js +10 -16
- package/lib/dependencies/ResolveDependency.js +11 -9
- package/lib/index.js +88 -34
- package/lib/json-compiler/default-page.mpx +3 -0
- package/lib/json-compiler/helper.js +22 -7
- package/lib/json-compiler/index.js +74 -26
- package/lib/loader.js +2 -9
- package/lib/native-loader.js +3 -8
- package/lib/parser.js +0 -1
- package/lib/platform/json/wx/index.js +21 -0
- package/lib/platform/template/wx/component-config/component.js +1 -2
- package/lib/platform/template/wx/component-config/hypen-tag-name.js +2 -6
- package/lib/platform/template/wx/component-config/index.js +2 -2
- package/lib/platform/template/wx/index.js +12 -14
- package/lib/runtime/base.styl +0 -5
- package/lib/runtime/components/web/getInnerListeners.js +16 -2
- package/lib/runtime/components/web/mpx-checkbox-group.vue +1 -1
- package/lib/runtime/components/web/mpx-form.vue +2 -2
- package/lib/runtime/components/web/mpx-image.vue +11 -15
- package/lib/runtime/components/web/mpx-movable-view.vue +3 -3
- package/lib/runtime/components/web/mpx-picker-view.vue +5 -5
- package/lib/runtime/components/web/mpx-picker.vue +3 -3
- package/lib/runtime/components/web/mpx-progress.vue +3 -1
- package/lib/runtime/components/web/mpx-radio-group.vue +1 -1
- package/lib/runtime/components/web/mpx-scroll-view.vue +17 -13
- package/lib/runtime/components/web/mpx-slider.vue +4 -4
- package/lib/runtime/components/web/mpx-swiper.vue +3 -3
- package/lib/runtime/components/web/mpx-switch.vue +1 -1
- package/lib/runtime/components/web/mpx-video.vue +14 -28
- package/lib/runtime/components/web/mpx-web-view.vue +4 -4
- package/lib/runtime/optionProcessor.js +23 -18
- package/lib/runtime/stringify.wxs +44 -8
- package/lib/style-compiler/index.js +3 -1
- package/lib/template-compiler/compiler.js +73 -50
- package/lib/utils/ts-loader-watch-run-loader-filter.js +4 -18
- package/lib/wxss/runtime/api.js +18 -19
- package/lib/wxss/runtime/noSourceMaps.js +3 -1
- package/lib/wxss/runtime/sourceMaps.js +8 -7
- package/package.json +3 -3
- package/lib/partial-compile/index.js +0 -35
|
@@ -28,23 +28,10 @@ class DynamicEntryDependency extends NullDependency {
|
|
|
28
28
|
return toPosix([request, entryType, outputPath, packageRoot, relativePath, context, ...range].join('|'))
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
collectDynamicRequest (mpx) {
|
|
32
|
-
if (!this.packageRoot) return
|
|
33
|
-
const curValue = mpx.dynamicEntryInfo[this.packageRoot] = mpx.dynamicEntryInfo[this.packageRoot] || {
|
|
34
|
-
hasPage: false,
|
|
35
|
-
entries: []
|
|
36
|
-
}
|
|
37
|
-
if (this.entryType === 'page') {
|
|
38
|
-
curValue.hasPage = true
|
|
39
|
-
} else {
|
|
40
|
-
curValue.entries.push(this.request)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
31
|
addEntry (compilation, callback) {
|
|
45
32
|
const mpx = compilation.__mpx__
|
|
46
33
|
let { request, entryType, outputPath, relativePath, context, originEntryNode, publicPath, resolver } = this
|
|
47
|
-
|
|
34
|
+
|
|
48
35
|
async.waterfall([
|
|
49
36
|
(callback) => {
|
|
50
37
|
if (context && resolver) {
|
|
@@ -56,12 +43,13 @@ class DynamicEntryDependency extends NullDependency {
|
|
|
56
43
|
}
|
|
57
44
|
},
|
|
58
45
|
(resource, callback) => {
|
|
46
|
+
const { resourcePath } = parseRequest(resource)
|
|
47
|
+
|
|
59
48
|
if (!outputPath) {
|
|
60
|
-
const { resourcePath } = parseRequest(resource)
|
|
61
49
|
outputPath = mpx.getOutputPath(resourcePath, entryType)
|
|
62
50
|
}
|
|
63
51
|
|
|
64
|
-
const { packageRoot, outputPath: filename, alreadyOutputted } = mpx.getPackageInfo({
|
|
52
|
+
const { packageName, packageRoot, outputPath: filename, alreadyOutputted } = mpx.getPackageInfo({
|
|
65
53
|
resource,
|
|
66
54
|
outputPath,
|
|
67
55
|
resourceType: entryType,
|
|
@@ -116,6 +104,12 @@ class DynamicEntryDependency extends NullDependency {
|
|
|
116
104
|
.catch(err => callback(err))
|
|
117
105
|
|
|
118
106
|
mpx.addEntryPromiseMap.set(key, addEntryPromise)
|
|
107
|
+
mpx.collectDynamicEntryInfo({
|
|
108
|
+
resource,
|
|
109
|
+
packageName,
|
|
110
|
+
filename,
|
|
111
|
+
entryType
|
|
112
|
+
})
|
|
119
113
|
}
|
|
120
114
|
}
|
|
121
115
|
], callback)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const NullDependency = require('webpack/lib/dependencies/NullDependency')
|
|
2
2
|
const parseRequest = require('../utils/parse-request')
|
|
3
3
|
const makeSerializable = require('webpack/lib/util/makeSerializable')
|
|
4
|
+
const { matchCondition } = require('../utils/match-condition')
|
|
4
5
|
|
|
5
6
|
class ResolveDependency extends NullDependency {
|
|
6
7
|
constructor (resource, packageName, issuerResource, range) {
|
|
@@ -22,28 +23,29 @@ class ResolveDependency extends NullDependency {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
getResolved () {
|
|
25
|
-
const { resource, packageName, compilation } = this
|
|
26
|
+
const { resource, packageName, compilation, issuerResource } = this
|
|
26
27
|
if (!compilation) return ''
|
|
27
28
|
const mpx = compilation.__mpx__
|
|
28
29
|
if (!mpx) return ''
|
|
29
|
-
const { pagesMap, componentsMap, staticResourcesMap } = mpx
|
|
30
|
+
const { pagesMap, componentsMap, staticResourcesMap, partialCompile } = mpx
|
|
30
31
|
const { resourcePath } = parseRequest(resource)
|
|
31
32
|
const currentComponentsMap = componentsMap[packageName]
|
|
32
33
|
const mainComponentsMap = componentsMap.main
|
|
33
34
|
const currentStaticResourcesMap = staticResourcesMap[packageName]
|
|
34
35
|
const mainStaticResourcesMap = staticResourcesMap.main
|
|
35
|
-
|
|
36
|
+
const resolveResult = pagesMap[resourcePath] || currentComponentsMap[resourcePath] || mainComponentsMap[resourcePath] || currentStaticResourcesMap[resourcePath] || mainStaticResourcesMap[resourcePath] || ''
|
|
37
|
+
if (!resolveResult) {
|
|
38
|
+
if (!partialCompile || matchCondition(resourcePath, partialCompile)) {
|
|
39
|
+
compilation.errors.push(new Error(`Path ${resource} is not a page/component/static resource, which is resolved from ${issuerResource}!`))
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return resolveResult
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
// resolved可能会动态变更,需用此更新hash
|
|
39
46
|
updateHash (hash, context) {
|
|
40
47
|
this.resolved = this.getResolved()
|
|
41
|
-
|
|
42
|
-
if (this.resolved) {
|
|
43
|
-
hash.update(this.resolved)
|
|
44
|
-
} else {
|
|
45
|
-
compilation.errors.push(new Error(`Path ${resource} is not a page/component/static resource, which is resolved from ${issuerResource}!`))
|
|
46
|
-
}
|
|
48
|
+
hash.update(this.resolved)
|
|
47
49
|
super.updateHash(hash, context)
|
|
48
50
|
}
|
|
49
51
|
|
package/lib/index.js
CHANGED
|
@@ -38,7 +38,6 @@ const FlagPluginDependency = require('./dependencies/FlagPluginDependency')
|
|
|
38
38
|
const RemoveEntryDependency = require('./dependencies/RemoveEntryDependency')
|
|
39
39
|
const RecordVueContentDependency = require('./dependencies/RecordVueContentDependency')
|
|
40
40
|
const SplitChunksPlugin = require('webpack/lib/optimize/SplitChunksPlugin')
|
|
41
|
-
const PartialCompilePlugin = require('./partial-compile/index')
|
|
42
41
|
const fixRelative = require('./utils/fix-relative')
|
|
43
42
|
const parseRequest = require('./utils/parse-request')
|
|
44
43
|
const { matchCondition } = require('./utils/match-condition')
|
|
@@ -55,6 +54,7 @@ const jsonThemeCompilerPath = normalize.lib('json-compiler/theme')
|
|
|
55
54
|
const jsonPluginCompilerPath = normalize.lib('json-compiler/plugin')
|
|
56
55
|
const extractorPath = normalize.lib('extractor')
|
|
57
56
|
const async = require('async')
|
|
57
|
+
const { parseQuery } = require('loader-utils')
|
|
58
58
|
const stringifyLoadersAndResource = require('./utils/stringify-loaders-resource')
|
|
59
59
|
const emitFile = require('./utils/emit-file')
|
|
60
60
|
const { MPX_PROCESSED_FLAG, MPX_DISABLE_EXTRACTOR_CACHE } = require('./utils/const')
|
|
@@ -112,7 +112,6 @@ class MpxWebpackPlugin {
|
|
|
112
112
|
constructor (options = {}) {
|
|
113
113
|
options.mode = options.mode || 'wx'
|
|
114
114
|
options.env = options.env || ''
|
|
115
|
-
|
|
116
115
|
options.srcMode = options.srcMode || options.mode
|
|
117
116
|
if (options.mode !== options.srcMode && options.srcMode !== 'wx') {
|
|
118
117
|
errors.push('MpxWebpackPlugin supports srcMode to be "wx" only temporarily!')
|
|
@@ -167,6 +166,7 @@ class MpxWebpackPlugin {
|
|
|
167
166
|
}, options.nativeConfig)
|
|
168
167
|
options.webConfig = options.webConfig || {}
|
|
169
168
|
options.partialCompile = options.mode !== 'web' && options.partialCompile
|
|
169
|
+
options.asyncSubpackageRules = options.asyncSubpackageRules || null
|
|
170
170
|
options.retryRequireAsync = options.retryRequireAsync || false
|
|
171
171
|
options.enableAliRequireAsync = options.enableAliRequireAsync || false
|
|
172
172
|
this.options = options
|
|
@@ -381,7 +381,33 @@ class MpxWebpackPlugin {
|
|
|
381
381
|
let mpx
|
|
382
382
|
|
|
383
383
|
if (this.options.partialCompile) {
|
|
384
|
-
|
|
384
|
+
function isResolvingPage (obj) {
|
|
385
|
+
// valid query should start with '?'
|
|
386
|
+
const query = parseQuery(obj.query || '?')
|
|
387
|
+
return query.isPage && !query.type
|
|
388
|
+
}
|
|
389
|
+
// new PartialCompilePlugin(this.options.partialCompile).apply(compiler)
|
|
390
|
+
compiler.resolverFactory.hooks.resolver.intercept({
|
|
391
|
+
factory: (type, hook) => {
|
|
392
|
+
hook.tap('MpxPartialCompilePlugin', (resolver) => {
|
|
393
|
+
resolver.hooks.result.tapAsync({
|
|
394
|
+
name: 'MpxPartialCompilePlugin',
|
|
395
|
+
stage: -100
|
|
396
|
+
}, (obj, resolverContext, callback) => {
|
|
397
|
+
if (obj.path.startsWith(require.resolve('./json-compiler/default-page.mpx'))) {
|
|
398
|
+
return callback(null, obj)
|
|
399
|
+
}
|
|
400
|
+
if (isResolvingPage(obj) && !matchCondition(obj.path, this.options.partialCompile)) {
|
|
401
|
+
const infix = obj.query ? '&' : '?'
|
|
402
|
+
obj.query += `${infix}resourcePath=${obj.path}`
|
|
403
|
+
obj.path = require.resolve('./json-compiler/default-page.mpx')
|
|
404
|
+
}
|
|
405
|
+
callback(null, obj)
|
|
406
|
+
})
|
|
407
|
+
})
|
|
408
|
+
return hook
|
|
409
|
+
}
|
|
410
|
+
})
|
|
385
411
|
}
|
|
386
412
|
|
|
387
413
|
const getPackageCacheGroup = packageName => {
|
|
@@ -455,17 +481,17 @@ class MpxWebpackPlugin {
|
|
|
455
481
|
}, (compilation, callback) => {
|
|
456
482
|
processSubpackagesEntriesMap(compilation, (err) => {
|
|
457
483
|
if (err) return callback(err)
|
|
458
|
-
const
|
|
459
|
-
for (const
|
|
460
|
-
const entryMap = mpx.dynamicEntryInfo[
|
|
461
|
-
if (!entryMap.hasPage) {
|
|
484
|
+
const checkDynamicEntryInfo = () => {
|
|
485
|
+
for (const packageName in mpx.dynamicEntryInfo) {
|
|
486
|
+
const entryMap = mpx.dynamicEntryInfo[packageName]
|
|
487
|
+
if (packageName !== 'main' && !entryMap.hasPage) {
|
|
462
488
|
// 引用未注册分包的所有资源
|
|
463
|
-
const
|
|
464
|
-
compilation.errors.push(new Error(`资源${
|
|
489
|
+
const resources = entryMap.entries.map(info => info.resource).join(',')
|
|
490
|
+
compilation.errors.push(new Error(`资源${resources}通过分包异步声明为${packageName}分包, 但${packageName}分包未注册或不存在相关页面!`))
|
|
465
491
|
}
|
|
466
492
|
}
|
|
467
493
|
}
|
|
468
|
-
|
|
494
|
+
checkDynamicEntryInfo()
|
|
469
495
|
callback()
|
|
470
496
|
})
|
|
471
497
|
})
|
|
@@ -522,8 +548,8 @@ class MpxWebpackPlugin {
|
|
|
522
548
|
})
|
|
523
549
|
|
|
524
550
|
compiler.hooks.thisCompilation.tap('MpxWebpackPlugin', (compilation, { normalModuleFactory }) => {
|
|
525
|
-
compilation.warnings
|
|
526
|
-
compilation.errors
|
|
551
|
+
compilation.warnings.push(...warnings)
|
|
552
|
+
compilation.errors.push(...errors)
|
|
527
553
|
const moduleGraph = compilation.moduleGraph
|
|
528
554
|
|
|
529
555
|
if (!compilation.__mpx__) {
|
|
@@ -552,7 +578,7 @@ class MpxWebpackPlugin {
|
|
|
552
578
|
subpackagesEntriesMap: {},
|
|
553
579
|
replacePathMap: {},
|
|
554
580
|
exportModules: new Set(),
|
|
555
|
-
//
|
|
581
|
+
// 记录动态添加入口的分包信息
|
|
556
582
|
dynamicEntryInfo: {},
|
|
557
583
|
// 记录entryModule与entryNode的对应关系,用于体积分析
|
|
558
584
|
entryNodeModulesMap: new Map(),
|
|
@@ -594,14 +620,28 @@ class MpxWebpackPlugin {
|
|
|
594
620
|
useRelativePath: this.options.useRelativePath,
|
|
595
621
|
removedChunks: [],
|
|
596
622
|
forceProxyEventRules: this.options.forceProxyEventRules,
|
|
597
|
-
|
|
623
|
+
enableRequireAsync: this.options.mode === 'wx' || (this.options.mode === 'ali' && this.options.enableAliRequireAsync),
|
|
624
|
+
partialCompile: this.options.partialCompile,
|
|
625
|
+
collectDynamicEntryInfo: ({ resource, packageName, filename, entryType }) => {
|
|
626
|
+
const curInfo = mpx.dynamicEntryInfo[packageName] = mpx.dynamicEntryInfo[packageName] || {
|
|
627
|
+
hasPage: false,
|
|
628
|
+
entries: []
|
|
629
|
+
}
|
|
630
|
+
if (entryType === 'page') curInfo.hasPage = true
|
|
631
|
+
curInfo.entries.push({
|
|
632
|
+
entryType,
|
|
633
|
+
resource,
|
|
634
|
+
filename
|
|
635
|
+
})
|
|
636
|
+
},
|
|
637
|
+
asyncSubpackageRules: this.options.asyncSubpackageRules,
|
|
598
638
|
pathHash: (resourcePath) => {
|
|
599
639
|
if (this.options.pathHashMode === 'relative' && this.options.projectRoot) {
|
|
600
640
|
return hash(path.relative(this.options.projectRoot, resourcePath))
|
|
601
641
|
}
|
|
602
642
|
return hash(resourcePath)
|
|
603
643
|
},
|
|
604
|
-
addEntry (request, name, callback) {
|
|
644
|
+
addEntry: (request, name, callback) => {
|
|
605
645
|
const dep = EntryPlugin.createDependency(request, { name })
|
|
606
646
|
compilation.addEntry(compiler.context, dep, { name }, callback)
|
|
607
647
|
return dep
|
|
@@ -761,10 +801,14 @@ class MpxWebpackPlugin {
|
|
|
761
801
|
const rawProcessModuleDependencies = compilation.processModuleDependencies
|
|
762
802
|
compilation.processModuleDependencies = (module, callback) => {
|
|
763
803
|
const presentationalDependencies = module.presentationalDependencies || []
|
|
804
|
+
const errors = []
|
|
764
805
|
async.forEach(presentationalDependencies.filter((dep) => dep.mpxAction), (dep, callback) => {
|
|
765
|
-
dep.mpxAction(module, compilation,
|
|
766
|
-
|
|
767
|
-
|
|
806
|
+
dep.mpxAction(module, compilation, (err) => {
|
|
807
|
+
if (err) errors.push(err)
|
|
808
|
+
callback()
|
|
809
|
+
})
|
|
810
|
+
}, () => {
|
|
811
|
+
compilation.errors.push(...errors)
|
|
768
812
|
rawProcessModuleDependencies.call(compilation, module, callback)
|
|
769
813
|
})
|
|
770
814
|
}
|
|
@@ -850,16 +894,17 @@ class MpxWebpackPlugin {
|
|
|
850
894
|
}
|
|
851
895
|
|
|
852
896
|
// hack process https://github.com/webpack/webpack/issues/16045
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
897
|
+
// no need anymore
|
|
898
|
+
// const _handleModuleBuildAndDependenciesRaw = compilation._handleModuleBuildAndDependencies
|
|
899
|
+
//
|
|
900
|
+
// compilation._handleModuleBuildAndDependencies = (originModule, module, recursive, callback) => {
|
|
901
|
+
// const rawCallback = callback
|
|
902
|
+
// callback = (err) => {
|
|
903
|
+
// if (err) return rawCallback(err)
|
|
904
|
+
// return rawCallback(null, module)
|
|
905
|
+
// }
|
|
906
|
+
// return _handleModuleBuildAndDependenciesRaw.call(compilation, originModule, module, recursive, callback)
|
|
907
|
+
// }
|
|
863
908
|
|
|
864
909
|
const rawEmitAsset = compilation.emitAsset
|
|
865
910
|
|
|
@@ -999,13 +1044,22 @@ class MpxWebpackPlugin {
|
|
|
999
1044
|
let request = expr.arguments[0].value
|
|
1000
1045
|
const range = expr.arguments[0].range
|
|
1001
1046
|
const context = parser.state.module.context
|
|
1002
|
-
const { queryObj } = parseRequest(request)
|
|
1003
|
-
|
|
1047
|
+
const { queryObj, resourcePath } = parseRequest(request)
|
|
1048
|
+
let tarRoot = queryObj.root
|
|
1049
|
+
if (!tarRoot && mpx.asyncSubpackageRules) {
|
|
1050
|
+
for (const item of mpx.asyncSubpackageRules) {
|
|
1051
|
+
if (matchCondition(resourcePath, item)) {
|
|
1052
|
+
tarRoot = item.root
|
|
1053
|
+
break
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
if (tarRoot) {
|
|
1004
1058
|
// 删除root query
|
|
1005
|
-
request = addQuery(request, {}, false, ['root'])
|
|
1006
|
-
// 目前仅wx支持require.async,其余平台使用CommonJsAsyncDependency进行模拟抹平
|
|
1007
|
-
if (mpx.
|
|
1008
|
-
const dep = new DynamicEntryDependency(request, 'export', '',
|
|
1059
|
+
if (queryObj.root) request = addQuery(request, {}, false, ['root'])
|
|
1060
|
+
// 目前仅wx和ali支持require.async,ali需要开启enableAliRequireAsync,其余平台使用CommonJsAsyncDependency进行模拟抹平
|
|
1061
|
+
if (mpx.enableRequireAsync) {
|
|
1062
|
+
const dep = new DynamicEntryDependency(request, 'export', '', tarRoot, '', context, range, {
|
|
1009
1063
|
isRequireAsync: true,
|
|
1010
1064
|
retryRequireAsync: !!this.options.retryRequireAsync
|
|
1011
1065
|
})
|
|
@@ -6,6 +6,7 @@ const parseRequest = require('../utils/parse-request')
|
|
|
6
6
|
const addQuery = require('../utils/add-query')
|
|
7
7
|
const loaderUtils = require('loader-utils')
|
|
8
8
|
const resolve = require('../utils/resolve')
|
|
9
|
+
const { matchCondition } = require('../utils/match-condition')
|
|
9
10
|
|
|
10
11
|
module.exports = function createJSONHelper ({ loaderContext, emitWarning, customGetDynamicEntry }) {
|
|
11
12
|
const mpx = loaderContext.getMpx()
|
|
@@ -16,7 +17,8 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
|
|
|
16
17
|
const pathHash = mpx.pathHash
|
|
17
18
|
const getOutputPath = mpx.getOutputPath
|
|
18
19
|
const mode = mpx.mode
|
|
19
|
-
const
|
|
20
|
+
const enableRequireAsync = mpx.enableRequireAsync
|
|
21
|
+
const asyncSubpackageRules = mpx.asyncSubpackageRules
|
|
20
22
|
|
|
21
23
|
const isUrlRequest = r => isUrlRequestRaw(r, root, externals)
|
|
22
24
|
const urlToRequest = r => loaderUtils.urlToRequest(r)
|
|
@@ -45,17 +47,27 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
|
|
|
45
47
|
if (resolveMode === 'native') {
|
|
46
48
|
component = urlToRequest(component)
|
|
47
49
|
}
|
|
48
|
-
|
|
49
50
|
resolve(context, component, loaderContext, (err, resource, info) => {
|
|
50
51
|
if (err) return callback(err)
|
|
51
52
|
const { resourcePath, queryObj } = parseRequest(resource)
|
|
52
|
-
|
|
53
|
+
let placeholder = null
|
|
53
54
|
if (queryObj.root) {
|
|
54
55
|
// 删除root query
|
|
55
56
|
resource = addQuery(resource, {}, false, ['root'])
|
|
56
57
|
// 目前只有微信支持分包异步化
|
|
57
|
-
if (
|
|
58
|
+
if (enableRequireAsync) {
|
|
59
|
+
tarRoot = queryObj.root
|
|
60
|
+
}
|
|
61
|
+
} else if (!queryObj.root && asyncSubpackageRules && enableRequireAsync) {
|
|
62
|
+
for (const item of asyncSubpackageRules) {
|
|
63
|
+
if (matchCondition(resourcePath, item)) {
|
|
64
|
+
tarRoot = item.root
|
|
65
|
+
placeholder = item.placeholder
|
|
66
|
+
break
|
|
67
|
+
}
|
|
68
|
+
}
|
|
58
69
|
}
|
|
70
|
+
|
|
59
71
|
const parsed = path.parse(resourcePath)
|
|
60
72
|
const ext = parsed.ext
|
|
61
73
|
const resourceName = path.join(parsed.dir, parsed.name)
|
|
@@ -84,7 +96,7 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
|
|
|
84
96
|
}
|
|
85
97
|
|
|
86
98
|
const entry = getDynamicEntry(resource, 'component', outputPath, tarRoot, relativePath)
|
|
87
|
-
callback(null, entry)
|
|
99
|
+
callback(null, entry, tarRoot, placeholder)
|
|
88
100
|
})
|
|
89
101
|
}
|
|
90
102
|
|
|
@@ -101,7 +113,9 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
|
|
|
101
113
|
// 增加 page 标识
|
|
102
114
|
page = addQuery(page, { isPage: true })
|
|
103
115
|
resolve(context, page, loaderContext, (err, resource) => {
|
|
104
|
-
if (err)
|
|
116
|
+
if (err) {
|
|
117
|
+
return callback(err)
|
|
118
|
+
}
|
|
105
119
|
const { resourcePath, queryObj: { isFirst } } = parseRequest(resource)
|
|
106
120
|
const ext = path.extname(resourcePath)
|
|
107
121
|
let outputPath
|
|
@@ -124,7 +138,8 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
|
|
|
124
138
|
const key = [resourcePath, outputPath, tarRoot].join('|')
|
|
125
139
|
callback(null, entry, {
|
|
126
140
|
isFirst,
|
|
127
|
-
key
|
|
141
|
+
key,
|
|
142
|
+
resource
|
|
128
143
|
})
|
|
129
144
|
})
|
|
130
145
|
}
|
|
@@ -38,6 +38,7 @@ module.exports = function (content) {
|
|
|
38
38
|
const globalSrcMode = mpx.srcMode
|
|
39
39
|
const localSrcMode = queryObj.mode
|
|
40
40
|
const srcMode = localSrcMode || globalSrcMode
|
|
41
|
+
const projectRoot = mpx.projectRoot
|
|
41
42
|
|
|
42
43
|
const isApp = !(pagesMap[resourcePath] || componentsMap[resourcePath])
|
|
43
44
|
const publicPath = this._compilation.outputOptions.publicPath || ''
|
|
@@ -55,6 +56,25 @@ module.exports = function (content) {
|
|
|
55
56
|
)
|
|
56
57
|
}
|
|
57
58
|
|
|
59
|
+
const fillInComponentPlaceholder = (name, placeholder, placeholderEntry) => {
|
|
60
|
+
const componentPlaceholder = json.componentPlaceholder || {}
|
|
61
|
+
if (componentPlaceholder[name]) return
|
|
62
|
+
componentPlaceholder[name] = placeholder
|
|
63
|
+
json.componentPlaceholder = componentPlaceholder
|
|
64
|
+
if (placeholderEntry && !json.usingComponents[placeholder]) json.usingComponents[placeholder] = placeholderEntry
|
|
65
|
+
}
|
|
66
|
+
const normalizePlaceholder = (placeholder) => {
|
|
67
|
+
if (typeof placeholder === 'string') {
|
|
68
|
+
placeholder = {
|
|
69
|
+
name: placeholder
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (!placeholder.name) {
|
|
73
|
+
emitError('The asyncSubpackageRules configuration format of @mpxjs/webpack-plugin a is incorrect')
|
|
74
|
+
}
|
|
75
|
+
return placeholder
|
|
76
|
+
}
|
|
77
|
+
|
|
58
78
|
const {
|
|
59
79
|
isUrlRequest,
|
|
60
80
|
urlToRequest,
|
|
@@ -142,20 +162,6 @@ module.exports = function (content) {
|
|
|
142
162
|
}
|
|
143
163
|
}
|
|
144
164
|
|
|
145
|
-
// 校验异步组件占位符 componentPlaceholder 不为空
|
|
146
|
-
const { usingComponents, componentPlaceholder = {} } = json
|
|
147
|
-
if (usingComponents) {
|
|
148
|
-
for (const compName in usingComponents) {
|
|
149
|
-
const compPath = usingComponents[compName]
|
|
150
|
-
if (!/\?root=/g.test(compPath)) continue
|
|
151
|
-
const compPlaceholder = componentPlaceholder[compName]
|
|
152
|
-
if (!compPlaceholder) {
|
|
153
|
-
const errMsg = `componentPlaceholder of "${compName}" doesn't exist! \n\r`
|
|
154
|
-
emitError(errMsg)
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
165
|
// 快应用补全json配置,必填项
|
|
160
166
|
if (mode === 'qa' && isApp) {
|
|
161
167
|
const defaultConf = {
|
|
@@ -175,14 +181,14 @@ module.exports = function (content) {
|
|
|
175
181
|
type: 'json',
|
|
176
182
|
waterfall: true,
|
|
177
183
|
warn: emitWarning,
|
|
178
|
-
error: emitError
|
|
184
|
+
error: emitError,
|
|
185
|
+
data: {
|
|
186
|
+
// polyfill global usingComponents & record globalComponents
|
|
187
|
+
globalComponents: mpx.usingComponents
|
|
188
|
+
}
|
|
179
189
|
}
|
|
180
190
|
if (!isApp) {
|
|
181
191
|
rulesRunnerOptions.mainKey = pagesMap[resourcePath] ? 'page' : 'component'
|
|
182
|
-
// polyfill global usingComponents
|
|
183
|
-
rulesRunnerOptions.data = {
|
|
184
|
-
globalComponents: mpx.usingComponents
|
|
185
|
-
}
|
|
186
192
|
}
|
|
187
193
|
|
|
188
194
|
const rulesRunner = getRulesRunner(rulesRunnerOptions)
|
|
@@ -191,22 +197,47 @@ module.exports = function (content) {
|
|
|
191
197
|
rulesRunner(json)
|
|
192
198
|
}
|
|
193
199
|
|
|
194
|
-
if (isApp
|
|
200
|
+
if (isApp) {
|
|
201
|
+
Object.assign(mpx.usingComponents, json.usingComponents)
|
|
195
202
|
// 在 rulesRunner 运行后保存全局注册组件
|
|
196
|
-
|
|
203
|
+
// todo 其余地方在使用mpx.usingComponents时存在缓存问题,要规避该问题需要在所有使用mpx.usingComponents的loader中添加app resourcePath作为fileDependency,但对于缓存有效率影响巨大
|
|
204
|
+
// todo 需要考虑一种精准控制缓存的方式,仅在全局组件发生变更时才使相关使用方的缓存失效,例如按需在相关模块上动态添加request query?
|
|
205
|
+
this._module.addPresentationalDependency(new RecordGlobalComponentsDependency(mpx.usingComponents, this.context))
|
|
197
206
|
}
|
|
198
207
|
|
|
199
208
|
const processComponents = (components, context, callback) => {
|
|
200
209
|
if (components) {
|
|
201
210
|
async.eachOf(components, (component, name, callback) => {
|
|
202
|
-
processComponent(component, context, { relativePath }, (err, entry) => {
|
|
211
|
+
processComponent(component, context, { relativePath }, (err, entry, root, placeholder) => {
|
|
203
212
|
if (err === RESOLVE_IGNORED_ERR) {
|
|
204
213
|
delete components[name]
|
|
205
214
|
return callback()
|
|
206
215
|
}
|
|
207
216
|
if (err) return callback(err)
|
|
208
217
|
components[name] = entry
|
|
209
|
-
|
|
218
|
+
if (root) {
|
|
219
|
+
if (placeholder) {
|
|
220
|
+
placeholder = normalizePlaceholder(placeholder)
|
|
221
|
+
if (placeholder.resource) {
|
|
222
|
+
processComponent(placeholder.resource, projectRoot, { relativePath }, (err, entry) => {
|
|
223
|
+
if (err) return callback(err)
|
|
224
|
+
fillInComponentPlaceholder(name, placeholder.name, entry)
|
|
225
|
+
callback()
|
|
226
|
+
})
|
|
227
|
+
} else {
|
|
228
|
+
fillInComponentPlaceholder(name, placeholder.name)
|
|
229
|
+
callback()
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
if (!json.componentPlaceholder || !json.componentPlaceholder[name]) {
|
|
233
|
+
const errMsg = `componentPlaceholder of "${name}" doesn't exist! \n\r`
|
|
234
|
+
emitError(errMsg)
|
|
235
|
+
}
|
|
236
|
+
callback()
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
callback()
|
|
240
|
+
}
|
|
210
241
|
})
|
|
211
242
|
}, callback)
|
|
212
243
|
} else {
|
|
@@ -219,14 +250,20 @@ module.exports = function (content) {
|
|
|
219
250
|
const localPages = []
|
|
220
251
|
const subPackagesCfg = {}
|
|
221
252
|
const pageKeySet = new Set()
|
|
222
|
-
|
|
253
|
+
const defaultPagePath = require.resolve('./default-page.mpx')
|
|
223
254
|
const processPages = (pages, context, tarRoot = '', callback) => {
|
|
224
255
|
if (pages) {
|
|
256
|
+
const pagesCache = []
|
|
225
257
|
async.each(pages, (page, callback) => {
|
|
226
|
-
processPage(page, context, tarRoot, (err, entry, { isFirst, key } = {}) => {
|
|
258
|
+
processPage(page, context, tarRoot, (err, entry, { isFirst, key, resource } = {}) => {
|
|
227
259
|
if (err) return callback(err === RESOLVE_IGNORED_ERR ? null : err)
|
|
228
260
|
if (pageKeySet.has(key)) return callback()
|
|
261
|
+
if (resource.startsWith(defaultPagePath)) {
|
|
262
|
+
pagesCache.push(entry)
|
|
263
|
+
return callback()
|
|
264
|
+
}
|
|
229
265
|
pageKeySet.add(key)
|
|
266
|
+
|
|
230
267
|
if (tarRoot && subPackagesCfg) {
|
|
231
268
|
subPackagesCfg[tarRoot].pages.push(entry)
|
|
232
269
|
} else {
|
|
@@ -239,7 +276,18 @@ module.exports = function (content) {
|
|
|
239
276
|
}
|
|
240
277
|
callback()
|
|
241
278
|
})
|
|
242
|
-
},
|
|
279
|
+
}, () => {
|
|
280
|
+
if (tarRoot && subPackagesCfg) {
|
|
281
|
+
if (!subPackagesCfg[tarRoot].pages.length && pagesCache[0]) {
|
|
282
|
+
subPackagesCfg[tarRoot].pages.push(pagesCache[0])
|
|
283
|
+
}
|
|
284
|
+
} else {
|
|
285
|
+
if (!localPages.length && pagesCache[0]) {
|
|
286
|
+
localPages.push(pagesCache[0])
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
callback()
|
|
290
|
+
})
|
|
243
291
|
} else {
|
|
244
292
|
callback()
|
|
245
293
|
}
|
package/lib/loader.js
CHANGED
|
@@ -119,7 +119,6 @@ module.exports = function (content) {
|
|
|
119
119
|
|
|
120
120
|
let usingComponents = [].concat(Object.keys(mpx.usingComponents))
|
|
121
121
|
let componentPlaceholder = []
|
|
122
|
-
|
|
123
122
|
let componentGenerics = {}
|
|
124
123
|
|
|
125
124
|
if (parts.json && parts.json.content) {
|
|
@@ -133,18 +132,12 @@ module.exports = function (content) {
|
|
|
133
132
|
}
|
|
134
133
|
if (!isApp) {
|
|
135
134
|
rulesRunnerOptions.mainKey = pagesMap[resourcePath] ? 'page' : 'component'
|
|
136
|
-
// polyfill global usingComponents
|
|
137
|
-
// 预读json时无需注入polyfill全局组件
|
|
138
|
-
// rulesRunnerOptions.data = {
|
|
139
|
-
// globalComponents: mpx.usingComponents
|
|
140
|
-
// }
|
|
141
135
|
}
|
|
142
|
-
|
|
136
|
+
const rulesRunner = getRulesRunner(rulesRunnerOptions)
|
|
143
137
|
try {
|
|
144
138
|
const ret = JSON5.parse(parts.json.content)
|
|
139
|
+
if (rulesRunner) rulesRunner(ret)
|
|
145
140
|
if (ret.usingComponents) {
|
|
146
|
-
const rulesRunner = getRulesRunner(rulesRunnerOptions)
|
|
147
|
-
if (rulesRunner) rulesRunner(ret)
|
|
148
141
|
usingComponents = usingComponents.concat(Object.keys(ret.usingComponents))
|
|
149
142
|
}
|
|
150
143
|
if (ret.componentPlaceholder) {
|
package/lib/native-loader.js
CHANGED
|
@@ -137,6 +137,7 @@ module.exports = function (content) {
|
|
|
137
137
|
} catch (e) {
|
|
138
138
|
return callback(e)
|
|
139
139
|
}
|
|
140
|
+
let usingComponents = Object.keys(mpx.usingComponents)
|
|
140
141
|
const rulesRunnerOptions = {
|
|
141
142
|
mode,
|
|
142
143
|
srcMode,
|
|
@@ -147,16 +148,10 @@ module.exports = function (content) {
|
|
|
147
148
|
}
|
|
148
149
|
if (!isApp) {
|
|
149
150
|
rulesRunnerOptions.mainKey = pagesMap[resourcePath] ? 'page' : 'component'
|
|
150
|
-
// polyfill global usingComponents
|
|
151
|
-
// 预读json时无需注入polyfill全局组件
|
|
152
|
-
// rulesRunnerOptions.data = {
|
|
153
|
-
// globalComponents: mpx.usingComponents
|
|
154
|
-
// }
|
|
155
151
|
}
|
|
156
|
-
|
|
152
|
+
const rulesRunner = getRulesRunner(rulesRunnerOptions)
|
|
153
|
+
if (rulesRunner) rulesRunner(json)
|
|
157
154
|
if (json.usingComponents) {
|
|
158
|
-
const rulesRunner = getRulesRunner(rulesRunnerOptions)
|
|
159
|
-
if (rulesRunner) rulesRunner(json)
|
|
160
155
|
usingComponents = usingComponents.concat(Object.keys(json.usingComponents))
|
|
161
156
|
}
|
|
162
157
|
const {
|
package/lib/parser.js
CHANGED
|
@@ -70,6 +70,13 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
70
70
|
return input
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
function fillGlobalComponents (input, { globalComponents }) {
|
|
74
|
+
if (globalComponents) {
|
|
75
|
+
Object.assign(globalComponents, input.usingComponents)
|
|
76
|
+
}
|
|
77
|
+
return input
|
|
78
|
+
}
|
|
79
|
+
|
|
73
80
|
// 处理 ali swan 的组件名大写字母转连字符:WordExample/wordExample -> word-example
|
|
74
81
|
function componentNameCapitalToHyphen (type) {
|
|
75
82
|
return function (input) {
|
|
@@ -318,6 +325,20 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
318
325
|
tt: deletePath(),
|
|
319
326
|
jd: deletePath(true)
|
|
320
327
|
},
|
|
328
|
+
{
|
|
329
|
+
test: 'usingComponents',
|
|
330
|
+
ali: componentNameCapitalToHyphen('usingComponents'),
|
|
331
|
+
swan: componentNameCapitalToHyphen('usingComponents')
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
test: 'usingComponents',
|
|
335
|
+
// todo ali 2.0已支持全局组件,待移除
|
|
336
|
+
ali: fillGlobalComponents,
|
|
337
|
+
qq: fillGlobalComponents,
|
|
338
|
+
swan: fillGlobalComponents,
|
|
339
|
+
tt: fillGlobalComponents,
|
|
340
|
+
jd: fillGlobalComponents
|
|
341
|
+
},
|
|
321
342
|
{
|
|
322
343
|
test: 'usingComponents',
|
|
323
344
|
// todo ali 2.0已支持全局组件,待移除
|