@mpxjs/webpack-plugin 2.6.115 → 2.7.0-alpha

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 (129) hide show
  1. package/LICENSE +433 -0
  2. package/README.md +1 -1
  3. package/lib/config.js +14 -0
  4. package/lib/dependencies/AddEntryDependency.js +24 -0
  5. package/lib/dependencies/AppEntryDependency.js +58 -0
  6. package/lib/dependencies/CommonJsAsyncDependency.js +51 -0
  7. package/lib/dependencies/CommonJsVariableDependency.js +81 -0
  8. package/lib/dependencies/DynamicEntryDependency.js +171 -0
  9. package/lib/dependencies/FlagPluginDependency.js +24 -0
  10. package/lib/dependencies/InjectDependency.js +43 -0
  11. package/lib/dependencies/RecordGlobalComponentsDependency.js +50 -0
  12. package/lib/dependencies/RecordIndependentDependency.js +44 -0
  13. package/lib/dependencies/RecordResourceMapDependency.js +62 -0
  14. package/lib/dependencies/RemoveEntryDependency.js +40 -0
  15. package/lib/{dependency → dependencies}/ReplaceDependency.js +19 -2
  16. package/lib/dependencies/ResolveDependency.js +88 -0
  17. package/lib/extractor.js +82 -178
  18. package/lib/file-loader.js +7 -19
  19. package/lib/helpers.js +39 -334
  20. package/lib/independent-loader.js +52 -0
  21. package/lib/index.js +889 -525
  22. package/lib/json-compiler/helper.js +156 -0
  23. package/lib/json-compiler/index.js +245 -451
  24. package/lib/json-compiler/plugin.js +150 -0
  25. package/lib/json-compiler/{theme-loader.js → theme.js} +5 -3
  26. package/lib/loader.js +178 -241
  27. package/lib/native-loader.js +71 -133
  28. package/lib/parser.js +1 -2
  29. package/lib/partial-compile/index.js +35 -0
  30. package/lib/platform/json/wx/index.js +1 -1
  31. package/lib/platform/template/normalize-component-rules.js +2 -3
  32. package/lib/platform/template/wx/component-config/button.js +14 -2
  33. package/lib/platform/template/wx/component-config/image.js +4 -0
  34. package/lib/platform/template/wx/component-config/input.js +4 -0
  35. package/lib/platform/template/wx/component-config/rich-text.js +4 -0
  36. package/lib/platform/template/wx/component-config/scroll-view.js +4 -0
  37. package/lib/platform/template/wx/component-config/switch.js +4 -0
  38. package/lib/platform/template/wx/component-config/text.js +4 -0
  39. package/lib/platform/template/wx/component-config/textarea.js +5 -0
  40. package/lib/platform/template/wx/component-config/view.js +4 -0
  41. package/lib/platform/template/wx/index.js +149 -3
  42. package/lib/record-loader.js +11 -0
  43. package/lib/resolve-loader.js +6 -0
  44. package/lib/resolver/AddEnvPlugin.js +4 -3
  45. package/lib/resolver/AddModePlugin.js +4 -3
  46. package/lib/resolver/FixDescriptionInfoPlugin.js +28 -0
  47. package/lib/resolver/PackageEntryPlugin.js +23 -36
  48. package/lib/runtime/base.styl +5 -0
  49. package/lib/runtime/components/tenon/getInnerListeners.js +317 -0
  50. package/lib/runtime/components/tenon/tenon-button.vue +305 -0
  51. package/lib/runtime/components/tenon/tenon-image.vue +61 -0
  52. package/lib/runtime/components/tenon/tenon-input.vue +99 -0
  53. package/lib/runtime/components/tenon/tenon-rich-text.vue +21 -0
  54. package/lib/runtime/components/tenon/tenon-scroll-view.vue +124 -0
  55. package/lib/runtime/components/tenon/tenon-switch.vue +91 -0
  56. package/lib/runtime/components/tenon/tenon-text-area.vue +64 -0
  57. package/lib/runtime/components/tenon/tenon-text.vue +64 -0
  58. package/lib/runtime/components/tenon/tenon-view.vue +93 -0
  59. package/lib/runtime/components/tenon/util.js +44 -0
  60. package/lib/runtime/components/web/getInnerListeners.js +1 -3
  61. package/lib/runtime/components/web/mpx-image.vue +20 -5
  62. package/lib/runtime/components/web/mpx-movable-view.vue +6 -2
  63. package/lib/runtime/components/web/mpx-swiper.vue +18 -3
  64. package/lib/runtime/i18n.wxs +31 -11
  65. package/lib/runtime/optionProcessor.js +48 -3
  66. package/lib/runtime/optionProcessor.tenon.js +386 -0
  67. package/lib/selector.js +29 -10
  68. package/lib/style-compiler/index.js +16 -24
  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 +22 -16
  77. package/lib/template-compiler/compiler.js +106 -199
  78. package/lib/template-compiler/index.js +52 -139
  79. package/lib/template-compiler/trans-dynamic-class-expr.js +18 -13
  80. package/lib/tenon/index.js +105 -0
  81. package/lib/tenon/processJSON.js +356 -0
  82. package/lib/tenon/processScript.js +261 -0
  83. package/lib/tenon/processStyles.js +21 -0
  84. package/lib/tenon/processTemplate.js +133 -0
  85. package/lib/url-loader.js +11 -29
  86. package/lib/utils/add-query.js +1 -1
  87. package/lib/utils/const.js +10 -0
  88. package/lib/utils/emit-file.js +10 -0
  89. package/lib/utils/eval-json-js.js +31 -0
  90. package/lib/utils/get-entry-name.js +13 -0
  91. package/lib/utils/get-json-content.js +42 -0
  92. package/lib/utils/get-relative-path.js +25 -0
  93. package/lib/utils/is-url-request.js +10 -1
  94. package/lib/utils/match-condition.js +4 -1
  95. package/lib/utils/normalize.js +4 -15
  96. package/lib/utils/parse-request.js +3 -3
  97. package/lib/utils/resolve.js +13 -0
  98. package/lib/utils/set.js +47 -0
  99. package/lib/utils/stringify-loaders-resource.js +25 -0
  100. package/lib/utils/stringify-query.js +4 -0
  101. package/lib/web/processJSON.js +113 -144
  102. package/lib/web/processScript.js +47 -34
  103. package/lib/web/processTemplate.js +57 -40
  104. package/lib/wxml/{wxml-loader.js → loader.js} +21 -62
  105. package/lib/wxs/WxsModuleIdsPlugin.js +29 -0
  106. package/lib/wxs/WxsParserPlugin.js +2 -2
  107. package/lib/wxs/WxsPlugin.js +4 -8
  108. package/lib/wxs/WxsTemplatePlugin.js +46 -92
  109. package/lib/wxs/{wxs-i18n-loader.js → i18n-loader.js} +5 -4
  110. package/lib/wxs/loader.js +142 -0
  111. package/lib/wxs/{wxs-pre-loader.js → pre-loader.js} +20 -5
  112. package/lib/wxss/loader.js +31 -43
  113. package/lib/wxss/localsLoader.js +1 -5
  114. package/lib/wxss/processCss.js +107 -103
  115. package/package.json +21 -18
  116. package/lib/built-in-loader.js +0 -49
  117. package/lib/content-loader.js +0 -13
  118. package/lib/dependency/ChildCompileDependency.js +0 -24
  119. package/lib/dependency/InjectDependency.js +0 -26
  120. package/lib/dependency/RemovedModuleDependency.js +0 -23
  121. package/lib/dependency/ResolveDependency.js +0 -49
  122. package/lib/path-loader.js +0 -3
  123. package/lib/plugin-loader.js +0 -287
  124. package/lib/staticConfig.js +0 -4
  125. package/lib/utils/get-main-compilation.js +0 -6
  126. package/lib/utils/read-json-for-src.js +0 -34
  127. package/lib/utils/try-require.js +0 -16
  128. package/lib/wxs/wxs-loader.js +0 -117
  129. 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)
@@ -176,6 +141,9 @@ module.exports = function (raw = '{}') {
176
141
  if (!json.usingComponents) {
177
142
  json.usingComponents = {}
178
143
  }
144
+ if (!json.component && mode === 'swan') {
145
+ json.component = true
146
+ }
179
147
  }
180
148
  } else if (componentsMap[resourcePath]) {
181
149
  // component
@@ -221,13 +189,7 @@ module.exports = function (raw = '{}') {
221
189
  } else {
222
190
  // 保存全局注册组件
223
191
  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
- })
192
+ this._module.addPresentationalDependency(new RecordGlobalComponentsDependency(json.usingComponents, this.context))
231
193
  }
232
194
  }
233
195
 
@@ -237,141 +199,68 @@ module.exports = function (raw = '{}') {
237
199
  rulesRunner(json)
238
200
  }
239
201
 
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
202
  const processComponents = (components, context, callback) => {
247
203
  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))
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()
252
209
  }
253
- components[name] = componentPath
254
- }, undefined, callback)
210
+ if (err) return callback(err)
211
+ components[name] = entry
212
+ callback()
213
+ })
255
214
  }, callback)
256
215
  } else {
257
216
  callback()
258
217
  }
259
218
  }
260
219
 
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
220
  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
221
  // app.json
350
- const subPackagesCfg = {}
351
222
  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 })
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)
357
246
  } else {
358
- json.pages[0] = addQuery(json.pages[0], { isFirst: true })
247
+ callback()
359
248
  }
360
249
  }
361
250
 
362
251
  const processPackages = (packages, context, callback) => {
363
252
  if (packages) {
364
- async.forEach(packages, (packagePath, callback) => {
253
+ async.each(packages, (packagePath, callback) => {
365
254
  const { queryObj } = parseRequest(packagePath)
366
255
  async.waterfall([
367
256
  (callback) => {
368
- resolve(context, packagePath, (err, result) => {
257
+ resolve(context, packagePath, this, (err, result) => {
258
+ if (err) return callback(err)
369
259
  const { rawResourcePath } = parseRequest(result)
370
260
  callback(err, rawResourcePath)
371
261
  })
372
262
  },
373
263
  (result, callback) => {
374
- this.addDependency(result)
375
264
  fs.readFile(result, (err, content) => {
376
265
  if (err) return callback(err)
377
266
  callback(err, result, content.toString('utf-8'))
@@ -379,24 +268,21 @@ module.exports = function (raw = '{}') {
379
268
  },
380
269
  (result, content, callback) => {
381
270
  const extName = path.extname(result)
382
- if (extName === '.mpx' || extName === '.vue') {
271
+ if (extName === '.mpx') {
383
272
  const parts = parseComponent(content, {
384
273
  filePath: result,
385
274
  needMap: this.sourceMap,
386
275
  mode,
387
- defs,
388
276
  env
389
277
  })
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
- }
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)
398
285
  }
399
- callback(null, result, content)
400
286
  },
401
287
  (result, content, callback) => {
402
288
  try {
@@ -422,12 +308,12 @@ module.exports = function (raw = '{}') {
422
308
  subPackage.plugins = content.plugins
423
309
  }
424
310
 
425
- processSubPackagesQueue.push((callback) => {
311
+ processSelfQueue.push((callback) => {
426
312
  processSubPackage(subPackage, context, callback)
427
313
  })
428
314
  } else {
429
315
  processSelfQueue.push((callback) => {
430
- processPages(content.pages, '', '', context, callback)
316
+ processPages(content.pages, context, '', callback)
431
317
  })
432
318
  }
433
319
  }
@@ -442,14 +328,16 @@ module.exports = function (raw = '{}') {
442
328
  callback()
443
329
  }
444
330
  }
445
- ], callback)
331
+ ], (err) => {
332
+ callback(err === RESOLVE_IGNORED_ERR ? null : err)
333
+ })
446
334
  }, callback)
447
335
  } else {
448
336
  callback()
449
337
  }
450
338
  }
451
339
 
452
- const getOtherConfig = (raw) => {
340
+ const getOtherConfig = (config) => {
453
341
  let result = {}
454
342
  let blackListMap = {
455
343
  tarRoot: true,
@@ -457,14 +345,39 @@ module.exports = function (raw = '{}') {
457
345
  root: true,
458
346
  pages: true
459
347
  }
460
- for (let key in raw) {
348
+ for (let key in config) {
461
349
  if (!blackListMap[key]) {
462
- result[key] = raw[key]
350
+ result[key] = config[key]
463
351
  }
464
352
  }
465
353
  return result
466
354
  }
467
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
+
468
381
  // 为了获取资源的所属子包,该函数需串行执行
469
382
  const processSubPackage = (subPackage, context, callback) => {
470
383
  if (subPackage) {
@@ -476,29 +389,27 @@ module.exports = function (raw = '{}') {
476
389
  let srcRoot = subPackage.srcRoot || subPackage.root || ''
477
390
  if (!tarRoot || subPackagesCfg[tarRoot]) return callback()
478
391
 
392
+ context = path.join(context, srcRoot)
479
393
  const otherConfig = getOtherConfig(subPackage)
480
- // 支付宝不支持独立分包,无需处理
481
- if (otherConfig.independent && mode !== 'ali') {
482
- mpx.independentSubpackagesMap[tarRoot] = true
483
- }
484
-
485
394
  subPackagesCfg[tarRoot] = {
486
395
  root: tarRoot,
487
- pages: [],
488
- ...otherConfig
396
+ pages: []
489
397
  }
490
- mpx.currentPackageRoot = tarRoot
491
- mpx.componentsMap[tarRoot] = {}
492
- mpx.staticResourcesMap[tarRoot] = {}
493
- mpx.subpackageModulesMap[tarRoot] = {}
494
398
  async.parallel([
495
399
  (callback) => {
496
- processPages(subPackage.pages, srcRoot, tarRoot, context, callback)
400
+ processIndependent(otherConfig, context, tarRoot, callback)
401
+ },
402
+ (callback) => {
403
+ processPages(subPackage.pages, context, tarRoot, callback)
497
404
  },
498
405
  (callback) => {
499
- processPlugins(subPackage.plugins, srcRoot, tarRoot, context, callback)
406
+ processPlugins(subPackage.plugins, context, tarRoot, callback)
500
407
  }
501
- ], callback)
408
+ ], (err) => {
409
+ if (err) return callback(err)
410
+ Object.assign(subPackagesCfg[tarRoot], otherConfig)
411
+ callback()
412
+ })
502
413
  } else {
503
414
  callback()
504
415
  }
@@ -506,92 +417,8 @@ module.exports = function (raw = '{}') {
506
417
 
507
418
  const processSubPackages = (subPackages, context, callback) => {
508
419
  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
- })
420
+ async.each(subPackages, (subPackage, callback) => {
421
+ processSubPackage(subPackage, context, callback)
595
422
  }, callback)
596
423
  } else {
597
424
  callback()
@@ -630,15 +457,11 @@ module.exports = function (raw = '{}') {
630
457
 
631
458
  const processThemeLocation = (output) => {
632
459
  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`
460
+ const requestString = getRequestString('json', { src: urlToRequest(json.themeLocation) }, {
461
+ isTheme: true,
462
+ isStatic: true
463
+ })
464
+ output += `json.themeLocation = require(${requestString});\n`
642
465
  }
643
466
  return output
644
467
  }
@@ -655,146 +478,114 @@ module.exports = function (raw = '{}') {
655
478
 
656
479
  const processCustomTabBar = (tabBar, context, callback) => {
657
480
  if (tabBar && tabBar.custom) {
658
- 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
+ })
659
489
  } else {
660
490
  callback()
661
491
  }
662
492
  }
663
493
 
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))
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()
678
506
  }
679
- genericComponents[name] = componentPath
680
- }, undefined, callback)
507
+ if (err) return callback(err)
508
+ genericComponents[name] = entry
509
+ })
681
510
  }, callback)
682
511
  }, callback)
683
512
  }
684
513
 
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}!`))
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()
701
520
  }
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
- })
521
+ if (err) return callback(err)
522
+ plugin.export = entry
523
+ callback()
709
524
  })
710
525
  }
711
526
 
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) => {
527
+ const processPlugins = (plugins, context, tarRoot = '', callback) => {
528
+ if (mode !== 'wx' || !plugins) return callback() // 目前只有微信支持导出到插件
529
+ async.eachOf(plugins, (plugin, name, callback) => {
717
530
  async.parallel([
718
531
  (callback) => {
719
- if (plugin.genericsImplementation) {
720
- processPluginGenericsImplementation(plugin.genericsImplementation, tarRoot, context, callback)
721
- } else {
722
- callback()
723
- }
532
+ processPluginGenericsImplementation(plugin, context, tarRoot, callback)
724
533
  },
725
534
  (callback) => {
726
- processPluginExport(plugin, tarRoot, context, callback)
535
+ processPluginExport(plugin, context, tarRoot, callback)
727
536
  }
728
- ], (err) => {
729
- callback(err)
730
- })
537
+ ], callback)
731
538
  }, callback)
732
539
  }
733
540
 
734
- // 串行处理,先处理主包代码,再处理分包代码,为了正确识别出分包中定义的组件属于主包还是分包
735
- let errors = []
736
- // 外部收集errors,确保整个series流程能够执行完
737
- async.series([
541
+ async.parallel([
738
542
  (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)
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 })
764
549
  }
765
- callback()
766
- })
550
+ }
551
+ processPages(json.pages, this.context, '', callback)
767
552
  },
768
553
  (callback) => {
769
- if (mpx.appScriptPromise) {
770
- mpx.appScriptPromise.then(callback)
771
- } else {
772
- callback()
773
- }
554
+ processComponents(json.usingComponents, this.context, callback)
774
555
  },
775
556
  (callback) => {
776
- async.series(processSubPackagesQueue, (err) => {
777
- if (err) {
778
- errors.push(err)
779
- }
780
- // 处理完分包后重置currentPackageRoot以确保app中的资源输出到主包
781
- mpx.currentPackageRoot = ''
782
- callback()
783
- })
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)
784
570
  }
785
- ], () => {
786
- if (errors.length) return callback(errors[0])
571
+ ], (err) => {
572
+ if (err) return callback(err)
787
573
  delete json.packages
788
574
  delete json.subpackages
789
575
  delete json.subPackages
790
576
  json.pages = localPages
791
577
  for (let root in subPackagesCfg) {
792
- if (!json.subPackages) {
793
- 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)
794
585
  }
795
- json.subPackages.push(subPackagesCfg[root])
796
586
  }
797
587
  const processOutput = (output) => {
588
+ output = processDynamicEntry(output)
798
589
  output = processTabBar(output)
799
590
  output = processOptionMenu(output)
800
591
  output = processThemeLocation(output)
@@ -803,16 +594,20 @@ module.exports = function (raw = '{}') {
803
594
  callback(null, processOutput)
804
595
  })
805
596
  } else {
597
+ // page.json或component.json
806
598
  const processGenerics = (generics, context, callback) => {
807
599
  if (generics) {
808
- async.forEachOf(generics, (generic, name, callback) => {
600
+ async.eachOf(generics, (generic, name, callback) => {
809
601
  if (generic.default) {
810
- processComponent(generic.default, context, (componentPath) => {
811
- if (useRelativePath === true) {
812
- 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()
813
606
  }
814
- generic.default = componentPath
815
- }, undefined, callback)
607
+ if (err) return callback(err)
608
+ generic.default = entry
609
+ callback()
610
+ })
816
611
  } else {
817
612
  callback()
818
613
  }
@@ -821,7 +616,6 @@ module.exports = function (raw = '{}') {
821
616
  callback()
822
617
  }
823
618
  }
824
- // page.json或component.json
825
619
  async.parallel([
826
620
  (callback) => {
827
621
  processComponents(json.usingComponents, this.context, callback)
@@ -830,7 +624,7 @@ module.exports = function (raw = '{}') {
830
624
  processGenerics(json.componentGenerics, this.context, callback)
831
625
  }
832
626
  ], (err) => {
833
- callback(err)
627
+ callback(err, processDynamicEntry)
834
628
  })
835
629
  }
836
630
  }