@mpxjs/webpack-plugin 2.6.110 → 2.7.0-beta.10

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