@mpxjs/webpack-plugin 2.7.0-alpha.0 → 2.7.0-alpha.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.
Files changed (108) hide show
  1. package/README.md +1 -1
  2. package/lib/config.js +14 -0
  3. package/lib/dependencies/AddEntryDependency.js +24 -0
  4. package/lib/dependencies/AppEntryDependency.js +2 -0
  5. package/lib/dependencies/CommonJsAsyncDependency.js +51 -0
  6. package/lib/dependencies/CommonJsVariableDependency.js +13 -6
  7. package/lib/dependencies/DynamicEntryDependency.js +85 -41
  8. package/lib/dependencies/FlagPluginDependency.js +1 -0
  9. package/lib/dependencies/RecordIndependentDependency.js +44 -0
  10. package/lib/dependencies/RecordResourceMapDependency.js +62 -0
  11. package/lib/dependencies/RemoveEntryDependency.js +40 -0
  12. package/lib/dependencies/ResolveDependency.js +11 -6
  13. package/lib/extractor.js +17 -7
  14. package/lib/file-loader.js +2 -2
  15. package/lib/helpers.js +6 -12
  16. package/lib/independent-loader.js +52 -0
  17. package/lib/index.js +595 -304
  18. package/lib/json-compiler/helper.js +36 -32
  19. package/lib/json-compiler/index.js +119 -66
  20. package/lib/json-compiler/plugin.js +23 -7
  21. package/lib/loader.js +135 -90
  22. package/lib/native-loader.js +37 -69
  23. package/lib/parser.js +1 -2
  24. package/lib/partial-compile/index.js +35 -0
  25. package/lib/platform/json/wx/index.js +8 -3
  26. package/lib/platform/template/normalize-component-rules.js +2 -3
  27. package/lib/platform/template/wx/component-config/button.js +17 -5
  28. package/lib/platform/template/wx/component-config/image.js +4 -0
  29. package/lib/platform/template/wx/component-config/input.js +4 -0
  30. package/lib/platform/template/wx/component-config/navigator.js +1 -1
  31. package/lib/platform/template/wx/component-config/rich-text.js +4 -0
  32. package/lib/platform/template/wx/component-config/scroll-view.js +4 -0
  33. package/lib/platform/template/wx/component-config/switch.js +4 -0
  34. package/lib/platform/template/wx/component-config/text.js +4 -0
  35. package/lib/platform/template/wx/component-config/textarea.js +5 -0
  36. package/lib/platform/template/wx/component-config/view.js +4 -0
  37. package/lib/platform/template/wx/index.js +149 -3
  38. package/lib/record-loader.js +2 -2
  39. package/lib/resolve-loader.js +4 -1
  40. package/lib/resolver/AddEnvPlugin.js +4 -3
  41. package/lib/resolver/AddModePlugin.js +4 -3
  42. package/lib/resolver/FixDescriptionInfoPlugin.js +28 -0
  43. package/lib/resolver/PackageEntryPlugin.js +23 -36
  44. package/lib/runtime/base.styl +5 -0
  45. package/lib/runtime/components/tenon/getInnerListeners.js +317 -0
  46. package/lib/runtime/components/tenon/tenon-button.vue +305 -0
  47. package/lib/runtime/components/tenon/tenon-image.vue +61 -0
  48. package/lib/runtime/components/tenon/tenon-input.vue +99 -0
  49. package/lib/runtime/components/tenon/tenon-rich-text.vue +21 -0
  50. package/lib/runtime/components/tenon/tenon-scroll-view.vue +124 -0
  51. package/lib/runtime/components/tenon/tenon-switch.vue +91 -0
  52. package/lib/runtime/components/tenon/tenon-text-area.vue +64 -0
  53. package/lib/runtime/components/tenon/tenon-text.vue +64 -0
  54. package/lib/runtime/components/tenon/tenon-view.vue +93 -0
  55. package/lib/runtime/components/tenon/util.js +44 -0
  56. package/lib/runtime/components/web/getInnerListeners.js +51 -45
  57. package/lib/runtime/components/web/mpx-image.vue +20 -5
  58. package/lib/runtime/components/web/mpx-keep-alive.vue +4 -1
  59. package/lib/runtime/components/web/mpx-movable-view.vue +6 -2
  60. package/lib/runtime/components/web/mpx-swiper.vue +37 -8
  61. package/lib/runtime/components/web/mpx-tab-bar-container.vue +2 -2
  62. package/lib/runtime/components/web/mpx-textarea.vue +1 -1
  63. package/lib/runtime/i18n.wxs +28 -8
  64. package/lib/runtime/optionProcessor.js +50 -20
  65. package/lib/runtime/optionProcessor.tenon.js +386 -0
  66. package/lib/runtime/stringify.wxs +6 -4
  67. package/lib/selector.js +23 -5
  68. package/lib/style-compiler/index.js +12 -13
  69. package/lib/style-compiler/load-postcss-config.js +3 -1
  70. package/lib/style-compiler/plugins/conditional-strip.js +68 -65
  71. package/lib/style-compiler/plugins/hm.js +20 -0
  72. package/lib/style-compiler/plugins/rpx.js +43 -37
  73. package/lib/style-compiler/plugins/scope-id.js +79 -72
  74. package/lib/style-compiler/plugins/trans-special.js +25 -18
  75. package/lib/style-compiler/plugins/trim.js +13 -7
  76. package/lib/style-compiler/plugins/vw.js +19 -12
  77. package/lib/template-compiler/bind-this.js +4 -4
  78. package/lib/template-compiler/compiler.js +172 -62
  79. package/lib/template-compiler/index.js +8 -9
  80. package/lib/template-compiler/trans-dynamic-class-expr.js +32 -22
  81. package/lib/tenon/index.js +105 -0
  82. package/lib/tenon/processJSON.js +356 -0
  83. package/lib/tenon/processScript.js +261 -0
  84. package/lib/tenon/processStyles.js +21 -0
  85. package/lib/tenon/processTemplate.js +133 -0
  86. package/lib/utils/const.js +6 -1
  87. package/lib/utils/eval-json-js.js +31 -0
  88. package/lib/utils/get-entry-name.js +3 -3
  89. package/lib/utils/get-json-content.js +42 -0
  90. package/lib/utils/get-relative-path.js +25 -0
  91. package/lib/utils/match-condition.js +4 -1
  92. package/lib/utils/normalize.js +4 -2
  93. package/lib/utils/resolve.js +13 -0
  94. package/lib/web/processJSON.js +113 -144
  95. package/lib/web/processScript.js +45 -38
  96. package/lib/web/processTemplate.js +56 -41
  97. package/lib/wxml/loader.js +1 -6
  98. package/lib/wxs/WxsModuleIdsPlugin.js +11 -14
  99. package/lib/wxs/i18n-loader.js +5 -4
  100. package/lib/wxs/loader.js +87 -56
  101. package/lib/wxs/pre-loader.js +30 -10
  102. package/lib/wxss/loader.js +3 -3
  103. package/lib/wxss/processCss.js +135 -131
  104. package/package.json +23 -17
  105. package/lib/built-in-loader.js +0 -49
  106. package/lib/dependencies/RecordStaticResourceDependency.js +0 -47
  107. package/lib/utils/get-main-compilation.js +0 -6
  108. package/lib/utils/read-json-for-src.js +0 -34
@@ -3,33 +3,31 @@ const normalize = require('../utils/normalize')
3
3
  const nativeLoaderPath = normalize.lib('native-loader')
4
4
  const isUrlRequestRaw = require('../utils/is-url-request')
5
5
  const parseRequest = require('../utils/parse-request')
6
+ const addQuery = require('../utils/add-query')
6
7
  const loaderUtils = require('loader-utils')
8
+ const resolve = require('../utils/resolve')
7
9
 
8
- module.exports = function createJSONHelper ({ loaderContext, emitWarning }) {
10
+ module.exports = function createJSONHelper ({ loaderContext, emitWarning, customGetDynamicEntry }) {
9
11
  const mpx = loaderContext.getMpx()
10
12
  const resolveMode = mpx.resolveMode
11
13
  const externals = mpx.externals
12
14
  const root = mpx.projectRoot
13
- const publicPath = loaderContext._compilation.outputOptions.publicPath || ''
15
+ const publicPath = (loaderContext._compilation && loaderContext._compilation.outputOptions.publicPath) || ''
14
16
  const pathHash = mpx.pathHash
17
+ const getOutputPath = mpx.getOutputPath
18
+ const mode = mpx.mode
15
19
 
16
20
  const isUrlRequest = r => isUrlRequestRaw(r, root, externals)
17
21
  const urlToRequest = r => loaderUtils.urlToRequest(r)
18
22
 
19
- // todo 提供不记录dependency的resolve方法,非必要的情况下不记录dependency,提升缓存利用率
20
- const resolve = (context, request, callback) => {
21
- const { queryObj } = parseRequest(request)
22
- context = queryObj.context || context
23
- return loaderContext.resolve(context, request, callback)
24
- }
25
-
26
23
  const dynamicEntryMap = new Map()
27
24
 
28
25
  let dynamicEntryCount = 0
29
26
 
30
- const getDynamicEntry = (resource, type, outputPath = '', packageRoot = '', relativePath = '') => {
27
+ const getDynamicEntry = (request, type, outputPath = '', packageRoot = '', relativePath = '', context = '') => {
28
+ if (typeof customGetDynamicEntry === 'function') return customGetDynamicEntry(request, type, outputPath, packageRoot, relativePath, context)
31
29
  const key = `mpx_dynamic_entry_${dynamicEntryCount++}`
32
- const value = `__mpx_dynamic_entry__( ${JSON.stringify(resource)},${JSON.stringify(type)},${JSON.stringify(outputPath)},${JSON.stringify(packageRoot)},${JSON.stringify(relativePath)})`
30
+ const value = `__mpx_dynamic_entry__( ${JSON.stringify(request)},${JSON.stringify(type)},${JSON.stringify(outputPath)},${JSON.stringify(packageRoot)},${JSON.stringify(relativePath)},${JSON.stringify(context)})`
33
31
  dynamicEntryMap.set(key, value)
34
32
  return key
35
33
  }
@@ -42,20 +40,27 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning }) {
42
40
  }
43
41
 
44
42
  const processComponent = (component, context, { tarRoot = '', outputPath = '', relativePath = '' }, callback) => {
45
- if (!isUrlRequest(component)) return callback()
43
+ if (!isUrlRequest(component)) return callback(null, component)
46
44
  if (resolveMode === 'native') {
47
45
  component = urlToRequest(component)
48
46
  }
49
47
 
50
- resolve(context, component, (err, resource, info) => {
48
+ resolve(context, component, loaderContext, (err, resource, info) => {
51
49
  if (err) return callback(err)
52
- const resourcePath = parseRequest(resource).resourcePath
50
+ const { resourcePath, queryObj } = parseRequest(resource)
51
+
52
+ if (queryObj.root) {
53
+ // 删除root query
54
+ resource = addQuery(resource, {}, false, ['root'])
55
+ // 目前只有微信支持分包异步化
56
+ if (mode === 'wx') tarRoot = queryObj.root
57
+ }
53
58
  const parsed = path.parse(resourcePath)
54
59
  const ext = parsed.ext
55
60
  const resourceName = path.join(parsed.dir, parsed.name)
56
61
 
57
62
  if (!outputPath) {
58
- if (ext === '.js' && resourceName.includes('node_modules')) {
63
+ if (ext === '.js' && resourceName.includes('node_modules') && mode !== 'web') {
59
64
  let root = info.descriptionFileRoot
60
65
  let name = 'nativeComponent'
61
66
  if (info.descriptionFileData) {
@@ -70,11 +75,10 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning }) {
70
75
  let relative = path.relative(root, resourceName)
71
76
  outputPath = path.join('components', name + pathHash(root), relative)
72
77
  } else {
73
- let componentName = parsed.name
74
- outputPath = path.join('components', componentName + pathHash(resourcePath), componentName)
78
+ outputPath = getOutputPath(resourcePath, 'component')
75
79
  }
76
80
  }
77
- if (ext === '.js') {
81
+ if (ext === '.js' && mode !== 'web') {
78
82
  resource = `!!${nativeLoaderPath}!${resource}`
79
83
  }
80
84
 
@@ -83,43 +87,44 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning }) {
83
87
  })
84
88
  }
85
89
 
86
- const getPageName = (resourcePath, ext) => {
87
- const baseName = path.basename(resourcePath, ext)
88
- return path.join('pages', baseName + pathHash(resourcePath), baseName)
89
- }
90
-
91
90
  const processPage = (page, context, tarRoot = '', callback) => {
92
91
  let aliasPath = ''
93
92
  if (typeof page !== 'string') {
94
93
  aliasPath = page.path
95
94
  page = page.src
96
95
  }
97
- if (!isUrlRequest(page)) return callback()
96
+ if (!isUrlRequest(page)) return callback(null, page)
98
97
  if (resolveMode === 'native') {
99
98
  page = urlToRequest(page)
100
99
  }
101
- resolve(context, page, (err, resource) => {
100
+ // 增加 page 标识
101
+ page = addQuery(page, { isPage: true })
102
+ resolve(context, page, loaderContext, (err, resource) => {
102
103
  if (err) return callback(err)
103
- const { resourcePath } = parseRequest(resource)
104
+ const { resourcePath, queryObj: { isFirst } } = parseRequest(resource)
104
105
  const ext = path.extname(resourcePath)
105
106
  let outputPath
106
107
  if (aliasPath) {
107
- outputPath = aliasPath
108
+ outputPath = aliasPath.replace(/^\//, '')
108
109
  } else {
109
110
  const relative = path.relative(context, resourcePath)
110
111
  if (/^\./.test(relative)) {
111
112
  // 如果当前page不存在于context中,对其进行重命名
112
- outputPath = getPageName(resourcePath, ext)
113
+ outputPath = getOutputPath(resourcePath, 'page')
113
114
  emitWarning(`Current page [${resourcePath}] is not in current pages directory [${context}], the page path will be replaced with [${outputPath}], use ?resolve to get the page path and navigate to it!`)
114
115
  } else {
115
116
  outputPath = /^(.*?)(\.[^.]*)?$/.exec(relative)[1]
116
117
  }
117
118
  }
118
- if (ext === '.js') {
119
+ if (ext === '.js' && mode !== 'web') {
119
120
  resource = `!!${nativeLoaderPath}!${resource}`
120
121
  }
121
122
  const entry = getDynamicEntry(resource, 'page', outputPath, tarRoot, publicPath + tarRoot)
122
- callback(null, entry)
123
+ const key = [resourcePath, outputPath, tarRoot].join('|')
124
+ callback(null, entry, {
125
+ isFirst,
126
+ key
127
+ })
123
128
  })
124
129
  }
125
130
 
@@ -127,7 +132,7 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning }) {
127
132
  if (resolveMode === 'native') {
128
133
  js = urlToRequest(js)
129
134
  }
130
- resolve(context, js, (err, resource) => {
135
+ resolve(context, js, loaderContext, (err, resource) => {
131
136
  if (err) return callback(err)
132
137
  const { resourcePath } = parseRequest(resource)
133
138
  const relative = path.relative(context, resourcePath)
@@ -145,7 +150,6 @@ module.exports = function createJSONHelper ({ loaderContext, emitWarning }) {
145
150
  processDynamicEntry,
146
151
  processPage,
147
152
  processJsExport,
148
- resolve,
149
153
  isUrlRequest,
150
154
  urlToRequest
151
155
  }
@@ -4,15 +4,17 @@ const path = require('path')
4
4
  const parseComponent = require('../parser')
5
5
  const config = require('../config')
6
6
  const parseRequest = require('../utils/parse-request')
7
- const mpxJSON = require('../utils/mpx-json')
7
+ const evalJSONJS = require('../utils/eval-json-js')
8
8
  const fixUsingComponent = require('../utils/fix-using-component')
9
9
  const getRulesRunner = require('../platform/index')
10
10
  const addQuery = require('../utils/add-query')
11
- const readJsonForSrc = require('../utils/read-json-for-src')
11
+ 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 { MPX_DISABLE_EXTRACTOR_CACHE } = require('../utils/const')
15
+ const RecordIndependentDependency = require('../dependencies/RecordIndependentDependency')
16
+ const { MPX_DISABLE_EXTRACTOR_CACHE, RESOLVE_IGNORED_ERR, JSON_JS_EXT } = require('../utils/const')
17
+ const resolve = require('../utils/resolve')
16
18
 
17
19
  module.exports = function (content) {
18
20
  const nativeCallback = this.async()
@@ -27,13 +29,13 @@ module.exports = function (content) {
27
29
  // 微信插件下要求组件使用相对路径
28
30
  const useRelativePath = mpx.isPluginMode || mpx.useRelativePath
29
31
  const { resourcePath, queryObj } = parseRequest(this.resource)
32
+ const useJSONJS = queryObj.useJSONJS || this.resourcePath.endsWith(JSON_JS_EXT)
30
33
  const packageName = queryObj.packageRoot || mpx.currentPackageRoot || 'main'
31
34
  const pagesMap = mpx.pagesMap
32
35
  const componentsMap = mpx.componentsMap[packageName]
33
36
  const appInfo = mpx.appInfo
34
37
  const mode = mpx.mode
35
38
  const env = mpx.env
36
- const defs = mpx.defs
37
39
  const globalSrcMode = mpx.srcMode
38
40
  const localSrcMode = queryObj.mode
39
41
  const srcMode = localSrcMode || globalSrcMode
@@ -55,7 +57,6 @@ module.exports = function (content) {
55
57
  }
56
58
 
57
59
  const {
58
- resolve,
59
60
  isUrlRequest,
60
61
  urlToRequest,
61
62
  processPage,
@@ -95,6 +96,7 @@ module.exports = function (content) {
95
96
  } else {
96
97
  fs.readFile(file, (err, content) => {
97
98
  if (err) return callback(err)
99
+ if (!this._compilation) return callback()
98
100
  let targetPath = path.relative(context, file)
99
101
  this._compilation.assets[targetPath] = {
100
102
  size: function size () {
@@ -121,12 +123,10 @@ module.exports = function (content) {
121
123
  nativeCallback(null, output)
122
124
  }
123
125
 
124
- let json = {}
126
+ let json
125
127
  try {
126
- // 使用了MPXJSON的话先编译
127
- // 此处需要使用真实的resourcePath
128
- if (this.resourcePath.endsWith('.json.js')) {
129
- json = JSON.parse(mpxJSON.compileMPXJSONText({ source: content, defs, filePath: this.resourcePath }))
128
+ if (useJSONJS) {
129
+ json = evalJSONJS(content, this.resourcePath, this)
130
130
  } else {
131
131
  json = JSON5.parse(content || '{}')
132
132
  }
@@ -141,6 +141,9 @@ module.exports = function (content) {
141
141
  if (!json.usingComponents) {
142
142
  json.usingComponents = {}
143
143
  }
144
+ if (!json.component && mode === 'swan') {
145
+ json.component = true
146
+ }
144
147
  }
145
148
  } else if (componentsMap[resourcePath]) {
146
149
  // component
@@ -200,6 +203,10 @@ module.exports = function (content) {
200
203
  if (components) {
201
204
  async.eachOf(components, (component, name, callback) => {
202
205
  processComponent(component, context, { relativePath }, (err, entry) => {
206
+ if (err === RESOLVE_IGNORED_ERR) {
207
+ delete components[name]
208
+ return callback()
209
+ }
203
210
  if (err) return callback(err)
204
211
  components[name] = entry
205
212
  callback()
@@ -214,26 +221,20 @@ module.exports = function (content) {
214
221
  // app.json
215
222
  const localPages = []
216
223
  const subPackagesCfg = {}
217
- // 添加首页标识
218
- if (json.pages && json.pages[0]) {
219
- if (typeof json.pages[0] !== 'string') {
220
- json.pages[0].src = addQuery(json.pages[0].src, { isFirst: true })
221
- } else {
222
- json.pages[0] = addQuery(json.pages[0], { isFirst: true })
223
- }
224
- }
224
+ const pageKeySet = new Set()
225
225
 
226
226
  const processPages = (pages, context, tarRoot = '', callback) => {
227
227
  if (pages) {
228
228
  async.each(pages, (page, callback) => {
229
- const { queryObj } = parseRequest(page)
230
- processPage(page, context, tarRoot, (err, entry) => {
231
- if (err) return callback(err)
229
+ processPage(page, context, tarRoot, (err, entry, { isFirst, key } = {}) => {
230
+ if (err) return callback(err === RESOLVE_IGNORED_ERR ? null : err)
231
+ if (pageKeySet.has(key)) return callback()
232
+ pageKeySet.add(key)
232
233
  if (tarRoot && subPackagesCfg) {
233
234
  subPackagesCfg[tarRoot].pages.push(entry)
234
235
  } else {
235
236
  // 确保首页
236
- if (queryObj.isFirst) {
237
+ if (isFirst) {
237
238
  localPages.unshift(entry)
238
239
  } else {
239
240
  localPages.push(entry)
@@ -253,13 +254,13 @@ module.exports = function (content) {
253
254
  const { queryObj } = parseRequest(packagePath)
254
255
  async.waterfall([
255
256
  (callback) => {
256
- resolve(context, packagePath, (err, result) => {
257
+ resolve(context, packagePath, this, (err, result) => {
258
+ if (err) return callback(err)
257
259
  const { rawResourcePath } = parseRequest(result)
258
260
  callback(err, rawResourcePath)
259
261
  })
260
262
  },
261
263
  (result, callback) => {
262
- this.addDependency(result)
263
264
  fs.readFile(result, (err, content) => {
264
265
  if (err) return callback(err)
265
266
  callback(err, result, content.toString('utf-8'))
@@ -267,24 +268,21 @@ module.exports = function (content) {
267
268
  },
268
269
  (result, content, callback) => {
269
270
  const extName = path.extname(result)
270
- if (extName === '.mpx' || extName === '.vue') {
271
+ if (extName === '.mpx') {
271
272
  const parts = parseComponent(content, {
272
273
  filePath: result,
273
274
  needMap: this.sourceMap,
274
275
  mode,
275
- defs,
276
276
  env
277
277
  })
278
- const json = parts.json || {}
279
- if (json.content) {
280
- content = json.content
281
- } else if (json.src) {
282
- return readJsonForSrc(json.src, this, (content) => {
283
- callback(null, result, content)
284
- })
285
- }
278
+ // 对于通过.mpx文件声明的独立分包,默认将其自身的script block视为init module
279
+ if (queryObj.independent === true) queryObj.independent = result
280
+ getJSONContent(parts.json || {}, this, (err, content) => {
281
+ callback(err, result, content)
282
+ })
283
+ } else {
284
+ callback(null, result, content)
286
285
  }
287
- callback(null, result, content)
288
286
  },
289
287
  (result, content, callback) => {
290
288
  try {
@@ -330,7 +328,9 @@ module.exports = function (content) {
330
328
  callback()
331
329
  }
332
330
  }
333
- ], callback)
331
+ ], (err) => {
332
+ callback(err === RESOLVE_IGNORED_ERR ? null : err)
333
+ })
334
334
  }, callback)
335
335
  } else {
336
336
  callback()
@@ -353,6 +353,31 @@ module.exports = function (content) {
353
353
  return result
354
354
  }
355
355
 
356
+ const recordIndependent = (root, request) => {
357
+ this._module && this._module.addPresentationalDependency(new RecordIndependentDependency(root, request))
358
+ }
359
+
360
+ const processIndependent = (otherConfig, context, tarRoot, callback) => {
361
+ // 支付宝不支持独立分包,无需处理
362
+ const independent = otherConfig.independent
363
+ if (!independent || mode === 'ali') {
364
+ delete otherConfig.independent
365
+ return callback()
366
+ }
367
+ // independent配置为字符串时视为init module
368
+ if (typeof independent === 'string') {
369
+ otherConfig.independent = true
370
+ resolve(context, independent, this, (err, result) => {
371
+ if (err) return callback(err)
372
+ recordIndependent(tarRoot, result)
373
+ callback()
374
+ })
375
+ } else {
376
+ recordIndependent(tarRoot, true)
377
+ callback()
378
+ }
379
+ }
380
+
356
381
  // 为了获取资源的所属子包,该函数需串行执行
357
382
  const processSubPackage = (subPackage, context, callback) => {
358
383
  if (subPackage) {
@@ -364,26 +389,27 @@ module.exports = function (content) {
364
389
  let srcRoot = subPackage.srcRoot || subPackage.root || ''
365
390
  if (!tarRoot || subPackagesCfg[tarRoot]) return callback()
366
391
 
392
+ context = path.join(context, srcRoot)
367
393
  const otherConfig = getOtherConfig(subPackage)
368
- // 支付宝不支持独立分包,无需处理
369
- if (otherConfig.independent && mode !== 'ali') {
370
- mpx.independentSubpackagesMap[tarRoot] = true
371
- }
372
-
373
394
  subPackagesCfg[tarRoot] = {
374
395
  root: tarRoot,
375
- pages: [],
376
- ...otherConfig
396
+ pages: []
377
397
  }
378
- context = path.join(context, srcRoot)
379
398
  async.parallel([
399
+ (callback) => {
400
+ processIndependent(otherConfig, context, tarRoot, callback)
401
+ },
380
402
  (callback) => {
381
403
  processPages(subPackage.pages, context, tarRoot, callback)
382
404
  },
383
405
  (callback) => {
384
406
  processPlugins(subPackage.plugins, context, tarRoot, callback)
385
407
  }
386
- ], callback)
408
+ ], (err) => {
409
+ if (err) return callback(err)
410
+ Object.assign(subPackagesCfg[tarRoot], otherConfig)
411
+ callback()
412
+ })
387
413
  } else {
388
414
  callback()
389
415
  }
@@ -452,17 +478,32 @@ module.exports = function (content) {
452
478
 
453
479
  const processCustomTabBar = (tabBar, context, callback) => {
454
480
  if (tabBar && tabBar.custom) {
455
- processComponent('./custom-tab-bar/index', context, { outputPath: 'custom-tab-bar/index' }, callback)
481
+ processComponent('./custom-tab-bar/index', context, { outputPath: 'custom-tab-bar/index' }, (err, entry) => {
482
+ if (err === RESOLVE_IGNORED_ERR) {
483
+ delete tabBar.custom
484
+ return callback()
485
+ }
486
+ tabBar.custom = entry // hack for javascript parser call hook.
487
+ callback(err)
488
+ })
456
489
  } else {
457
490
  callback()
458
491
  }
459
492
  }
460
493
 
461
- const processPluginGenericsImplementation = (genericsImplementation, context, tarRoot, callback) => {
494
+ const processPluginGenericsImplementation = (plugin, context, tarRoot, callback) => {
495
+ if (!plugin.genericsImplementation) return callback()
462
496
  const relativePath = useRelativePath ? publicPath + tarRoot : ''
463
- async.eachOf(genericsImplementation, (genericComponents, name, callback) => {
497
+ async.eachOf(plugin.genericsImplementation, (genericComponents, name, callback) => {
464
498
  async.eachOf(genericComponents, (genericComponentPath, name, callback) => {
465
- processComponent(genericComponentPath, context, { tarRoot, relativePath }, (err, entry) => {
499
+ processComponent(genericComponentPath, context, {
500
+ tarRoot,
501
+ relativePath
502
+ }, (err, entry) => {
503
+ if (err === RESOLVE_IGNORED_ERR) {
504
+ delete genericComponents[name]
505
+ return callback()
506
+ }
466
507
  if (err) return callback(err)
467
508
  genericComponents[name] = entry
468
509
  })
@@ -471,10 +512,12 @@ module.exports = function (content) {
471
512
  }
472
513
 
473
514
  const processPluginExport = (plugin, context, tarRoot, callback) => {
474
- if (!plugin.export) {
475
- return callback()
476
- }
515
+ if (!plugin.export) return callback()
477
516
  processJsExport(plugin.export, context, tarRoot, (err, entry) => {
517
+ if (err === RESOLVE_IGNORED_ERR) {
518
+ delete plugin.export
519
+ return callback()
520
+ }
478
521
  if (err) return callback(err)
479
522
  plugin.export = entry
480
523
  callback()
@@ -486,31 +529,33 @@ module.exports = function (content) {
486
529
  async.eachOf(plugins, (plugin, name, callback) => {
487
530
  async.parallel([
488
531
  (callback) => {
489
- if (plugin.genericsImplementation) {
490
- processPluginGenericsImplementation(plugin.genericsImplementation, context, tarRoot, callback)
491
- } else {
492
- callback()
493
- }
532
+ processPluginGenericsImplementation(plugin, context, tarRoot, callback)
494
533
  },
495
534
  (callback) => {
496
535
  processPluginExport(plugin, context, tarRoot, callback)
497
536
  }
498
- ], (err) => {
499
- callback(err)
500
- })
537
+ ], callback)
501
538
  }, callback)
502
539
  }
503
540
 
504
541
  async.parallel([
505
542
  (callback) => {
506
- processPlugins(json.plugins, this.context, '', callback)
507
- },
508
- (callback) => {
543
+ // 添加首页标识
544
+ if (json.pages && json.pages[0]) {
545
+ if (typeof json.pages[0] !== 'string') {
546
+ json.pages[0].src = addQuery(json.pages[0].src, { isFirst: true })
547
+ } else {
548
+ json.pages[0] = addQuery(json.pages[0], { isFirst: true })
549
+ }
550
+ }
509
551
  processPages(json.pages, this.context, '', callback)
510
552
  },
511
553
  (callback) => {
512
554
  processComponents(json.usingComponents, this.context, callback)
513
555
  },
556
+ (callback) => {
557
+ processPlugins(json.plugins, this.context, '', callback)
558
+ },
514
559
  (callback) => {
515
560
  processWorkers(json.workers, this.context, callback)
516
561
  },
@@ -530,10 +575,14 @@ module.exports = function (content) {
530
575
  delete json.subPackages
531
576
  json.pages = localPages
532
577
  for (let root in subPackagesCfg) {
533
- if (!json.subPackages) {
534
- json.subPackages = []
578
+ const subPackageCfg = subPackagesCfg[root]
579
+ // 分包不存在 pages,输出 subPackages 字段会报错
580
+ if (subPackageCfg.pages.length) {
581
+ if (!json.subPackages) {
582
+ json.subPackages = []
583
+ }
584
+ json.subPackages.push(subPackageCfg)
535
585
  }
536
- json.subPackages.push(subPackagesCfg[root])
537
586
  }
538
587
  const processOutput = (output) => {
539
588
  output = processDynamicEntry(output)
@@ -551,6 +600,10 @@ module.exports = function (content) {
551
600
  async.eachOf(generics, (generic, name, callback) => {
552
601
  if (generic.default) {
553
602
  processComponent(generic.default, context, { relativePath }, (err, entry) => {
603
+ if (err === RESOLVE_IGNORED_ERR) {
604
+ delete generic.default
605
+ return callback()
606
+ }
554
607
  if (err) return callback(err)
555
608
  generic.default = entry
556
609
  callback()
@@ -2,7 +2,9 @@ const async = require('async')
2
2
  const JSON5 = require('json5')
3
3
  const getEntryName = require('../utils/get-entry-name')
4
4
  const FlagPluginDependency = require('../dependencies/FlagPluginDependency')
5
+ const RemoveEntryDependency = require('../dependencies/RemoveEntryDependency')
5
6
  const createJSONHelper = require('./helper')
7
+ const { MPX_DISABLE_EXTRACTOR_CACHE, RESOLVE_IGNORED_ERR } = require('../utils/const')
6
8
 
7
9
  module.exports = function (source) {
8
10
  // 该loader中会在每次编译中动态添加entry,不能缓存,否则watch不好使
@@ -14,6 +16,9 @@ module.exports = function (source) {
14
16
  return nativeCallback(null, source)
15
17
  }
16
18
 
19
+ // json模块必须每次都创建(但并不是每次都需要build),用于动态添加编译入口,传递信息以禁用父级extractor的缓存
20
+ this.emitFile(MPX_DISABLE_EXTRACTOR_CACHE, '', undefined, { skipEmit: true })
21
+
17
22
  this._module.addPresentationalDependency(new FlagPluginDependency())
18
23
 
19
24
  const emitWarning = (msg) => {
@@ -45,7 +50,7 @@ module.exports = function (source) {
45
50
  const srcMode = mpx.srcMode
46
51
  const entryName = getEntryName(this)
47
52
  // 最终输出中不需要为plugin.json产生chunk,而是使用extractor输出,删除plugin.json对应的entrypoint
48
- if (entryName) this._compilation.entries.delete(entryName)
53
+ if (entryName) this._module.addPresentationalDependency(new RemoveEntryDependency(entryName))
49
54
 
50
55
  // 新模式下plugin.json输出依赖于extractor
51
56
  const callback = (err, processOutput) => {
@@ -66,6 +71,10 @@ module.exports = function (source) {
66
71
  const processMain = (main, callback) => {
67
72
  if (!main) return callback()
68
73
  processJsExport(main, context, '', (err, entry) => {
74
+ if (err === RESOLVE_IGNORED_ERR) {
75
+ delete pluginEntry.main
76
+ return callback()
77
+ }
69
78
  if (err) return callback(err)
70
79
  pluginEntry.main = entry
71
80
  callback()
@@ -76,8 +85,12 @@ module.exports = function (source) {
76
85
  if (!components) return callback()
77
86
  async.eachOf(components, (component, name, callback) => {
78
87
  processComponent(component, context, { relativePath }, (err, entry) => {
88
+ if (err === RESOLVE_IGNORED_ERR) {
89
+ delete components[name]
90
+ return callback()
91
+ }
79
92
  if (err) return callback(err)
80
- pluginEntry.publicComponents[name] = entry
93
+ components[name] = entry
81
94
  callback()
82
95
  })
83
96
  }, callback)
@@ -103,21 +116,24 @@ module.exports = function (source) {
103
116
  pluginEntry.pages = []
104
117
  }
105
118
 
106
- async.eachOf(pages, (page, key) => {
119
+ async.eachOf(pages, (page, key, callback) => {
107
120
  processPage(page, context, '', (err, entry) => {
121
+ if (err === RESOLVE_IGNORED_ERR) {
122
+ delete pages[key]
123
+ return callback()
124
+ }
108
125
  if (err) return callback(err)
109
- pages[key] = entry
110
126
  if (mode === 'ali') {
111
127
  pluginEntry.pages.push(entry)
112
128
  if (!/^__private_page_\d+__$/.test(key)) {
113
129
  pluginEntry.publicPages[key] = entry
114
130
  }
115
131
  } else {
116
- pluginEntry.pages[key] = entry
132
+ pages[key] = entry
117
133
  }
118
134
  callback()
119
135
  })
120
- })
136
+ }, callback)
121
137
  }
122
138
 
123
139
  async.parallel([
@@ -126,7 +142,7 @@ module.exports = function (source) {
126
142
  }, (callback) => {
127
143
  return processComponents(pluginEntry.publicComponents, callback)
128
144
  }, (callback) => {
129
- return processPages(pluginEntry.publicPages, callback)
145
+ return processPages(pluginEntry.pages, callback)
130
146
  }
131
147
  ], (err) => {
132
148
  return callback(err, processDynamicEntry)