@mpxjs/webpack-plugin 2.9.0-beta.1 → 2.9.0-beta.3

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 (46) hide show
  1. package/lib/dependencies/CommonJsExtractDependency.js +51 -0
  2. package/lib/extractor.js +1 -0
  3. package/lib/helpers.js +9 -1
  4. package/lib/index.js +103 -21
  5. package/lib/json-compiler/helper.js +20 -7
  6. package/lib/json-compiler/index.js +48 -19
  7. package/lib/loader.js +1 -1
  8. package/lib/native-loader.js +18 -6
  9. package/lib/platform/json/wx/index.js +44 -2
  10. package/lib/platform/run-rules.js +2 -1
  11. package/lib/platform/template/normalize-component-rules.js +2 -0
  12. package/lib/platform/template/wx/component-config/fix-html-tag.js +17 -0
  13. package/lib/platform/template/wx/component-config/index.js +2 -0
  14. package/lib/platform/template/wx/index.js +45 -14
  15. package/lib/runtime/base.styl +9 -6
  16. package/lib/runtime/components/web/filterTag.js +9 -30
  17. package/lib/runtime/components/web/getInnerListeners.js +2 -14
  18. package/lib/runtime/components/web/mpx-keep-alive.vue +8 -17
  19. package/lib/runtime/components/web/mpx-movable-view.vue +28 -9
  20. package/lib/runtime/components/web/mpx-picker-view.vue +1 -1
  21. package/lib/runtime/components/web/mpx-scroll-view.vue +21 -10
  22. package/lib/runtime/components/web/mpx-video.vue +123 -89
  23. package/lib/runtime/components/web/mpx-web-view.vue +119 -81
  24. package/lib/runtime/components/wx/default-page.mpx +27 -0
  25. package/lib/runtime/optionProcessor.js +27 -20
  26. package/lib/style-compiler/index.js +5 -1
  27. package/lib/template-compiler/bind-this.js +248 -48
  28. package/lib/template-compiler/compiler.js +69 -109
  29. package/lib/template-compiler/index.js +16 -1
  30. package/lib/utils/dom-tag-config.js +101 -0
  31. package/lib/utils/make-map.js +12 -0
  32. package/lib/utils/string.js +7 -1
  33. package/lib/utils/ts-loader-watch-run-loader-filter.js +1 -1
  34. package/lib/web/processJSON.js +35 -0
  35. package/lib/web/processMainScript.js +1 -1
  36. package/lib/web/processTemplate.js +18 -35
  37. package/lib/web/script-helper.js +5 -2
  38. package/package.json +4 -4
  39. package/lib/json-compiler/default-page.mpx +0 -3
  40. package/lib/template-compiler/preprocessor.js +0 -29
  41. package/lib/wxss/compile-exports.js +0 -52
  42. package/lib/wxss/createResolver.js +0 -36
  43. package/lib/wxss/css-base.js +0 -79
  44. package/lib/wxss/getLocalIdent.js +0 -25
  45. package/lib/wxss/localsLoader.js +0 -44
  46. package/lib/wxss/processCss.js +0 -274
@@ -0,0 +1,51 @@
1
+ const ModuleDependency = require('webpack/lib/dependencies/ModuleDependency')
2
+ const makeSerializable = require('webpack/lib/util/makeSerializable')
3
+
4
+ class CommonJsExtractDependency extends ModuleDependency {
5
+ constructor (request, range) {
6
+ super(request)
7
+ this.range = range
8
+ }
9
+
10
+ get type () {
11
+ return 'mpx cjs extract'
12
+ }
13
+
14
+ get category () {
15
+ return 'commonjs'
16
+ }
17
+ }
18
+
19
+ CommonJsExtractDependency.Template = class CommonJsExtractDependencyTemplate extends (
20
+ ModuleDependency.Template
21
+ ) {
22
+ apply (
23
+ dep,
24
+ source,
25
+ {
26
+ runtimeTemplate,
27
+ moduleGraph,
28
+ chunkGraph,
29
+ runtimeRequirements
30
+ }
31
+ ) {
32
+ let content = ''
33
+ if (!dep.weak) {
34
+ content = runtimeTemplate.moduleExports({
35
+ module: moduleGraph.getModule(dep),
36
+ chunkGraph,
37
+ request: dep.request,
38
+ weak: dep.weak,
39
+ runtimeRequirements
40
+ })
41
+ }
42
+ source.replace(dep.range[0], dep.range[1] - 1, content)
43
+ }
44
+ }
45
+
46
+ makeSerializable(
47
+ CommonJsExtractDependency,
48
+ '@mpxjs/webpack-plugin/lib/dependencies/CommonJsExtractDependency'
49
+ )
50
+
51
+ module.exports = CommonJsExtractDependency
package/lib/extractor.js CHANGED
@@ -116,5 +116,6 @@ module.exports.pitch = async function (remainingRequest) {
116
116
  }
117
117
  }
118
118
 
119
+ if (!resultSource) buildInfo.isEmpty = true
119
120
  return resultSource
120
121
  }
package/lib/helpers.js CHANGED
@@ -20,7 +20,15 @@ module.exports = function createHelpers (loaderContext) {
20
20
  const { mode, env } = loaderContext.getMpx() || {}
21
21
 
22
22
  function getRequire (type, part, extraOptions, index) {
23
- return 'require(' + getRequestString(type, part, extraOptions, index) + ')'
23
+ let extract = false
24
+ switch (type) {
25
+ // eslint-disable-next-line no-fallthrough
26
+ case 'json':
27
+ case 'styles':
28
+ case 'template':
29
+ extract = true
30
+ }
31
+ return (extract ? 'require.extract(' : 'require(') + getRequestString(type, part, extraOptions, index) + ')'
24
32
  }
25
33
 
26
34
  function getImport (type, part, extraOptions, index) {
package/lib/index.js CHANGED
@@ -8,6 +8,7 @@ const ReplaceDependency = require('./dependencies/ReplaceDependency')
8
8
  const NullFactory = require('webpack/lib/NullFactory')
9
9
  const CommonJsVariableDependency = require('./dependencies/CommonJsVariableDependency')
10
10
  const CommonJsAsyncDependency = require('./dependencies/CommonJsAsyncDependency')
11
+ const CommonJsExtractDependency = require('./dependencies/CommonJsExtractDependency')
11
12
  const harmonySpecifierTag = require('webpack/lib/dependencies/HarmonyImportDependencyParserPlugin').harmonySpecifierTag
12
13
  const NormalModule = require('webpack/lib/NormalModule')
13
14
  const EntryPlugin = require('webpack/lib/EntryPlugin')
@@ -123,6 +124,7 @@ class MpxWebpackPlugin {
123
124
  options.resolveMode = options.resolveMode || 'webpack'
124
125
  options.writeMode = options.writeMode || 'changed'
125
126
  options.autoScopeRules = options.autoScopeRules || {}
127
+ options.renderOptimizeRules = options.renderOptimizeRules || {}
126
128
  options.autoVirtualHostRules = options.autoVirtualHostRules || {}
127
129
  options.forceDisableProxyCtor = options.forceDisableProxyCtor || false
128
130
  options.transMpxRules = options.transMpxRules || {
@@ -166,8 +168,16 @@ class MpxWebpackPlugin {
166
168
  }, options.nativeConfig)
167
169
  options.webConfig = options.webConfig || {}
168
170
  options.partialCompile = options.mode !== 'web' && options.partialCompile
171
+ options.asyncSubpackageRules = options.asyncSubpackageRules || null
169
172
  options.retryRequireAsync = options.retryRequireAsync || false
170
173
  options.enableAliRequireAsync = options.enableAliRequireAsync || false
174
+ options.optimizeSize = options.optimizeSize || false
175
+ let proxyComponentEventsRules = []
176
+ const proxyComponentEventsRulesRaw = options.proxyComponentEventsRules
177
+ if (proxyComponentEventsRulesRaw) {
178
+ proxyComponentEventsRules = Array.isArray(proxyComponentEventsRulesRaw) ? proxyComponentEventsRulesRaw : [proxyComponentEventsRulesRaw]
179
+ }
180
+ options.proxyComponentEventsRules = proxyComponentEventsRules
171
181
  this.options = options
172
182
  // Hack for buildDependencies
173
183
  const rawResolveBuildDependencies = FileSystemInfo.prototype.resolveBuildDependencies
@@ -292,6 +302,14 @@ class MpxWebpackPlugin {
292
302
  warnings.push(`webpack options: MpxWebpackPlugin accept options.output.filename to be ${outputFilename} only, custom options.output.filename will be ignored!`)
293
303
  }
294
304
  compiler.options.output.filename = compiler.options.output.chunkFilename = outputFilename
305
+ if (this.options.optimizeSize) {
306
+ compiler.options.optimization.chunkIds = 'total-size'
307
+ compiler.options.optimization.moduleIds = 'natural'
308
+ compiler.options.optimization.mangleExports = 'size'
309
+ compiler.options.output.globalObject = 'g'
310
+ // todo chunkLoadingGlobal不具备项目唯一性,在多构建产物混编时可能存在问题,尤其在支付宝使用全局对象传递的情况下
311
+ compiler.options.output.chunkLoadingGlobal = 'c'
312
+ }
295
313
  }
296
314
 
297
315
  if (!compiler.options.node || !compiler.options.node.global) {
@@ -385,6 +403,7 @@ class MpxWebpackPlugin {
385
403
  const query = parseQuery(obj.query || '?')
386
404
  return query.isPage && !query.type
387
405
  }
406
+
388
407
  // new PartialCompilePlugin(this.options.partialCompile).apply(compiler)
389
408
  compiler.resolverFactory.hooks.resolver.intercept({
390
409
  factory: (type, hook) => {
@@ -393,13 +412,13 @@ class MpxWebpackPlugin {
393
412
  name: 'MpxPartialCompilePlugin',
394
413
  stage: -100
395
414
  }, (obj, resolverContext, callback) => {
396
- if (obj.path.startsWith(require.resolve('./json-compiler/default-page.mpx'))) {
415
+ if (obj.path.startsWith(require.resolve('./runtime/components/wx/default-page.mpx'))) {
397
416
  return callback(null, obj)
398
417
  }
399
418
  if (isResolvingPage(obj) && !matchCondition(obj.path, this.options.partialCompile)) {
400
419
  const infix = obj.query ? '&' : '?'
401
420
  obj.query += `${infix}resourcePath=${obj.path}`
402
- obj.path = require.resolve('./json-compiler/default-page.mpx')
421
+ obj.path = require.resolve('./runtime/components/wx/default-page.mpx')
403
422
  }
404
423
  callback(null, obj)
405
424
  })
@@ -542,6 +561,9 @@ class MpxWebpackPlugin {
542
561
  compilation.dependencyFactories.set(CommonJsAsyncDependency, normalModuleFactory)
543
562
  compilation.dependencyTemplates.set(CommonJsAsyncDependency, new CommonJsAsyncDependency.Template())
544
563
 
564
+ compilation.dependencyFactories.set(CommonJsExtractDependency, normalModuleFactory)
565
+ compilation.dependencyTemplates.set(CommonJsExtractDependency, new CommonJsExtractDependency.Template())
566
+
545
567
  compilation.dependencyFactories.set(RecordVueContentDependency, new NullFactory())
546
568
  compilation.dependencyTemplates.set(RecordVueContentDependency, new RecordVueContentDependency.Template())
547
569
  })
@@ -616,6 +638,7 @@ class MpxWebpackPlugin {
616
638
  appTitle: 'Mpx homepage',
617
639
  attributes: this.options.attributes,
618
640
  externals: this.options.externals,
641
+ renderOptimizeRules: this.options.renderOptimizeRules,
619
642
  useRelativePath: this.options.useRelativePath,
620
643
  removedChunks: [],
621
644
  forceProxyEventRules: this.options.forceProxyEventRules,
@@ -633,6 +656,8 @@ class MpxWebpackPlugin {
633
656
  filename
634
657
  })
635
658
  },
659
+ asyncSubpackageRules: this.options.asyncSubpackageRules,
660
+ proxyComponentEventsRules: this.options.proxyComponentEventsRules,
636
661
  pathHash: (resourcePath) => {
637
662
  if (this.options.pathHashMode === 'relative' && this.options.projectRoot) {
638
663
  return hash(path.relative(this.options.projectRoot, resourcePath))
@@ -694,7 +719,15 @@ class MpxWebpackPlugin {
694
719
  mpx.extractedFilesCache.set(resource, file)
695
720
  return file
696
721
  },
697
- recordResourceMap: ({ resourcePath, resourceType, outputPath, packageRoot = '', recordOnly, warn, error }) => {
722
+ recordResourceMap: ({
723
+ resourcePath,
724
+ resourceType,
725
+ outputPath,
726
+ packageRoot = '',
727
+ recordOnly,
728
+ warn,
729
+ error
730
+ }) => {
698
731
  const packageName = packageRoot || 'main'
699
732
  const resourceMap = mpx[`${resourceType}sMap`] || mpx.otherResourcesMap
700
733
  const currentResourceMap = resourceMap.main ? resourceMap[packageName] = resourceMap[packageName] || {} : resourceMap
@@ -919,6 +952,17 @@ class MpxWebpackPlugin {
919
952
  })
920
953
 
921
954
  compilation.hooks.finishModules.tap('MpxWebpackPlugin', (modules) => {
955
+ // 移除extractor抽取后的空模块
956
+ for (const module of modules) {
957
+ if (module.buildInfo.isEmpty) {
958
+ for (const connection of moduleGraph.getIncomingConnections(module)) {
959
+ if (connection.dependency.type === 'mpx cjs extract') {
960
+ connection.weak = true
961
+ connection.dependency.weak = true
962
+ }
963
+ }
964
+ }
965
+ }
922
966
  // 自动跟进分包配置修改splitChunksPlugin配置
923
967
  if (splitChunksPlugin) {
924
968
  let needInit = false
@@ -1042,13 +1086,22 @@ class MpxWebpackPlugin {
1042
1086
  let request = expr.arguments[0].value
1043
1087
  const range = expr.arguments[0].range
1044
1088
  const context = parser.state.module.context
1045
- const { queryObj } = parseRequest(request)
1046
- if (queryObj.root) {
1089
+ const { queryObj, resourcePath } = parseRequest(request)
1090
+ let tarRoot = queryObj.root
1091
+ if (!tarRoot && mpx.asyncSubpackageRules) {
1092
+ for (const item of mpx.asyncSubpackageRules) {
1093
+ if (matchCondition(resourcePath, item)) {
1094
+ tarRoot = item.root
1095
+ break
1096
+ }
1097
+ }
1098
+ }
1099
+ if (tarRoot) {
1047
1100
  // 删除root query
1048
- request = addQuery(request, {}, false, ['root'])
1101
+ if (queryObj.root) request = addQuery(request, {}, false, ['root'])
1049
1102
  // 目前仅wx和ali支持require.async,ali需要开启enableAliRequireAsync,其余平台使用CommonJsAsyncDependency进行模拟抹平
1050
1103
  if (mpx.enableRequireAsync) {
1051
- const dep = new DynamicEntryDependency(request, 'export', '', queryObj.root, '', context, range, {
1104
+ const dep = new DynamicEntryDependency(request, 'export', '', tarRoot, '', context, range, {
1052
1105
  isRequireAsync: true,
1053
1106
  retryRequireAsync: !!this.options.retryRequireAsync
1054
1107
  })
@@ -1083,6 +1136,31 @@ class MpxWebpackPlugin {
1083
1136
  stage: -1000
1084
1137
  }, (expr, calleeMembers, callExpr) => requireAsyncHandler(callExpr, calleeMembers, expr.arguments))
1085
1138
 
1139
+ const requireExtractHandler = (expr, members, args) => {
1140
+ if (members[0] === 'extract') {
1141
+ const request = expr.arguments[0].value
1142
+ const range = expr.range
1143
+ const dep = new CommonJsExtractDependency(request, range)
1144
+ parser.state.current.addDependency(dep)
1145
+ if (args) parser.walkExpressions(args)
1146
+ return true
1147
+ }
1148
+ }
1149
+
1150
+ parser.hooks.callMemberChain
1151
+ .for('require')
1152
+ .tap({
1153
+ name: 'MpxWebpackPlugin',
1154
+ stage: -2000
1155
+ }, (expr, members) => requireExtractHandler(expr, members))
1156
+
1157
+ parser.hooks.callMemberChainOfCallMemberChain
1158
+ .for('require')
1159
+ .tap({
1160
+ name: 'MpxWebpackPlugin',
1161
+ stage: -2000
1162
+ }, (expr, calleeMembers, callExpr) => requireExtractHandler(callExpr, calleeMembers, expr.arguments))
1163
+
1086
1164
  // hack babel polyfill global
1087
1165
  parser.hooks.statementIf.tap('MpxWebpackPlugin', (expr) => {
1088
1166
  if (/core-js.+microtask/.test(parser.state.module.resource)) {
@@ -1302,6 +1380,8 @@ class MpxWebpackPlugin {
1302
1380
  chunkLoadingGlobal
1303
1381
  } = compilation.outputOptions
1304
1382
 
1383
+ const chunkLoadingGlobalStr = JSON.stringify(chunkLoadingGlobal)
1384
+
1305
1385
  function getTargetFile (file) {
1306
1386
  let targetFile = file
1307
1387
  const queryStringIdx = targetFile.indexOf('?')
@@ -1321,7 +1401,7 @@ class MpxWebpackPlugin {
1321
1401
 
1322
1402
  const originalSource = compilation.assets[chunkFile]
1323
1403
  const source = new ConcatSource()
1324
- source.add(`\nvar ${globalObject} = ${globalObject} || {};\n\n`)
1404
+ source.add(`\nvar ${globalObject} = {};\n`)
1325
1405
 
1326
1406
  relativeChunks.forEach((relativeChunk, index) => {
1327
1407
  const relativeChunkFile = relativeChunk.files.values().next().value
@@ -1338,16 +1418,16 @@ class MpxWebpackPlugin {
1338
1418
  if (compilation.options.entry[chunk.name]) {
1339
1419
  // 在rootChunk中挂载jsonpCallback
1340
1420
  source.add('// process ali subpackages runtime in root chunk\n' +
1341
- 'var context = (function() { return this })() || Function("return this")();\n\n')
1342
- source.add(`context[${JSON.stringify(chunkLoadingGlobal)}] = ${globalObject}[${JSON.stringify(chunkLoadingGlobal)}] = require("${relativePath}");\n`)
1421
+ 'var context = (function() { return this })() || Function("return this")();\n')
1422
+ source.add(`context[${chunkLoadingGlobalStr}] = ${globalObject}[${chunkLoadingGlobalStr}] = require("${relativePath}");\n`)
1343
1423
  } else {
1344
1424
  // 其余chunk中通过context全局传递runtime
1345
1425
  source.add('// process ali subpackages runtime in other chunk\n' +
1346
- 'var context = (function() { return this })() || Function("return this")();\n\n')
1347
- source.add(`${globalObject}[${JSON.stringify(chunkLoadingGlobal)}] = context[${JSON.stringify(chunkLoadingGlobal)}];\n`)
1426
+ 'var context = (function() { return this })() || Function("return this")();\n')
1427
+ source.add(`${globalObject}[${chunkLoadingGlobalStr}] = context[${chunkLoadingGlobalStr}];\n`)
1348
1428
  }
1349
1429
  } else {
1350
- source.add(`${globalObject}[${JSON.stringify(chunkLoadingGlobal)}] = require("${relativePath}");\n`)
1430
+ source.add(`${globalObject}[${chunkLoadingGlobalStr}] = require("${relativePath}");\n`)
1351
1431
  }
1352
1432
  } else {
1353
1433
  source.add(`require("${relativePath}");\n`)
@@ -1355,10 +1435,11 @@ class MpxWebpackPlugin {
1355
1435
  })
1356
1436
 
1357
1437
  if (isRuntime) {
1358
- source.add('var context = (function() { return this })() || Function("return this")();\n')
1359
- source.add(`
1438
+ if (mpx.mode === 'ali' || mpx.mode === 'qq') {
1439
+ source.add(`
1360
1440
  // Fix babel runtime in some quirky environment like ali & qq dev.
1361
1441
  try {
1442
+ var context = (function() { return this })() || Function("return this")();
1362
1443
  if(!context.console){
1363
1444
  context.console = console;
1364
1445
  context.setInterval = setInterval;
@@ -1399,8 +1480,9 @@ try {
1399
1480
  }
1400
1481
  } catch(e){
1401
1482
  }\n`)
1483
+ }
1402
1484
  source.add(originalSource)
1403
- source.add(`\nmodule.exports = ${globalObject}[${JSON.stringify(chunkLoadingGlobal)}];\n`)
1485
+ source.add(`\nmodule.exports = ${globalObject}[${chunkLoadingGlobalStr}];\n`)
1404
1486
  } else {
1405
1487
  source.add(originalSource)
1406
1488
  }
@@ -1458,8 +1540,8 @@ try {
1458
1540
  })
1459
1541
 
1460
1542
  const typeLoaderProcessInfo = {
1461
- styles: ['css-loader', wxssLoaderPath, styleCompilerPath],
1462
- template: ['html-loader', wxmlLoaderPath, templateCompilerPath]
1543
+ styles: ['node_modules/css-loader', wxssLoaderPath, styleCompilerPath],
1544
+ template: ['node_modules/html-loader', wxmlLoaderPath, templateCompilerPath]
1463
1545
  }
1464
1546
 
1465
1547
  // 应用过rules后,注入mpx相关资源编译loader
@@ -1522,15 +1604,15 @@ try {
1522
1604
  if (mpx.mode === 'web') {
1523
1605
  const mpxStyleOptions = queryObj.mpxStyleOptions
1524
1606
  const firstLoader = loaders[0] ? toPosix(loaders[0].loader) : ''
1525
- const isPitcherRequest = firstLoader.includes('vue-loader/lib/loaders/pitcher')
1607
+ const isPitcherRequest = firstLoader.includes('node_modules/vue-loader/lib/loaders/pitcher')
1526
1608
  let cssLoaderIndex = -1
1527
1609
  let vueStyleLoaderIndex = -1
1528
1610
  let mpxStyleLoaderIndex = -1
1529
1611
  loaders.forEach((loader, index) => {
1530
1612
  const currentLoader = toPosix(loader.loader)
1531
- if (currentLoader.includes('css-loader') && cssLoaderIndex === -1) {
1613
+ if (currentLoader.includes('node_modules/css-loader') && cssLoaderIndex === -1) {
1532
1614
  cssLoaderIndex = index
1533
- } else if (currentLoader.includes('vue-loader/lib/loaders/stylePostLoader') && vueStyleLoaderIndex === -1) {
1615
+ } else if (currentLoader.includes('node_modules/vue-loader/lib/loaders/stylePostLoader') && vueStyleLoaderIndex === -1) {
1534
1616
  vueStyleLoaderIndex = index
1535
1617
  } else if (currentLoader.includes(styleCompilerPath) && mpxStyleLoaderIndex === -1) {
1536
1618
  mpxStyleLoaderIndex = index
@@ -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()
@@ -17,9 +18,11 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
17
18
  const getOutputPath = mpx.getOutputPath
18
19
  const mode = mpx.mode
19
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)
25
+ const isScript = ext => /\.(ts|js)$/.test(ext)
23
26
 
24
27
  const dynamicEntryMap = new Map()
25
28
 
@@ -45,23 +48,33 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
45
48
  if (resolveMode === 'native') {
46
49
  component = urlToRequest(component)
47
50
  }
48
-
49
51
  resolve(context, component, loaderContext, (err, resource, info) => {
50
52
  if (err) return callback(err)
51
53
  const { resourcePath, queryObj } = parseRequest(resource)
52
-
54
+ let placeholder = null
53
55
  if (queryObj.root) {
54
56
  // 删除root query
55
57
  resource = addQuery(resource, {}, false, ['root'])
56
58
  // 目前只有微信支持分包异步化
57
- if (enableRequireAsync) tarRoot = queryObj.root
59
+ if (enableRequireAsync) {
60
+ tarRoot = queryObj.root
61
+ }
62
+ } else if (!queryObj.root && asyncSubpackageRules && enableRequireAsync) {
63
+ for (const item of asyncSubpackageRules) {
64
+ if (matchCondition(resourcePath, item)) {
65
+ tarRoot = item.root
66
+ placeholder = item.placeholder
67
+ break
68
+ }
69
+ }
58
70
  }
71
+
59
72
  const parsed = path.parse(resourcePath)
60
73
  const ext = parsed.ext
61
74
  const resourceName = path.join(parsed.dir, parsed.name)
62
75
 
63
76
  if (!outputPath) {
64
- if (ext === '.js' && resourceName.includes('node_modules') && mode !== 'web') {
77
+ if (isScript(ext) && resourceName.includes('node_modules') && mode !== 'web') {
65
78
  let root = info.descriptionFileRoot
66
79
  let name = 'nativeComponent'
67
80
  if (info.descriptionFileData) {
@@ -79,12 +92,12 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
79
92
  outputPath = getOutputPath(resourcePath, 'component')
80
93
  }
81
94
  }
82
- if (ext === '.js' && mode !== 'web') {
95
+ if (isScript(ext) && mode !== 'web') {
83
96
  resource = `!!${nativeLoaderPath}!${resource}`
84
97
  }
85
98
 
86
99
  const entry = getDynamicEntry(resource, 'component', outputPath, tarRoot, relativePath)
87
- callback(null, entry)
100
+ callback(null, entry, tarRoot, placeholder)
88
101
  })
89
102
  }
90
103
 
@@ -119,7 +132,7 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
119
132
  outputPath = /^(.*?)(\.[^.]*)?$/.exec(relative)[1]
120
133
  }
121
134
  }
122
- if (ext === '.js' && mode !== 'web') {
135
+ if (isScript(ext) && mode !== 'web') {
123
136
  resource = `!!${nativeLoaderPath}!${resource}`
124
137
  }
125
138
  const entry = getDynamicEntry(resource, 'page', outputPath, tarRoot, publicPath + tarRoot)
@@ -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,
@@ -134,6 +154,9 @@ module.exports = function (content) {
134
154
  if (!json.usingComponents) {
135
155
  json.usingComponents = {}
136
156
  }
157
+ if (!json.component && mode === 'swan') {
158
+ json.component = true
159
+ }
137
160
  }
138
161
  } else if (componentsMap[resourcePath]) {
139
162
  // component
@@ -142,22 +165,6 @@ module.exports = function (content) {
142
165
  }
143
166
  }
144
167
 
145
- // 校验异步组件占位符 componentPlaceholder 不为空
146
- if (mpx.enableRequireAsync) {
147
- const { usingComponents, componentPlaceholder = {} } = json
148
- if (usingComponents) {
149
- for (const compName in usingComponents) {
150
- const compPath = usingComponents[compName]
151
- if (!/\?root=/g.test(compPath)) continue
152
- const compPlaceholder = componentPlaceholder[compName]
153
- if (!compPlaceholder) {
154
- const errMsg = `componentPlaceholder of "${compName}" doesn't exist! \n\r`
155
- emitError(errMsg)
156
- }
157
- }
158
- }
159
- }
160
-
161
168
  // 快应用补全json配置,必填项
162
169
  if (mode === 'qa' && isApp) {
163
170
  const defaultConf = {
@@ -204,14 +211,36 @@ module.exports = function (content) {
204
211
  const processComponents = (components, context, callback) => {
205
212
  if (components) {
206
213
  async.eachOf(components, (component, name, callback) => {
207
- processComponent(component, context, { relativePath }, (err, entry) => {
214
+ processComponent(component, context, { relativePath }, (err, entry, root, placeholder) => {
208
215
  if (err === RESOLVE_IGNORED_ERR) {
209
216
  delete components[name]
210
217
  return callback()
211
218
  }
212
219
  if (err) return callback(err)
213
220
  components[name] = entry
214
- callback()
221
+ if (root) {
222
+ if (placeholder) {
223
+ placeholder = normalizePlaceholder(placeholder)
224
+ if (placeholder.resource) {
225
+ processComponent(placeholder.resource, projectRoot, { relativePath }, (err, entry) => {
226
+ if (err) return callback(err)
227
+ fillInComponentPlaceholder(name, placeholder.name, entry)
228
+ callback()
229
+ })
230
+ } else {
231
+ fillInComponentPlaceholder(name, placeholder.name)
232
+ callback()
233
+ }
234
+ } else {
235
+ if (!json.componentPlaceholder || !json.componentPlaceholder[name]) {
236
+ const errMsg = `componentPlaceholder of "${name}" doesn't exist! \n\r`
237
+ emitError(errMsg)
238
+ }
239
+ callback()
240
+ }
241
+ } else {
242
+ callback()
243
+ }
215
244
  })
216
245
  }, callback)
217
246
  } else {
@@ -224,7 +253,7 @@ module.exports = function (content) {
224
253
  const localPages = []
225
254
  const subPackagesCfg = {}
226
255
  const pageKeySet = new Set()
227
- const defaultPagePath = require.resolve('./default-page.mpx')
256
+ const defaultPagePath = require.resolve('../runtime/components/wx/default-page.mpx')
228
257
  const processPages = (pages, context, tarRoot = '', callback) => {
229
258
  if (pages) {
230
259
  const pagesCache = []
package/lib/loader.js CHANGED
@@ -285,7 +285,7 @@ module.exports = function (content) {
285
285
  let ctor = 'App'
286
286
  if (ctorType === 'page') {
287
287
  // swan也默认使用Page构造器
288
- if (mpx.forceUsePageCtor || mode === 'ali' || mode === 'swan') {
288
+ if (mpx.forceUsePageCtor || mode === 'ali') {
289
289
  ctor = 'Page'
290
290
  } else {
291
291
  ctor = 'Component'
@@ -8,7 +8,7 @@ const async = require('async')
8
8
  const { matchCondition } = require('./utils/match-condition')
9
9
  const { JSON_JS_EXT } = require('./utils/const')
10
10
  const getRulesRunner = require('./platform')
11
-
11
+ // todo native-loader考虑与mpx-loader或加强复用,原生组件约等于4个区块都为src的.mpx文件
12
12
  module.exports = function (content) {
13
13
  this.cacheable()
14
14
 
@@ -44,6 +44,8 @@ module.exports = function (content) {
44
44
  scss: '.scss'
45
45
  }
46
46
 
47
+ const TS_EXT = '.ts'
48
+
47
49
  let useJSONJS = false
48
50
  let cssLang = ''
49
51
  const hasScoped = (queryObj.scoped || autoScope) && mode === 'ali'
@@ -54,7 +56,7 @@ module.exports = function (content) {
54
56
  this.resolve(parsed.dir, resourceName + extName, callback)
55
57
  }
56
58
 
57
- function checkCSSLangFiles (callback) {
59
+ function checkCSSLangFile (callback) {
58
60
  const langs = mpx.nativeConfig.cssLangs || ['less', 'stylus', 'scss', 'sass']
59
61
  const results = []
60
62
  async.eachOf(langs, function (lang, i, callback) {
@@ -89,6 +91,15 @@ module.exports = function (content) {
89
91
  })
90
92
  }
91
93
 
94
+ function checkTSFile (callback) {
95
+ checkFileExists(TS_EXT, (err, result) => {
96
+ if (!err && result) {
97
+ typeResourceMap.script = result
98
+ }
99
+ callback()
100
+ })
101
+ }
102
+
92
103
  const emitWarning = (msg) => {
93
104
  this.emitWarning(
94
105
  new Error('[native-loader][' + this.resource + ']: ' + msg)
@@ -105,15 +116,16 @@ module.exports = function (content) {
105
116
  async.waterfall([
106
117
  (callback) => {
107
118
  async.parallel([
108
- checkCSSLangFiles,
109
- checkJSONJSFile
119
+ checkCSSLangFile,
120
+ checkJSONJSFile,
121
+ checkTSFile
110
122
  ], (err) => {
111
123
  callback(err)
112
124
  })
113
125
  },
114
126
  (callback) => {
115
127
  async.forEachOf(typeExtMap, (ext, key, callback) => {
116
- // 检测到jsonjs或cssLang时跳过对应类型文件检测
128
+ // 对应资源存在预处理类型文件时跳过对应的标准文件检测
117
129
  if (typeResourceMap[key]) {
118
130
  return callback()
119
131
  }
@@ -202,7 +214,7 @@ module.exports = function (content) {
202
214
  let ctorType = 'app'
203
215
  if (pagesMap[resourcePath]) {
204
216
  ctorType = 'page'
205
- if (mpx.forceUsePageCtor || mode === 'ali' || mode === 'swan') {
217
+ if (mpx.forceUsePageCtor || mode === 'ali') {
206
218
  ctor = 'Page'
207
219
  } else {
208
220
  ctor = 'Component'