@mpxjs/webpack-plugin 2.9.0-beta.2 → 2.9.0-beta.4

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 +82 -18
  5. package/lib/json-compiler/helper.js +4 -3
  6. package/lib/json-compiler/index.js +4 -1
  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 -1
  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 +13 -6
  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 +4 -2
  26. package/lib/style-compiler/index.js +5 -1
  27. package/lib/template-compiler/bind-this.js +273 -47
  28. package/lib/template-compiler/compiler.js +54 -58
  29. package/lib/template-compiler/index.js +35 -23
  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 +8 -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')
@@ -166,9 +167,11 @@ class MpxWebpackPlugin {
166
167
  }, options.nativeConfig)
167
168
  options.webConfig = options.webConfig || {}
168
169
  options.partialCompile = options.mode !== 'web' && options.partialCompile
169
- options.asyncSubpackageRules = options.asyncSubpackageRules || null
170
+ options.asyncSubpackageRules = options.asyncSubpackageRules || []
171
+ options.optimizeRenderRules = options.optimizeRenderRules || {}
170
172
  options.retryRequireAsync = options.retryRequireAsync || false
171
173
  options.enableAliRequireAsync = options.enableAliRequireAsync || false
174
+ options.optimizeSize = options.optimizeSize || false
172
175
  this.options = options
173
176
  // Hack for buildDependencies
174
177
  const rawResolveBuildDependencies = FileSystemInfo.prototype.resolveBuildDependencies
@@ -293,6 +296,14 @@ class MpxWebpackPlugin {
293
296
  warnings.push(`webpack options: MpxWebpackPlugin accept options.output.filename to be ${outputFilename} only, custom options.output.filename will be ignored!`)
294
297
  }
295
298
  compiler.options.output.filename = compiler.options.output.chunkFilename = outputFilename
299
+ if (this.options.optimizeSize) {
300
+ compiler.options.optimization.chunkIds = 'total-size'
301
+ compiler.options.optimization.moduleIds = 'natural'
302
+ compiler.options.optimization.mangleExports = 'size'
303
+ compiler.options.output.globalObject = 'g'
304
+ // todo chunkLoadingGlobal不具备项目唯一性,在多构建产物混编时可能存在问题,尤其在支付宝使用全局对象传递的情况下
305
+ compiler.options.output.chunkLoadingGlobal = 'c'
306
+ }
296
307
  }
297
308
 
298
309
  if (!compiler.options.node || !compiler.options.node.global) {
@@ -386,6 +397,7 @@ class MpxWebpackPlugin {
386
397
  const query = parseQuery(obj.query || '?')
387
398
  return query.isPage && !query.type
388
399
  }
400
+
389
401
  // new PartialCompilePlugin(this.options.partialCompile).apply(compiler)
390
402
  compiler.resolverFactory.hooks.resolver.intercept({
391
403
  factory: (type, hook) => {
@@ -394,13 +406,13 @@ class MpxWebpackPlugin {
394
406
  name: 'MpxPartialCompilePlugin',
395
407
  stage: -100
396
408
  }, (obj, resolverContext, callback) => {
397
- if (obj.path.startsWith(require.resolve('./json-compiler/default-page.mpx'))) {
409
+ if (obj.path.startsWith(require.resolve('./runtime/components/wx/default-page.mpx'))) {
398
410
  return callback(null, obj)
399
411
  }
400
412
  if (isResolvingPage(obj) && !matchCondition(obj.path, this.options.partialCompile)) {
401
413
  const infix = obj.query ? '&' : '?'
402
414
  obj.query += `${infix}resourcePath=${obj.path}`
403
- obj.path = require.resolve('./json-compiler/default-page.mpx')
415
+ obj.path = require.resolve('./runtime/components/wx/default-page.mpx')
404
416
  }
405
417
  callback(null, obj)
406
418
  })
@@ -543,6 +555,9 @@ class MpxWebpackPlugin {
543
555
  compilation.dependencyFactories.set(CommonJsAsyncDependency, normalModuleFactory)
544
556
  compilation.dependencyTemplates.set(CommonJsAsyncDependency, new CommonJsAsyncDependency.Template())
545
557
 
558
+ compilation.dependencyFactories.set(CommonJsExtractDependency, normalModuleFactory)
559
+ compilation.dependencyTemplates.set(CommonJsExtractDependency, new CommonJsExtractDependency.Template())
560
+
546
561
  compilation.dependencyFactories.set(RecordVueContentDependency, new NullFactory())
547
562
  compilation.dependencyTemplates.set(RecordVueContentDependency, new RecordVueContentDependency.Template())
548
563
  })
@@ -635,6 +650,7 @@ class MpxWebpackPlugin {
635
650
  })
636
651
  },
637
652
  asyncSubpackageRules: this.options.asyncSubpackageRules,
653
+ optimizeRenderRules: this.options.optimizeRenderRules,
638
654
  pathHash: (resourcePath) => {
639
655
  if (this.options.pathHashMode === 'relative' && this.options.projectRoot) {
640
656
  return hash(path.relative(this.options.projectRoot, resourcePath))
@@ -696,7 +712,15 @@ class MpxWebpackPlugin {
696
712
  mpx.extractedFilesCache.set(resource, file)
697
713
  return file
698
714
  },
699
- recordResourceMap: ({ resourcePath, resourceType, outputPath, packageRoot = '', recordOnly, warn, error }) => {
715
+ recordResourceMap: ({
716
+ resourcePath,
717
+ resourceType,
718
+ outputPath,
719
+ packageRoot = '',
720
+ recordOnly,
721
+ warn,
722
+ error
723
+ }) => {
700
724
  const packageName = packageRoot || 'main'
701
725
  const resourceMap = mpx[`${resourceType}sMap`] || mpx.otherResourcesMap
702
726
  const currentResourceMap = resourceMap.main ? resourceMap[packageName] = resourceMap[packageName] || {} : resourceMap
@@ -921,6 +945,17 @@ class MpxWebpackPlugin {
921
945
  })
922
946
 
923
947
  compilation.hooks.finishModules.tap('MpxWebpackPlugin', (modules) => {
948
+ // 移除extractor抽取后的空模块
949
+ for (const module of modules) {
950
+ if (module.buildInfo.isEmpty) {
951
+ for (const connection of moduleGraph.getIncomingConnections(module)) {
952
+ if (connection.dependency.type === 'mpx cjs extract') {
953
+ connection.weak = true
954
+ connection.dependency.weak = true
955
+ }
956
+ }
957
+ }
958
+ }
924
959
  // 自动跟进分包配置修改splitChunksPlugin配置
925
960
  if (splitChunksPlugin) {
926
961
  let needInit = false
@@ -1094,6 +1129,31 @@ class MpxWebpackPlugin {
1094
1129
  stage: -1000
1095
1130
  }, (expr, calleeMembers, callExpr) => requireAsyncHandler(callExpr, calleeMembers, expr.arguments))
1096
1131
 
1132
+ const requireExtractHandler = (expr, members, args) => {
1133
+ if (members[0] === 'extract') {
1134
+ const request = expr.arguments[0].value
1135
+ const range = expr.range
1136
+ const dep = new CommonJsExtractDependency(request, range)
1137
+ parser.state.current.addDependency(dep)
1138
+ if (args) parser.walkExpressions(args)
1139
+ return true
1140
+ }
1141
+ }
1142
+
1143
+ parser.hooks.callMemberChain
1144
+ .for('require')
1145
+ .tap({
1146
+ name: 'MpxWebpackPlugin',
1147
+ stage: -2000
1148
+ }, (expr, members) => requireExtractHandler(expr, members))
1149
+
1150
+ parser.hooks.callMemberChainOfCallMemberChain
1151
+ .for('require')
1152
+ .tap({
1153
+ name: 'MpxWebpackPlugin',
1154
+ stage: -2000
1155
+ }, (expr, calleeMembers, callExpr) => requireExtractHandler(callExpr, calleeMembers, expr.arguments))
1156
+
1097
1157
  // hack babel polyfill global
1098
1158
  parser.hooks.statementIf.tap('MpxWebpackPlugin', (expr) => {
1099
1159
  if (/core-js.+microtask/.test(parser.state.module.resource)) {
@@ -1313,6 +1373,8 @@ class MpxWebpackPlugin {
1313
1373
  chunkLoadingGlobal
1314
1374
  } = compilation.outputOptions
1315
1375
 
1376
+ const chunkLoadingGlobalStr = JSON.stringify(chunkLoadingGlobal)
1377
+
1316
1378
  function getTargetFile (file) {
1317
1379
  let targetFile = file
1318
1380
  const queryStringIdx = targetFile.indexOf('?')
@@ -1332,7 +1394,7 @@ class MpxWebpackPlugin {
1332
1394
 
1333
1395
  const originalSource = compilation.assets[chunkFile]
1334
1396
  const source = new ConcatSource()
1335
- source.add(`\nvar ${globalObject} = ${globalObject} || {};\n\n`)
1397
+ source.add(`\nvar ${globalObject} = {};\n`)
1336
1398
 
1337
1399
  relativeChunks.forEach((relativeChunk, index) => {
1338
1400
  const relativeChunkFile = relativeChunk.files.values().next().value
@@ -1349,16 +1411,16 @@ class MpxWebpackPlugin {
1349
1411
  if (compilation.options.entry[chunk.name]) {
1350
1412
  // 在rootChunk中挂载jsonpCallback
1351
1413
  source.add('// process ali subpackages runtime in root chunk\n' +
1352
- 'var context = (function() { return this })() || Function("return this")();\n\n')
1353
- source.add(`context[${JSON.stringify(chunkLoadingGlobal)}] = ${globalObject}[${JSON.stringify(chunkLoadingGlobal)}] = require("${relativePath}");\n`)
1414
+ 'var context = (function() { return this })() || Function("return this")();\n')
1415
+ source.add(`context[${chunkLoadingGlobalStr}] = ${globalObject}[${chunkLoadingGlobalStr}] = require("${relativePath}");\n`)
1354
1416
  } else {
1355
1417
  // 其余chunk中通过context全局传递runtime
1356
1418
  source.add('// process ali subpackages runtime in other chunk\n' +
1357
- 'var context = (function() { return this })() || Function("return this")();\n\n')
1358
- source.add(`${globalObject}[${JSON.stringify(chunkLoadingGlobal)}] = context[${JSON.stringify(chunkLoadingGlobal)}];\n`)
1419
+ 'var context = (function() { return this })() || Function("return this")();\n')
1420
+ source.add(`${globalObject}[${chunkLoadingGlobalStr}] = context[${chunkLoadingGlobalStr}];\n`)
1359
1421
  }
1360
1422
  } else {
1361
- source.add(`${globalObject}[${JSON.stringify(chunkLoadingGlobal)}] = require("${relativePath}");\n`)
1423
+ source.add(`${globalObject}[${chunkLoadingGlobalStr}] = require("${relativePath}");\n`)
1362
1424
  }
1363
1425
  } else {
1364
1426
  source.add(`require("${relativePath}");\n`)
@@ -1366,10 +1428,11 @@ class MpxWebpackPlugin {
1366
1428
  })
1367
1429
 
1368
1430
  if (isRuntime) {
1369
- source.add('var context = (function() { return this })() || Function("return this")();\n')
1370
- source.add(`
1431
+ if (mpx.mode === 'ali' || mpx.mode === 'qq') {
1432
+ source.add(`
1371
1433
  // Fix babel runtime in some quirky environment like ali & qq dev.
1372
1434
  try {
1435
+ var context = (function() { return this })() || Function("return this")();
1373
1436
  if(!context.console){
1374
1437
  context.console = console;
1375
1438
  context.setInterval = setInterval;
@@ -1410,8 +1473,9 @@ try {
1410
1473
  }
1411
1474
  } catch(e){
1412
1475
  }\n`)
1476
+ }
1413
1477
  source.add(originalSource)
1414
- source.add(`\nmodule.exports = ${globalObject}[${JSON.stringify(chunkLoadingGlobal)}];\n`)
1478
+ source.add(`\nmodule.exports = ${globalObject}[${chunkLoadingGlobalStr}];\n`)
1415
1479
  } else {
1416
1480
  source.add(originalSource)
1417
1481
  }
@@ -1469,8 +1533,8 @@ try {
1469
1533
  })
1470
1534
 
1471
1535
  const typeLoaderProcessInfo = {
1472
- styles: ['css-loader', wxssLoaderPath, styleCompilerPath],
1473
- template: ['html-loader', wxmlLoaderPath, templateCompilerPath]
1536
+ styles: ['node_modules/css-loader', wxssLoaderPath, styleCompilerPath],
1537
+ template: ['node_modules/html-loader', wxmlLoaderPath, templateCompilerPath]
1474
1538
  }
1475
1539
 
1476
1540
  // 应用过rules后,注入mpx相关资源编译loader
@@ -1533,15 +1597,15 @@ try {
1533
1597
  if (mpx.mode === 'web') {
1534
1598
  const mpxStyleOptions = queryObj.mpxStyleOptions
1535
1599
  const firstLoader = loaders[0] ? toPosix(loaders[0].loader) : ''
1536
- const isPitcherRequest = firstLoader.includes('vue-loader/lib/loaders/pitcher')
1600
+ const isPitcherRequest = firstLoader.includes('node_modules/vue-loader/lib/loaders/pitcher')
1537
1601
  let cssLoaderIndex = -1
1538
1602
  let vueStyleLoaderIndex = -1
1539
1603
  let mpxStyleLoaderIndex = -1
1540
1604
  loaders.forEach((loader, index) => {
1541
1605
  const currentLoader = toPosix(loader.loader)
1542
- if (currentLoader.includes('css-loader') && cssLoaderIndex === -1) {
1606
+ if (currentLoader.includes('node_modules/css-loader') && cssLoaderIndex === -1) {
1543
1607
  cssLoaderIndex = index
1544
- } else if (currentLoader.includes('vue-loader/lib/loaders/stylePostLoader') && vueStyleLoaderIndex === -1) {
1608
+ } else if (currentLoader.includes('node_modules/vue-loader/lib/loaders/stylePostLoader') && vueStyleLoaderIndex === -1) {
1545
1609
  vueStyleLoaderIndex = index
1546
1610
  } else if (currentLoader.includes(styleCompilerPath) && mpxStyleLoaderIndex === -1) {
1547
1611
  mpxStyleLoaderIndex = index
@@ -22,6 +22,7 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
22
22
 
23
23
  const isUrlRequest = r => isUrlRequestRaw(r, root, externals)
24
24
  const urlToRequest = r => loaderUtils.urlToRequest(r)
25
+ const isScript = ext => /\.(ts|js)$/.test(ext)
25
26
 
26
27
  const dynamicEntryMap = new Map()
27
28
 
@@ -73,7 +74,7 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
73
74
  const resourceName = path.join(parsed.dir, parsed.name)
74
75
 
75
76
  if (!outputPath) {
76
- if (ext === '.js' && resourceName.includes('node_modules') && mode !== 'web') {
77
+ if (isScript(ext) && resourceName.includes('node_modules') && mode !== 'web') {
77
78
  let root = info.descriptionFileRoot
78
79
  let name = 'nativeComponent'
79
80
  if (info.descriptionFileData) {
@@ -91,7 +92,7 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
91
92
  outputPath = getOutputPath(resourcePath, 'component')
92
93
  }
93
94
  }
94
- if (ext === '.js' && mode !== 'web') {
95
+ if (isScript(ext) && mode !== 'web') {
95
96
  resource = `!!${nativeLoaderPath}!${resource}`
96
97
  }
97
98
 
@@ -131,7 +132,7 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning, custom
131
132
  outputPath = /^(.*?)(\.[^.]*)?$/.exec(relative)[1]
132
133
  }
133
134
  }
134
- if (ext === '.js' && mode !== 'web') {
135
+ if (isScript(ext) && mode !== 'web') {
135
136
  resource = `!!${nativeLoaderPath}!${resource}`
136
137
  }
137
138
  const entry = getDynamicEntry(resource, 'page', outputPath, tarRoot, publicPath + tarRoot)
@@ -154,6 +154,9 @@ module.exports = function (content) {
154
154
  if (!json.usingComponents) {
155
155
  json.usingComponents = {}
156
156
  }
157
+ if (!json.component && mode === 'swan') {
158
+ json.component = true
159
+ }
157
160
  }
158
161
  } else if (componentsMap[resourcePath]) {
159
162
  // component
@@ -250,7 +253,7 @@ module.exports = function (content) {
250
253
  const localPages = []
251
254
  const subPackagesCfg = {}
252
255
  const pageKeySet = new Set()
253
- const defaultPagePath = require.resolve('./default-page.mpx')
256
+ const defaultPagePath = require.resolve('../runtime/components/wx/default-page.mpx')
254
257
  const processPages = (pages, context, tarRoot = '', callback) => {
255
258
  if (pages) {
256
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'
@@ -3,6 +3,7 @@ const normalizeTest = require('../normalize-test')
3
3
  const changeKey = require('../change-key')
4
4
  const normalize = require('../../../utils/normalize')
5
5
  const { capitalToHyphen } = require('../../../utils/string')
6
+ const { isOriginTag } = require('../../../utils/dom-tag-config')
6
7
 
7
8
  const mpxViewPath = normalize.lib('runtime/components/ali/mpx-view.mpx')
8
9
  const mpxTextPath = normalize.lib('runtime/components/ali/mpx-text.mpx')
@@ -70,6 +71,19 @@ module.exports = function getSpec ({ warn, error }) {
70
71
  return input
71
72
  }
72
73
 
74
+ // 校验输出支付宝 componentGenerics 配置的正确性
75
+ function aliComponentGenericsValidate (input) {
76
+ const componentGenerics = input.componentGenerics
77
+ if (componentGenerics && typeof componentGenerics === 'object') {
78
+ Object.keys(componentGenerics).forEach(key => {
79
+ if (!componentGenerics[key].default) {
80
+ error(`Ali environment componentGenerics need to specify a default custom component! please check the configuration of component ${key}`)
81
+ }
82
+ })
83
+ }
84
+ return input
85
+ }
86
+
73
87
  function fillGlobalComponents (input, { globalComponents }) {
74
88
  if (globalComponents) {
75
89
  Object.assign(globalComponents, input.usingComponents)
@@ -112,10 +126,30 @@ module.exports = function getSpec ({ warn, error }) {
112
126
  }
113
127
  }
114
128
 
129
+ /**
130
+ * 将小程序代码中使用的与原生 HTML tag 同名组件进行转化,以解决与原生tag命名冲突问题。
131
+ * @param {string} type usingComponents
132
+ * @returns input
133
+ */
134
+ function webHTMLTagProcesser (type) {
135
+ return function (input) {
136
+ const usingComponents = input[type]
137
+ if (usingComponents) {
138
+ Object.keys(usingComponents).forEach(tag => {
139
+ if (isOriginTag(tag)) {
140
+ usingComponents[`mpx-com-${tag}`] = usingComponents[tag]
141
+ delete usingComponents[tag]
142
+ }
143
+ })
144
+ }
145
+ return input
146
+ }
147
+ }
148
+
115
149
  const componentRules = [
116
150
  {
117
151
  test: 'componentGenerics',
118
- ali: deletePath(true)
152
+ ali: aliComponentGenericsValidate
119
153
  },
120
154
  {
121
155
  test: 'componentPlaceholder',
@@ -124,6 +158,10 @@ module.exports = function getSpec ({ warn, error }) {
124
158
  tt: deletePath(),
125
159
  jd: deletePath()
126
160
  },
161
+ {
162
+ test: 'usingComponents',
163
+ web: webHTMLTagProcesser('usingComponents')
164
+ },
127
165
  {
128
166
  test: 'usingComponents',
129
167
  ali: componentNameCapitalToHyphen('usingComponents'),
@@ -224,7 +262,7 @@ module.exports = function getSpec ({ warn, error }) {
224
262
  }
225
263
 
226
264
  const spec = {
227
- supportedModes: ['ali', 'swan', 'qq', 'tt', 'jd', 'qa', 'dd'],
265
+ supportedModes: ['ali', 'swan', 'qq', 'tt', 'jd', 'qa', 'dd', 'web'],
228
266
  normalizeTest,
229
267
  page: [
230
268
  ...windowRules,
@@ -325,6 +363,10 @@ module.exports = function getSpec ({ warn, error }) {
325
363
  tt: deletePath(),
326
364
  jd: deletePath(true)
327
365
  },
366
+ {
367
+ test: 'usingComponents',
368
+ web: webHTMLTagProcesser('usingComponents')
369
+ },
328
370
  {
329
371
  test: 'usingComponents',
330
372
  ali: componentNameCapitalToHyphen('usingComponents'),
@@ -32,7 +32,8 @@ module.exports = function runRules (rules = [], input, options = {}) {
32
32
  if (result !== undefined) {
33
33
  input = result
34
34
  }
35
- if (!waterfall) break
35
+ // rule 内外 waterfall 均为 false 时跳过
36
+ if (!rule.waterfall && !waterfall) break
36
37
  }
37
38
  }
38
39
  return input
@@ -11,6 +11,8 @@ module.exports = function normalizeComponentRules (cfgs, spec) {
11
11
  if (cfg.test) {
12
12
  result.test = cfg.test
13
13
  }
14
+ // 透传 waterfall 信息
15
+ if (cfg.waterfall) result.waterfall = cfg.waterfall
14
16
  const supportedModes = cfg.supportedModes || spec.supportedModes
15
17
  // 合并component-config中组件的event 与index中公共的event规则
16
18
  const eventRules = (cfg.event || []).concat(spec.event.rules)
@@ -0,0 +1,17 @@
1
+ const { isOriginTag } = require('../../../../utils/dom-tag-config')
2
+
3
+ module.exports = function () {
4
+ return {
5
+ waterfall: true,
6
+ test: (input) => isOriginTag(input),
7
+ // 处理原生tag
8
+ web (tag, data = {}) {
9
+ // @see packages/webpack-plugin/lib/platform/json/wx/index.js webHTMLTagProcesser
10
+ const newTag = `mpx-com-${tag}`
11
+ const usingComponents = data.usingComponents || []
12
+ // 存在同名组件,则返回新tag
13
+ if (usingComponents.includes(newTag)) return newTag
14
+ return tag
15
+ }
16
+ }
17
+ }
@@ -39,6 +39,7 @@ const view = require('./view')
39
39
  const webView = require('./web-view')
40
40
  const wxs = require('./wxs')
41
41
  const component = require('./component')
42
+ const fixHTMLTag = require('./fix-html-tag')
42
43
 
43
44
  module.exports = function getComponentConfigs ({ warn, error }) {
44
45
  /**
@@ -79,6 +80,7 @@ module.exports = function getComponentConfigs ({ warn, error }) {
79
80
 
80
81
  // 转换规则只需以微信为基准配置微信和支付宝的差异部分,比如微信和支付宝都支持但是写法不一致,或者微信支持而支付宝不支持的部分(抛出错误或警告)
81
82
  return [
83
+ fixHTMLTag(),
82
84
  ...Nonsupport({ print }),
83
85
  ad({ print }),
84
86
  view({ print }),