@mpxjs/webpack-plugin 2.6.114-alpha.4 → 2.6.114-alpha.7

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 (104) hide show
  1. package/lib/{dependency → dependencies}/AddEntryDependency.js +0 -0
  2. package/lib/dependencies/AppEntryDependency.js +58 -0
  3. package/lib/dependencies/CommonJsAsyncDependency.js +51 -0
  4. package/lib/dependencies/CommonJsVariableDependency.js +81 -0
  5. package/lib/dependencies/DynamicEntryDependency.js +171 -0
  6. package/lib/dependencies/FlagPluginDependency.js +24 -0
  7. package/lib/dependencies/InjectDependency.js +43 -0
  8. package/lib/dependencies/RecordGlobalComponentsDependency.js +50 -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/{dependency → dependencies}/ReplaceDependency.js +19 -2
  13. package/lib/dependencies/ResolveDependency.js +88 -0
  14. package/lib/extractor.js +82 -178
  15. package/lib/file-loader.js +7 -19
  16. package/lib/helpers.js +39 -334
  17. package/lib/independent-loader.js +52 -0
  18. package/lib/index.js +864 -541
  19. package/lib/json-compiler/helper.js +156 -0
  20. package/lib/json-compiler/index.js +242 -451
  21. package/lib/json-compiler/plugin.js +150 -0
  22. package/lib/json-compiler/{theme-loader.js → theme.js} +5 -3
  23. package/lib/loader.js +137 -240
  24. package/lib/native-loader.js +71 -133
  25. package/lib/parser.js +1 -2
  26. package/lib/partial-compile/index.js +35 -0
  27. package/lib/platform/json/wx/index.js +1 -1
  28. package/lib/platform/template/normalize-component-rules.js +2 -3
  29. package/lib/platform/template/wx/index.js +30 -4
  30. package/lib/record-loader.js +11 -0
  31. package/lib/{path-loader.js → resolve-loader.js} +0 -0
  32. package/lib/resolver/AddEnvPlugin.js +4 -3
  33. package/lib/resolver/AddModePlugin.js +4 -3
  34. package/lib/resolver/FixDescriptionInfoPlugin.js +28 -0
  35. package/lib/resolver/PackageEntryPlugin.js +23 -36
  36. package/lib/runtime/base.styl +5 -0
  37. package/lib/runtime/components/tenon/tenon-button.vue +1 -1
  38. package/lib/runtime/components/tenon/tenon-image.vue +1 -1
  39. package/lib/runtime/components/tenon/tenon-input.vue +1 -1
  40. package/lib/runtime/components/tenon/tenon-switch.vue +1 -1
  41. package/lib/runtime/components/tenon/tenon-text-area.vue +1 -1
  42. package/lib/runtime/components/tenon/tenon-text.vue +1 -1
  43. package/lib/runtime/components/web/mpx-image.vue +20 -5
  44. package/lib/runtime/components/web/mpx-movable-view.vue +6 -2
  45. package/lib/runtime/components/web/mpx-swiper.vue +18 -3
  46. package/lib/runtime/i18n.wxs +31 -11
  47. package/lib/runtime/optionProcessor.js +48 -3
  48. package/lib/selector.js +29 -10
  49. package/lib/style-compiler/index.js +15 -23
  50. package/lib/style-compiler/load-postcss-config.js +3 -1
  51. package/lib/style-compiler/plugins/conditional-strip.js +68 -65
  52. package/lib/style-compiler/plugins/rpx.js +43 -37
  53. package/lib/style-compiler/plugins/scope-id.js +79 -72
  54. package/lib/style-compiler/plugins/trans-special.js +25 -18
  55. package/lib/style-compiler/plugins/trim.js +13 -7
  56. package/lib/style-compiler/plugins/vw.js +22 -16
  57. package/lib/template-compiler/compiler.js +95 -197
  58. package/lib/template-compiler/index.js +52 -139
  59. package/lib/template-compiler/trans-dynamic-class-expr.js +18 -13
  60. package/lib/tenon/index.js +1 -3
  61. package/lib/tenon/processScript.js +52 -40
  62. package/lib/url-loader.js +11 -29
  63. package/lib/utils/add-query.js +1 -1
  64. package/lib/utils/const.js +10 -0
  65. package/lib/utils/emit-file.js +10 -0
  66. package/lib/utils/eval-json-js.js +31 -0
  67. package/lib/utils/get-entry-name.js +13 -0
  68. package/lib/utils/get-json-content.js +42 -0
  69. package/lib/utils/is-url-request.js +10 -1
  70. package/lib/utils/match-condition.js +4 -1
  71. package/lib/utils/normalize.js +4 -15
  72. package/lib/utils/parse-request.js +3 -3
  73. package/lib/utils/resolve.js +13 -0
  74. package/lib/utils/set.js +47 -0
  75. package/lib/utils/stringify-loaders-resource.js +25 -0
  76. package/lib/utils/stringify-query.js +4 -0
  77. package/lib/web/processJSON.js +113 -144
  78. package/lib/web/processScript.js +47 -34
  79. package/lib/web/processTemplate.js +57 -40
  80. package/lib/wxml/{wxml-loader.js → loader.js} +21 -62
  81. package/lib/wxs/WxsModuleIdsPlugin.js +29 -0
  82. package/lib/wxs/WxsParserPlugin.js +2 -2
  83. package/lib/wxs/WxsPlugin.js +4 -8
  84. package/lib/wxs/WxsTemplatePlugin.js +46 -92
  85. package/lib/wxs/{wxs-i18n-loader.js → i18n-loader.js} +5 -4
  86. package/lib/wxs/loader.js +142 -0
  87. package/lib/wxs/{wxs-pre-loader.js → pre-loader.js} +20 -5
  88. package/lib/wxss/loader.js +31 -43
  89. package/lib/wxss/localsLoader.js +1 -5
  90. package/lib/wxss/processCss.js +107 -103
  91. package/package.json +18 -20
  92. package/lib/built-in-loader.js +0 -49
  93. package/lib/content-loader.js +0 -13
  94. package/lib/dependency/ChildCompileDependency.js +0 -24
  95. package/lib/dependency/InjectDependency.js +0 -26
  96. package/lib/dependency/RemovedModuleDependency.js +0 -23
  97. package/lib/dependency/ResolveDependency.js +0 -53
  98. package/lib/plugin-loader.js +0 -287
  99. package/lib/staticConfig.js +0 -4
  100. package/lib/utils/get-main-compilation.js +0 -6
  101. package/lib/utils/read-json-for-src.js +0 -34
  102. package/lib/utils/try-require.js +0 -16
  103. package/lib/wxs/wxs-loader.js +0 -117
  104. package/lib/wxss/getImportPrefix.js +0 -30
@@ -1,88 +1,90 @@
1
1
  const async = require('async')
2
2
  const JSON5 = require('json5')
3
3
  const path = require('path')
4
- const SingleEntryPlugin = require('webpack/lib/SingleEntryPlugin')
5
- const loaderUtils = require('loader-utils')
6
4
  const parseComponent = require('../parser')
7
5
  const config = require('../config')
8
- const normalize = require('../utils/normalize')
9
- const nativeLoaderPath = normalize.lib('native-loader')
10
- const themeLoaderPath = normalize.lib('json-compiler/theme-loader')
11
- const extractorPath = normalize.lib('extractor')
12
6
  const parseRequest = require('../utils/parse-request')
13
- const mpxJSON = require('../utils/mpx-json')
14
- const toPosix = require('../utils/to-posix')
7
+ const evalJSONJS = require('../utils/eval-json-js')
15
8
  const fixUsingComponent = require('../utils/fix-using-component')
16
9
  const getRulesRunner = require('../platform/index')
17
- const isUrlRequestRaw = require('../utils/is-url-request')
18
10
  const addQuery = require('../utils/add-query')
19
- const readJsonForSrc = require('../utils/read-json-for-src')
20
- const getMainCompilation = require('../utils/get-main-compilation')
21
-
22
- module.exports = function (raw = '{}') {
23
- // 该loader中会在每次编译中动态添加entry,不能缓存,否则watch不好使
24
- this.cacheable(false)
11
+ const getJSONContent = require('../utils/get-json-content')
12
+ const createHelpers = require('../helpers')
13
+ const createJSONHelper = require('./helper')
14
+ const RecordGlobalComponentsDependency = require('../dependencies/RecordGlobalComponentsDependency')
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')
18
+
19
+ module.exports = function (content) {
25
20
  const nativeCallback = this.async()
26
- const options = loaderUtils.getOptions(this) || {}
27
- const mainCompilation = getMainCompilation(this._compilation)
28
- const mpx = mainCompilation.__mpx__
29
- const getOutputPath = mpx.getOutputPath
30
-
31
- const emitWarning = (msg) => {
32
- this.emitWarning(
33
- new Error('[json compiler][' + this.resource + ']: ' + msg)
34
- )
35
- }
36
-
37
- const emitError = (msg) => {
38
- this.emitError(
39
- new Error('[json compiler][' + this.resource + ']: ' + msg)
40
- )
41
- }
42
-
43
- const stringifyRequest = r => loaderUtils.stringifyRequest(this, r)
44
- const isUrlRequest = r => isUrlRequestRaw(r, options.root)
45
- const urlToRequest = r => loaderUtils.urlToRequest(r)
21
+ const mpx = this.getMpx()
46
22
 
47
23
  if (!mpx) {
48
- return nativeCallback(null, raw)
24
+ return nativeCallback(null, content)
49
25
  }
26
+ // json模块必须每次都创建(但并不是每次都需要build),用于动态添加编译入口,传递信息以禁用父级extractor的缓存
27
+ this.emitFile(MPX_DISABLE_EXTRACTOR_CACHE, '', undefined, { skipEmit: true })
50
28
 
51
29
  // 微信插件下要求组件使用相对路径
52
30
  const useRelativePath = mpx.isPluginMode || mpx.useRelativePath
53
31
  const { resourcePath, queryObj } = parseRequest(this.resource)
32
+ const useJSONJS = queryObj.useJSONJS || this.resourcePath.endsWith(JSON_JS_EXT)
54
33
  const packageName = queryObj.packageRoot || mpx.currentPackageRoot || 'main'
55
34
  const pagesMap = mpx.pagesMap
56
35
  const componentsMap = mpx.componentsMap[packageName]
57
- const getEntryNode = mpx.getEntryNode
36
+ const appInfo = mpx.appInfo
58
37
  const mode = mpx.mode
59
38
  const env = mpx.env
60
- const defs = mpx.defs
61
39
  const globalSrcMode = mpx.srcMode
62
40
  const localSrcMode = queryObj.mode
63
41
  const srcMode = localSrcMode || globalSrcMode
64
- const resolveMode = mpx.resolveMode
65
- const externals = mpx.externals
66
- const pathHash = mpx.pathHash
42
+
67
43
  const isApp = !(pagesMap[resourcePath] || componentsMap[resourcePath])
68
44
  const publicPath = this._compilation.outputOptions.publicPath || ''
69
45
  const fs = this._compiler.inputFileSystem
70
- const rootName = mainCompilation._preparedEntrypoints[0].name
71
- const currentName = componentsMap[resourcePath] || pagesMap[resourcePath] || rootName
72
- const currentPath = publicPath + currentName
73
46
 
74
- // json模块都是由.mpx或.js的入口模块引入,且引入关系为一对一,其issuer必为入口module
75
- const entryModule = this._module.issuer
76
- // 通过rawRequest关联entryNode和entryModule
77
- const entryRequest = entryModule.rawRequest
78
- const entryType = isApp ? 'App' : pagesMap[resourcePath] ? 'Page' : 'Component'
47
+ const emitWarning = (msg) => {
48
+ this.emitWarning(
49
+ new Error('[json compiler][' + this.resource + ']: ' + msg)
50
+ )
51
+ }
52
+
53
+ const emitError = (msg) => {
54
+ this.emitError(
55
+ new Error('[json compiler][' + this.resource + ']: ' + msg)
56
+ )
57
+ }
58
+
59
+ const {
60
+ isUrlRequest,
61
+ urlToRequest,
62
+ processPage,
63
+ processDynamicEntry,
64
+ processComponent,
65
+ processJsExport
66
+ } = createJSONHelper({
67
+ loaderContext: this,
68
+ emitWarning,
69
+ emitError
70
+ })
71
+
72
+ const { getRequestString } = createHelpers(this)
79
73
 
80
- const currentEntry = getEntryNode(entryRequest, entryType, entryModule)
74
+ let currentName
75
+
76
+ if (isApp) {
77
+ currentName = appInfo.name
78
+ } else {
79
+ currentName = componentsMap[resourcePath] || pagesMap[resourcePath]
80
+ }
81
+
82
+ const relativePath = useRelativePath ? publicPath + path.dirname(currentName) : ''
81
83
 
82
84
  const copydir = (dir, context, callback) => {
83
85
  fs.readdir(dir, (err, files) => {
84
86
  if (err) return callback(err)
85
- async.forEach(files, (file, callback) => {
87
+ async.each(files, (file, callback) => {
86
88
  file = path.join(dir, file)
87
89
  async.waterfall([
88
90
  (callback) => {
@@ -94,6 +96,7 @@ module.exports = function (raw = '{}') {
94
96
  } else {
95
97
  fs.readFile(file, (err, content) => {
96
98
  if (err) return callback(err)
99
+ if (!this._compilation) return callback()
97
100
  let targetPath = path.relative(context, file)
98
101
  this._compilation.assets[targetPath] = {
99
102
  size: function size () {
@@ -112,58 +115,20 @@ module.exports = function (raw = '{}') {
112
115
  })
113
116
  }
114
117
 
115
- let entryDeps = new Set()
116
-
117
- let cacheCallback
118
-
119
- const checkEntryDeps = (callback) => {
120
- callback = callback || cacheCallback
121
- if (callback && entryDeps.size === 0) {
122
- callback()
123
- } else {
124
- cacheCallback = callback
125
- }
126
- }
127
-
128
- const addEntrySafely = (resource, name, callback) => {
129
- // 如果loader已经回调,就不再添加entry
130
- if (callbacked) return callback()
131
- const dep = SingleEntryPlugin.createDependency(resource, name)
132
- entryDeps.add(dep)
133
- this._compilation.addEntry(this._compiler.context, dep, name, (err, module) => {
134
- entryDeps.delete(dep)
135
- checkEntryDeps()
136
- callback(err, module)
137
- })
138
- }
139
-
140
- // const deleteEntry = (name) => {
141
- // const index = this._compilation._preparedEntrypoints.findIndex(slot => slot.name === name)
142
- // if (index >= 0) {
143
- // this._compilation._preparedEntrypoints.splice(index, 1)
144
- // }
145
- // }
146
-
147
- let callbacked = false
148
118
  const callback = (err, processOutput) => {
149
- checkEntryDeps(() => {
150
- callbacked = true
151
- if (err) return nativeCallback(err)
152
- let output = `var json = ${JSON.stringify(json, null, 2)};\n`
153
- if (processOutput) output = processOutput(output)
154
- output += `module.exports = JSON.stringify(json, null, 2);\n`
155
- nativeCallback(null, output)
156
- })
119
+ if (err) return nativeCallback(err)
120
+ let output = `var json = ${JSON.stringify(json, null, 2)};\n`
121
+ if (processOutput) output = processOutput(output)
122
+ output += `module.exports = JSON.stringify(json, null, 2);\n`
123
+ nativeCallback(null, output)
157
124
  }
158
125
 
159
- let json = {}
126
+ let json
160
127
  try {
161
- // 使用了MPXJSON的话先编译
162
- // 此处需要使用真实的resourcePath
163
- if (this.resourcePath.endsWith('.json.js')) {
164
- json = JSON.parse(mpxJSON.compileMPXJSONText({ source: raw, defs, filePath: this.resourcePath }))
128
+ if (useJSONJS) {
129
+ json = evalJSONJS(content, this.resourcePath, this)
165
130
  } else {
166
- json = JSON5.parse(raw)
131
+ json = JSON5.parse(content || '{}')
167
132
  }
168
133
  } catch (err) {
169
134
  return callback(err)
@@ -224,13 +189,7 @@ module.exports = function (raw = '{}') {
224
189
  } else {
225
190
  // 保存全局注册组件
226
191
  if (json.usingComponents) {
227
- mpx.usingComponents = {}
228
- Object.keys(json.usingComponents).forEach((key) => {
229
- const request = json.usingComponents[key]
230
- mpx.usingComponents[key] = addQuery(request, {
231
- context: this.context
232
- })
233
- })
192
+ this._module.addPresentationalDependency(new RecordGlobalComponentsDependency(json.usingComponents, this.context))
234
193
  }
235
194
  }
236
195
 
@@ -240,141 +199,68 @@ module.exports = function (raw = '{}') {
240
199
  rulesRunner(json)
241
200
  }
242
201
 
243
- const resolve = (context, request, callback) => {
244
- const { queryObj } = parseRequest(request)
245
- context = queryObj.context || context
246
- return this.resolve(context, request, callback)
247
- }
248
-
249
202
  const processComponents = (components, context, callback) => {
250
203
  if (components) {
251
- async.forEachOf(components, (component, name, callback) => {
252
- processComponent(component, context, (componentPath) => {
253
- if (useRelativePath === true) {
254
- componentPath = toPosix(path.relative(path.dirname(currentPath), componentPath))
204
+ async.eachOf(components, (component, name, callback) => {
205
+ processComponent(component, context, { relativePath }, (err, entry) => {
206
+ if (err === RESOLVE_IGNORED_ERR) {
207
+ delete components[name]
208
+ return callback()
255
209
  }
256
- components[name] = componentPath
257
- }, undefined, callback)
210
+ if (err) return callback(err)
211
+ components[name] = entry
212
+ callback()
213
+ })
258
214
  }, callback)
259
215
  } else {
260
216
  callback()
261
217
  }
262
218
  }
263
219
 
264
- const processComponent = (component, context, rewritePath, outputPath, callback) => {
265
- if (!isUrlRequest(component)) return callback()
266
- if (resolveMode === 'native') {
267
- component = urlToRequest(component)
268
- }
269
-
270
- if (externals.some((external) => {
271
- if (typeof external === 'string') {
272
- return external === component
273
- } else if (external instanceof RegExp) {
274
- return external.test(component)
275
- }
276
- return false
277
- })) {
278
- return callback()
279
- }
280
-
281
- resolve(context, component, (err, resource, info) => {
282
- if (err) return callback(err)
283
- const resourcePath = parseRequest(resource).resourcePath
284
- const parsed = path.parse(resourcePath)
285
- const ext = parsed.ext
286
- const resourceName = path.join(parsed.dir, parsed.name)
287
-
288
- if (!outputPath) {
289
- if (ext === '.js' && resourceName.includes('node_modules')) {
290
- let root = info.descriptionFileRoot
291
- let name = 'nativeComponent'
292
- if (info.descriptionFileData) {
293
- if (info.descriptionFileData.miniprogram) {
294
- root = path.join(root, info.descriptionFileData.miniprogram)
295
- }
296
- if (info.descriptionFileData.name) {
297
- // 去掉name里面的@符号,因为支付宝不支持文件路径上有@
298
- name = info.descriptionFileData.name.split('@').join('')
299
- }
300
- }
301
- let relativePath = path.relative(root, resourceName)
302
- outputPath = path.join('components', name + pathHash(root), relativePath)
303
- } else {
304
- outputPath = getOutputPath(resourcePath, 'component')
305
- }
306
- }
307
- const { packageRoot, outputPath: componentPath, alreadyOutputed } = mpx.getPackageInfo({
308
- resource,
309
- outputPath,
310
- resourceType: 'components',
311
- warn: (err) => {
312
- this.emitWarning(err)
313
- }
314
- })
315
- if (packageRoot) {
316
- resource = addQuery(resource, {
317
- packageRoot
318
- })
319
- }
320
- rewritePath && rewritePath(publicPath + componentPath)
321
- if (ext === '.js') {
322
- resource = '!!' + nativeLoaderPath + '!' + resource
323
- }
324
- currentEntry.addChild(getEntryNode(resource, 'Component'))
325
- // 如果之前已经创建了入口,直接return
326
- if (alreadyOutputed) {
327
- return callback()
328
- }
329
- addEntrySafely(resource, componentPath, callback)
330
- })
331
- }
332
-
333
- // 由于json模块都是由mpx/js文件引入的,需要向上找两层issuer获取真实的引用源
334
- const getJsonIssuer = (module) => {
335
- if (module.issuer) {
336
- return module.issuer.issuer
337
- }
338
- }
339
-
340
220
  if (isApp) {
341
- if (!mpx.hasApp) {
342
- mpx.hasApp = true
343
- } else {
344
- const issuer = getJsonIssuer(this._module)
345
- if (issuer) {
346
- emitError(`[json compiler]:Mpx单次构建中只能存在一个App,当前组件/页面[${this.resource}]通过[${issuer.resource}]非法引入,引用的资源将被忽略,请确保组件/页面资源通过usingComponents/pages配置引入!`)
347
- } else {
348
- emitError(`[json compiler]:Mpx单次构建中只能存在一个App,请检查当前entry中的资源[${this.resource}]是否为组件/页面,通过添加?component/page查询字符串显式声明该资源是组件/页面!`)
349
- }
350
- return callback()
351
- }
352
221
  // app.json
353
- const subPackagesCfg = {}
354
222
  const localPages = []
355
- const processSubPackagesQueue = []
356
- // 添加首页标识
357
- if (json.pages && json.pages[0]) {
358
- if (typeof json.pages[0] !== 'string') {
359
- json.pages[0].src = addQuery(json.pages[0].src, { isFirst: true })
223
+ const subPackagesCfg = {}
224
+ const pageKeySet = new Set()
225
+
226
+ const processPages = (pages, context, tarRoot = '', callback) => {
227
+ if (pages) {
228
+ async.each(pages, (page, callback) => {
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)
233
+ if (tarRoot && subPackagesCfg) {
234
+ subPackagesCfg[tarRoot].pages.push(entry)
235
+ } else {
236
+ // 确保首页
237
+ if (isFirst) {
238
+ localPages.unshift(entry)
239
+ } else {
240
+ localPages.push(entry)
241
+ }
242
+ }
243
+ callback()
244
+ })
245
+ }, callback)
360
246
  } else {
361
- json.pages[0] = addQuery(json.pages[0], { isFirst: true })
247
+ callback()
362
248
  }
363
249
  }
364
250
 
365
251
  const processPackages = (packages, context, callback) => {
366
252
  if (packages) {
367
- async.forEach(packages, (packagePath, callback) => {
253
+ async.each(packages, (packagePath, callback) => {
368
254
  const { queryObj } = parseRequest(packagePath)
369
255
  async.waterfall([
370
256
  (callback) => {
371
- resolve(context, packagePath, (err, result) => {
257
+ resolve(context, packagePath, this, (err, result) => {
258
+ if (err) return callback(err)
372
259
  const { rawResourcePath } = parseRequest(result)
373
260
  callback(err, rawResourcePath)
374
261
  })
375
262
  },
376
263
  (result, callback) => {
377
- this.addDependency(result)
378
264
  fs.readFile(result, (err, content) => {
379
265
  if (err) return callback(err)
380
266
  callback(err, result, content.toString('utf-8'))
@@ -382,24 +268,21 @@ module.exports = function (raw = '{}') {
382
268
  },
383
269
  (result, content, callback) => {
384
270
  const extName = path.extname(result)
385
- if (extName === '.mpx' || extName === '.vue') {
271
+ if (extName === '.mpx') {
386
272
  const parts = parseComponent(content, {
387
273
  filePath: result,
388
274
  needMap: this.sourceMap,
389
275
  mode,
390
- defs,
391
276
  env
392
277
  })
393
- const json = parts.json || {}
394
- if (json.content) {
395
- content = json.content
396
- } else if (json.src) {
397
- return readJsonForSrc(json.src, this, (content) => {
398
- callback(null, result, content)
399
- })
400
- }
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)
401
285
  }
402
- callback(null, result, content)
403
286
  },
404
287
  (result, content, callback) => {
405
288
  try {
@@ -425,12 +308,12 @@ module.exports = function (raw = '{}') {
425
308
  subPackage.plugins = content.plugins
426
309
  }
427
310
 
428
- processSubPackagesQueue.push((callback) => {
311
+ processSelfQueue.push((callback) => {
429
312
  processSubPackage(subPackage, context, callback)
430
313
  })
431
314
  } else {
432
315
  processSelfQueue.push((callback) => {
433
- processPages(content.pages, '', '', context, callback)
316
+ processPages(content.pages, context, '', callback)
434
317
  })
435
318
  }
436
319
  }
@@ -445,14 +328,16 @@ module.exports = function (raw = '{}') {
445
328
  callback()
446
329
  }
447
330
  }
448
- ], callback)
331
+ ], (err) => {
332
+ callback(err === RESOLVE_IGNORED_ERR ? null : err)
333
+ })
449
334
  }, callback)
450
335
  } else {
451
336
  callback()
452
337
  }
453
338
  }
454
339
 
455
- const getOtherConfig = (raw) => {
340
+ const getOtherConfig = (config) => {
456
341
  let result = {}
457
342
  let blackListMap = {
458
343
  tarRoot: true,
@@ -460,14 +345,39 @@ module.exports = function (raw = '{}') {
460
345
  root: true,
461
346
  pages: true
462
347
  }
463
- for (let key in raw) {
348
+ for (let key in config) {
464
349
  if (!blackListMap[key]) {
465
- result[key] = raw[key]
350
+ result[key] = config[key]
466
351
  }
467
352
  }
468
353
  return result
469
354
  }
470
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
+
471
381
  // 为了获取资源的所属子包,该函数需串行执行
472
382
  const processSubPackage = (subPackage, context, callback) => {
473
383
  if (subPackage) {
@@ -479,29 +389,27 @@ module.exports = function (raw = '{}') {
479
389
  let srcRoot = subPackage.srcRoot || subPackage.root || ''
480
390
  if (!tarRoot || subPackagesCfg[tarRoot]) return callback()
481
391
 
392
+ context = path.join(context, srcRoot)
482
393
  const otherConfig = getOtherConfig(subPackage)
483
- // 支付宝不支持独立分包,无需处理
484
- if (otherConfig.independent && mode !== 'ali') {
485
- mpx.independentSubpackagesMap[tarRoot] = true
486
- }
487
-
488
394
  subPackagesCfg[tarRoot] = {
489
395
  root: tarRoot,
490
- pages: [],
491
- ...otherConfig
396
+ pages: []
492
397
  }
493
- mpx.currentPackageRoot = tarRoot
494
- mpx.componentsMap[tarRoot] = {}
495
- mpx.staticResourcesMap[tarRoot] = {}
496
- mpx.subpackageModulesMap[tarRoot] = {}
497
398
  async.parallel([
498
399
  (callback) => {
499
- processPages(subPackage.pages, srcRoot, tarRoot, context, callback)
400
+ processIndependent(otherConfig, context, tarRoot, callback)
401
+ },
402
+ (callback) => {
403
+ processPages(subPackage.pages, context, tarRoot, callback)
500
404
  },
501
405
  (callback) => {
502
- processPlugins(subPackage.plugins, srcRoot, tarRoot, context, callback)
406
+ processPlugins(subPackage.plugins, context, tarRoot, callback)
503
407
  }
504
- ], callback)
408
+ ], (err) => {
409
+ if (err) return callback(err)
410
+ Object.assign(subPackagesCfg[tarRoot], otherConfig)
411
+ callback()
412
+ })
505
413
  } else {
506
414
  callback()
507
415
  }
@@ -509,92 +417,8 @@ module.exports = function (raw = '{}') {
509
417
 
510
418
  const processSubPackages = (subPackages, context, callback) => {
511
419
  if (subPackages) {
512
- subPackages.forEach((subPackage) => {
513
- processSubPackagesQueue.push((callback) => {
514
- processSubPackage(subPackage, context, callback)
515
- })
516
- })
517
- }
518
- callback()
519
- }
520
-
521
- // const getPageName = (resourcePath, ext) => {
522
- // const baseName = path.basename(resourcePath, ext)
523
- // return path.join('pages', baseName + pathHash(resourcePath), baseName)
524
- // }
525
-
526
- const processPages = (pages, srcRoot = '', tarRoot = '', context, callback) => {
527
- if (pages) {
528
- context = path.join(context, srcRoot)
529
- async.forEach(pages, (page, callback) => {
530
- let aliasPath = ''
531
- if (typeof page !== 'string') {
532
- aliasPath = page.path
533
- page = page.src
534
- }
535
- if (!isUrlRequest(page)) return callback()
536
- if (resolveMode === 'native') {
537
- page = urlToRequest(page)
538
- }
539
- resolve(context, page, (err, resource) => {
540
- if (err) return callback(err)
541
- const { resourcePath, queryObj } = parseRequest(resource)
542
- const ext = path.extname(resourcePath)
543
- // 获取pageName
544
- let pageName
545
- if (aliasPath) {
546
- pageName = toPosix(path.join(tarRoot, aliasPath))
547
- // 判断 key 存在重复情况直接报错
548
- for (let key in pagesMap) {
549
- if (pagesMap[key] === pageName && key !== resourcePath) {
550
- emitError(`Current page [${resourcePath}] registers a conflict page path [${pageName}] with existed page [${key}], which is not allowed, please rename it!`)
551
- return callback()
552
- }
553
- }
554
- } else {
555
- const relative = path.relative(context, resourcePath)
556
- if (/^\./.test(relative)) {
557
- // 如果当前page不存在于context中,对其进行重命名
558
- pageName = getOutputPath(resourcePath, 'page')
559
- emitWarning(`Current page [${resourcePath}] is not in current pages directory [${context}], the page path will be replaced with [${pageName}], use ?resolve to get the page path and navigate to it!`)
560
- } else {
561
- pageName = toPosix(path.join(tarRoot, /^(.*?)(\.[^.]*)?$/.exec(relative)[1]))
562
- // 如果当前page与已有page存在命名冲突,也进行重命名
563
- }
564
- for (let key in pagesMap) {
565
- if (pagesMap[key] === pageName && key !== resourcePath) {
566
- const pageNameRaw = pageName
567
- pageName = getOutputPath(resourcePath, 'page', { conflictPath: pageNameRaw })
568
- emitWarning(`Current page [${resourcePath}] is registered with a conflict page path [${pageNameRaw}] which is already existed in system, the page path will be replaced with [${pageName}], use ?resolve to get the page path and navigate to it!`)
569
- break
570
- }
571
- }
572
- }
573
- if (ext === '.js') {
574
- resource = '!!' + nativeLoaderPath + '!' + resource
575
- }
576
- // 如果之前已经创建了页面入口,直接return,目前暂时不支持多个分包复用同一个页面
577
- if (pagesMap[resourcePath]) {
578
- emitWarning(`Current page [${resourcePath}] which is imported from [${this.resourcePath}] has been registered in pagesMap already, it will be ignored, please check it and remove the redundant page declaration!`)
579
- return callback()
580
- }
581
- currentEntry.addChild(getEntryNode(resource, 'Page'))
582
- pagesMap[resourcePath] = pageName
583
- if (tarRoot && subPackagesCfg[tarRoot]) {
584
- resource = addQuery(resource, {
585
- packageRoot: tarRoot
586
- })
587
- subPackagesCfg[tarRoot].pages.push(toPosix(path.relative(tarRoot, pageName)))
588
- } else {
589
- // 确保首页
590
- if (queryObj.isFirst) {
591
- localPages.unshift(pageName)
592
- } else {
593
- localPages.push(pageName)
594
- }
595
- }
596
- addEntrySafely(resource, pageName, callback)
597
- })
420
+ async.each(subPackages, (subPackage, callback) => {
421
+ processSubPackage(subPackage, context, callback)
598
422
  }, callback)
599
423
  } else {
600
424
  callback()
@@ -633,15 +457,11 @@ module.exports = function (raw = '{}') {
633
457
 
634
458
  const processThemeLocation = (output) => {
635
459
  if (json.themeLocation && isUrlRequest(json.themeLocation)) {
636
- const themeRequest = '!!' + extractorPath + '?' +
637
- JSON.stringify({
638
- type: 'json',
639
- index: -1
640
- }) + '!' +
641
- themeLoaderPath + '?root = ' + options.root + '!' +
642
- addQuery(urlToRequest(json.themeLocation), { __component: true, isStatic: true })
643
-
644
- output += `json.themeLocation = require(${stringifyRequest(themeRequest)});\n`
460
+ const requestString = getRequestString('json', { src: urlToRequest(json.themeLocation) }, {
461
+ isTheme: true,
462
+ isStatic: true
463
+ })
464
+ output += `json.themeLocation = require(${requestString});\n`
645
465
  }
646
466
  return output
647
467
  }
@@ -658,146 +478,114 @@ module.exports = function (raw = '{}') {
658
478
 
659
479
  const processCustomTabBar = (tabBar, context, callback) => {
660
480
  if (tabBar && tabBar.custom) {
661
- processComponent('./custom-tab-bar/index', context, undefined, '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
+ })
662
489
  } else {
663
490
  callback()
664
491
  }
665
492
  }
666
493
 
667
- const addMiniToPluginModules = module => {
668
- if (mpx.miniToPluginModules) {
669
- mpx.miniToPluginModules.add(module)
670
- } else {
671
- mpx.miniToPluginModules = new Set([module])
672
- }
673
- }
674
-
675
- const processPluginGenericsImplementation = (genericsImplementation, tarRoot, context, callback) => {
676
- async.forEachOf(genericsImplementation, (genericComponents, name, callback) => {
677
- async.forEachOf(genericComponents, (genericComponentPath, name, callback) => {
678
- processComponent(genericComponentPath, context, (componentPath) => {
679
- if (useRelativePath === true) {
680
- componentPath = toPosix(path.relative(publicPath + tarRoot, componentPath))
494
+ const processPluginGenericsImplementation = (plugin, context, tarRoot, callback) => {
495
+ if (!plugin.genericsImplementation) return callback()
496
+ const relativePath = useRelativePath ? publicPath + tarRoot : ''
497
+ async.eachOf(plugin.genericsImplementation, (genericComponents, name, callback) => {
498
+ async.eachOf(genericComponents, (genericComponentPath, name, callback) => {
499
+ processComponent(genericComponentPath, context, {
500
+ tarRoot,
501
+ relativePath
502
+ }, (err, entry) => {
503
+ if (err === RESOLVE_IGNORED_ERR) {
504
+ delete genericComponents[name]
505
+ return callback()
681
506
  }
682
- genericComponents[name] = componentPath
683
- }, undefined, callback)
507
+ if (err) return callback(err)
508
+ genericComponents[name] = entry
509
+ })
684
510
  }, callback)
685
511
  }, callback)
686
512
  }
687
513
 
688
- const processPluginExport = (plugin, tarRoot, context, callback) => {
689
- if (!plugin.export) {
690
- return callback()
691
- }
692
- let pluginExport = plugin.export
693
- if (resolveMode === 'native') {
694
- pluginExport = urlToRequest(pluginExport)
695
- }
696
- resolve(context, pluginExport, (err, resource, info) => {
697
- if (err) return callback(err)
698
- const { resourcePath } = parseRequest(resource)
699
- // 获取 export 的模块名
700
- const relative = path.relative(context, resourcePath)
701
- const name = toPosix(/^(.*?)(\.[^.]*)?$/.exec(relative)[1])
702
- if (/^\./.test(name)) {
703
- return callback(new Error(`The miniprogram plugins' export path ${plugin.export} must be in the context ${context}!`))
514
+ const processPluginExport = (plugin, context, tarRoot, callback) => {
515
+ if (!plugin.export) return callback()
516
+ processJsExport(plugin.export, context, tarRoot, (err, entry) => {
517
+ if (err === RESOLVE_IGNORED_ERR) {
518
+ delete plugin.export
519
+ return callback()
704
520
  }
705
- plugin.export = name + '.js'
706
- addEntrySafely(resource, toPosix(tarRoot ? `${tarRoot}/${name}` : name), (err, module) => {
707
- if (err) return callback(err)
708
- addMiniToPluginModules(module)
709
- currentEntry.addChild(getEntryNode(resource, 'PluginExport', module))
710
- callback(err, module)
711
- })
521
+ if (err) return callback(err)
522
+ plugin.export = entry
523
+ callback()
712
524
  })
713
525
  }
714
526
 
715
- /* 导出到插件 */
716
- const processPlugins = (plugins, srcRoot = '', tarRoot = '', context, callback) => {
717
- if (mpx.mode !== 'wx' || !plugins) return callback() // 目前只有微信支持导出到插件
718
- context = path.join(context, srcRoot)
719
- async.forEachOf(plugins, (plugin, name, callback) => {
527
+ const processPlugins = (plugins, context, tarRoot = '', callback) => {
528
+ if (mode !== 'wx' || !plugins) return callback() // 目前只有微信支持导出到插件
529
+ async.eachOf(plugins, (plugin, name, callback) => {
720
530
  async.parallel([
721
531
  (callback) => {
722
- if (plugin.genericsImplementation) {
723
- processPluginGenericsImplementation(plugin.genericsImplementation, tarRoot, context, callback)
724
- } else {
725
- callback()
726
- }
532
+ processPluginGenericsImplementation(plugin, context, tarRoot, callback)
727
533
  },
728
534
  (callback) => {
729
- processPluginExport(plugin, tarRoot, context, callback)
535
+ processPluginExport(plugin, context, tarRoot, callback)
730
536
  }
731
- ], (err) => {
732
- callback(err)
733
- })
537
+ ], callback)
734
538
  }, callback)
735
539
  }
736
540
 
737
- // 串行处理,先处理主包代码,再处理分包代码,为了正确识别出分包中定义的组件属于主包还是分包
738
- let errors = []
739
- // 外部收集errors,确保整个series流程能够执行完
740
- async.series([
541
+ async.parallel([
741
542
  (callback) => {
742
- async.parallel([
743
- (callback) => {
744
- processPlugins(json.plugins, '', '', this.context, callback)
745
- },
746
- (callback) => {
747
- processPages(json.pages, '', '', this.context, callback)
748
- },
749
- (callback) => {
750
- processComponents(json.usingComponents, this.context, callback)
751
- },
752
- (callback) => {
753
- processWorkers(json.workers, this.context, callback)
754
- },
755
- (callback) => {
756
- processPackages(json.packages, this.context, callback)
757
- },
758
- (callback) => {
759
- processCustomTabBar(json.tabBar, this.context, callback)
760
- },
761
- (callback) => {
762
- processSubPackages(json.subPackages || json.subpackages, this.context, callback)
763
- }
764
- ], (err) => {
765
- if (err) {
766
- errors.push(err)
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 })
767
549
  }
768
- callback()
769
- })
550
+ }
551
+ processPages(json.pages, this.context, '', callback)
770
552
  },
771
553
  (callback) => {
772
- if (mpx.appScriptPromise) {
773
- mpx.appScriptPromise.then(callback)
774
- } else {
775
- callback()
776
- }
554
+ processComponents(json.usingComponents, this.context, callback)
777
555
  },
778
556
  (callback) => {
779
- async.series(processSubPackagesQueue, (err) => {
780
- if (err) {
781
- errors.push(err)
782
- }
783
- // 处理完分包后重置currentPackageRoot以确保app中的资源输出到主包
784
- mpx.currentPackageRoot = ''
785
- callback()
786
- })
557
+ processPlugins(json.plugins, this.context, '', callback)
558
+ },
559
+ (callback) => {
560
+ processWorkers(json.workers, this.context, callback)
561
+ },
562
+ (callback) => {
563
+ processPackages(json.packages, this.context, callback)
564
+ },
565
+ (callback) => {
566
+ processCustomTabBar(json.tabBar, this.context, callback)
567
+ },
568
+ (callback) => {
569
+ processSubPackages(json.subPackages || json.subpackages, this.context, callback)
787
570
  }
788
- ], () => {
789
- if (errors.length) return callback(errors[0])
571
+ ], (err) => {
572
+ if (err) return callback(err)
790
573
  delete json.packages
791
574
  delete json.subpackages
792
575
  delete json.subPackages
793
576
  json.pages = localPages
794
577
  for (let root in subPackagesCfg) {
795
- if (!json.subPackages) {
796
- 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)
797
585
  }
798
- json.subPackages.push(subPackagesCfg[root])
799
586
  }
800
587
  const processOutput = (output) => {
588
+ output = processDynamicEntry(output)
801
589
  output = processTabBar(output)
802
590
  output = processOptionMenu(output)
803
591
  output = processThemeLocation(output)
@@ -806,16 +594,20 @@ module.exports = function (raw = '{}') {
806
594
  callback(null, processOutput)
807
595
  })
808
596
  } else {
597
+ // page.json或component.json
809
598
  const processGenerics = (generics, context, callback) => {
810
599
  if (generics) {
811
- async.forEachOf(generics, (generic, name, callback) => {
600
+ async.eachOf(generics, (generic, name, callback) => {
812
601
  if (generic.default) {
813
- processComponent(generic.default, context, (componentPath) => {
814
- if (useRelativePath === true) {
815
- componentPath = toPosix(path.relative(path.dirname(currentPath), componentPath))
602
+ processComponent(generic.default, context, { relativePath }, (err, entry) => {
603
+ if (err === RESOLVE_IGNORED_ERR) {
604
+ delete generic.default
605
+ return callback()
816
606
  }
817
- generic.default = componentPath
818
- }, undefined, callback)
607
+ if (err) return callback(err)
608
+ generic.default = entry
609
+ callback()
610
+ })
819
611
  } else {
820
612
  callback()
821
613
  }
@@ -824,7 +616,6 @@ module.exports = function (raw = '{}') {
824
616
  callback()
825
617
  }
826
618
  }
827
- // page.json或component.json
828
619
  async.parallel([
829
620
  (callback) => {
830
621
  processComponents(json.usingComponents, this.context, callback)
@@ -833,7 +624,7 @@ module.exports = function (raw = '{}') {
833
624
  processGenerics(json.componentGenerics, this.context, callback)
834
625
  }
835
626
  ], (err) => {
836
- callback(err)
627
+ callback(err, processDynamicEntry)
837
628
  })
838
629
  }
839
630
  }