@mpxjs/webpack-plugin 2.7.0-beta.4 → 2.7.0-beta.8

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 (34) hide show
  1. package/lib/dependencies/CommonJsVariableDependency.js +1 -3
  2. package/lib/dependencies/DynamicEntryDependency.js +2 -1
  3. package/lib/dependencies/{RecordStaticResourceDependency.js → RecordResourceMapDependency.js} +12 -7
  4. package/lib/dependencies/ResolveDependency.js +8 -7
  5. package/lib/extractor.js +4 -4
  6. package/lib/file-loader.js +2 -2
  7. package/lib/index.js +154 -118
  8. package/lib/json-compiler/helper.js +14 -11
  9. package/lib/json-compiler/index.js +19 -13
  10. package/lib/loader.js +27 -36
  11. package/lib/platform/json/wx/index.js +7 -2
  12. package/lib/platform/template/wx/component-config/button.js +3 -3
  13. package/lib/platform/template/wx/component-config/navigator.js +1 -1
  14. package/lib/runtime/base.styl +5 -0
  15. package/lib/runtime/components/web/getInnerListeners.js +51 -45
  16. package/lib/runtime/components/web/mpx-keep-alive.vue +4 -1
  17. package/lib/runtime/components/web/mpx-tab-bar-container.vue +2 -2
  18. package/lib/runtime/optionProcessor.js +5 -20
  19. package/lib/runtime/stringify.wxs +3 -3
  20. package/lib/style-compiler/index.js +4 -5
  21. package/lib/template-compiler/bind-this.js +4 -4
  22. package/lib/template-compiler/compiler.js +100 -36
  23. package/lib/template-compiler/index.js +3 -6
  24. package/lib/template-compiler/trans-dynamic-class-expr.js +3 -3
  25. package/lib/utils/const.js +3 -1
  26. package/lib/web/processJSON.js +105 -113
  27. package/lib/web/processScript.js +30 -24
  28. package/lib/web/processTemplate.js +56 -37
  29. package/lib/wxs/loader.js +24 -27
  30. package/lib/wxs/pre-loader.js +4 -4
  31. package/lib/wxss/processCss.js +44 -44
  32. package/package.json +8 -8
  33. package/lib/built-in-loader.js +0 -45
  34. package/lib/record-loader.js +0 -11
@@ -1,6 +1,7 @@
1
1
  const JSON5 = require('json5')
2
2
  const he = require('he')
3
3
  const config = require('../config')
4
+ const { MPX_ROOT_VIEW, MPX_APP_MODULE_ID } = require('../utils/const')
4
5
  const normalize = require('../utils/normalize')
5
6
  const isValidIdentifierStr = require('../utils/is-valid-identifier-str')
6
7
  const isEmptyObject = require('../utils/is-empty-object')
@@ -1710,31 +1711,71 @@ function processAliExternalClassesHack (el, options) {
1710
1711
  }
1711
1712
  }
1712
1713
 
1714
+ // externalClasses只能模拟静态传递
1713
1715
  function processWebExternalClassesHack (el, options) {
1714
- // todo 处理scoped的情况, 处理组件多层传递externalClass的情况,通过externalClass属性传递实际类名及scopeId信息,可以使用特殊的类名形式代表scopeId,如#idstring
1715
- let staticClass = el.attrsMap['class']
1716
- let dynamicClass = el.attrsMap[':class']
1717
- if (staticClass || dynamicClass) {
1718
- const externalClasses = []
1716
+ const staticClass = getAndRemoveAttr(el, 'class').val
1717
+ if (staticClass) {
1718
+ const classNames = staticClass.split(/\s+/)
1719
+ const replacements = []
1719
1720
  options.externalClasses.forEach((className) => {
1720
- const reg = new RegExp('\\b' + className + '\\b')
1721
- if (reg.test(staticClass) || reg.test(dynamicClass)) {
1722
- externalClasses.push(className)
1721
+ const index = classNames.indexOf(className)
1722
+ if (index > -1) {
1723
+ replacements.push(`$attrs[${JSON.stringify(className)}]`)
1724
+ classNames.splice(index, 1)
1723
1725
  }
1724
1726
  })
1725
- if (externalClasses.length) {
1727
+
1728
+ if (classNames.length) {
1729
+ addAttrs(el, [{
1730
+ name: 'class',
1731
+ value: classNames.join(' ')
1732
+ }])
1733
+ }
1734
+
1735
+ if (replacements.length) {
1736
+ const dynamicClass = getAndRemoveAttr(el, ':class').val
1737
+ if (dynamicClass) replacements.push(dynamicClass)
1738
+
1726
1739
  addAttrs(el, [{
1727
- name: 'v-ex-classes',
1728
- value: JSON.stringify(externalClasses)
1740
+ name: ':class',
1741
+ value: `[${replacements.join(',')}]`
1729
1742
  }])
1730
1743
  }
1731
1744
  }
1745
+
1746
+ // 处理externalClasses多层透传
1747
+ const isComponent = isComponentNode(el, options)
1748
+ if (isComponent) {
1749
+ options.externalClasses.forEach((classLikeAttrName) => {
1750
+ let classLikeAttrValue = getAndRemoveAttr(el, classLikeAttrName).val
1751
+ if (classLikeAttrValue) {
1752
+ const classNames = classLikeAttrValue.split(/\s+/)
1753
+ const replacements = []
1754
+ options.externalClasses.forEach((className) => {
1755
+ const index = classNames.indexOf(className)
1756
+ if (index > -1) {
1757
+ replacements.push(`$attrs[${JSON.stringify(className)}]`)
1758
+ classNames.splice(index, 1)
1759
+ }
1760
+ })
1761
+
1762
+ if (classNames.length) {
1763
+ replacements.unshift(JSON.stringify(classNames.join(' ')))
1764
+ }
1765
+
1766
+ addAttrs(el, [{
1767
+ name: ':' + classLikeAttrName,
1768
+ value: `[${replacements.join(',')}].join(' ')`
1769
+ }])
1770
+ }
1771
+ })
1772
+ }
1732
1773
  }
1733
1774
 
1734
1775
  function processScoped (el, options) {
1735
1776
  if (options.hasScoped && isRealNode(el)) {
1736
1777
  const moduleId = options.moduleId
1737
- const rootModuleId = options.isComponent ? '' : 'mpx-app-scope' // 处理app全局样式对页面的影响
1778
+ const rootModuleId = options.isComponent ? '' : MPX_APP_MODULE_ID // 处理app全局样式对页面的影响
1738
1779
  const staticClass = getAndRemoveAttr(el, 'class').val
1739
1780
  addAttrs(el, [{
1740
1781
  name: 'class',
@@ -1757,17 +1798,33 @@ function processBuiltInComponents (el, meta) {
1757
1798
  }
1758
1799
  }
1759
1800
 
1760
- function processAliStyleClassHack (el, options) {
1761
- if (!isComponentNode(el, options)) return
1801
+ function processAliStyleClassHack (el, options, root) {
1802
+ let processor
1803
+ // 处理组件标签
1804
+ if (isComponentNode(el, options)) processor = ({ value, typeName }) => [typeName, value]
1805
+ // 处理组件根节点
1806
+ if (options.isComponent && el === root && isRealNode(el)) {
1807
+ processor = ({ name, value, typeName }) => {
1808
+ let sep = name === 'style' ? ';' : ' '
1809
+ value = value ? `{{${typeName}||''}}${sep}${value}` : `{{${typeName}||''}}`
1810
+ return [name, value]
1811
+ }
1812
+ }
1813
+ // 非上述两种不处理
1814
+ if (!processor) return
1815
+ // 处理style、class
1762
1816
  ['style', 'class'].forEach((type) => {
1763
1817
  let exp = getAndRemoveAttr(el, type).val
1764
- let typeName = 'mpx' + type.replace(/^./, (matched) => {
1765
- return matched.toUpperCase()
1818
+ let typeName = 'mpx' + type.replace(/^./, (matched) => matched.toUpperCase())
1819
+ let [newName, newValue] = processor({
1820
+ name: type,
1821
+ value: exp,
1822
+ typeName
1766
1823
  })
1767
- if (exp !== undefined) {
1824
+ if (newValue !== undefined) {
1768
1825
  addAttrs(el, [{
1769
- name: typeName,
1770
- value: exp
1826
+ name: newName,
1827
+ value: newValue
1771
1828
  }])
1772
1829
  }
1773
1830
  })
@@ -1775,21 +1832,24 @@ function processAliStyleClassHack (el, options) {
1775
1832
 
1776
1833
  // 有virtualHost情况wx组件注入virtualHost。无virtualHost阿里组件注入root-view。其他跳过。
1777
1834
  function getVirtualHostRoot (options, meta) {
1778
- if (mode === 'wx' && options.hasVirtualHost && options.isComponent) {
1779
- !meta.options && (meta.options = {})
1780
- meta.options.virtualHost = true
1781
- }
1782
- if (mode === 'ali' && !options.hasVirtualHost && options.isComponent) {
1783
- return createASTElement('view', [
1784
- {
1785
- name: 'class',
1786
- value: `mpx-root-view host-${options.moduleId} ${options.hasScoped ? options.moduleId : ''} {{mpxClass||''}}`
1787
- },
1788
- {
1789
- name: 'style',
1790
- value: `{{mpxStyle||''}}`
1791
- }
1792
- ])
1835
+ if (options.isComponent) {
1836
+ // 处理组件时
1837
+ if (mode === 'wx' && options.hasVirtualHost) {
1838
+ // wx组件注入virtualHost配置
1839
+ !meta.options && (meta.options = {})
1840
+ meta.options.virtualHost = true
1841
+ }
1842
+ if (mode === 'ali' && !options.hasVirtualHost) {
1843
+ // ali组件根节点实体化
1844
+ let rootView = createASTElement('view', [
1845
+ {
1846
+ name: 'class',
1847
+ value: `${MPX_ROOT_VIEW} host-${options.moduleId}`
1848
+ }
1849
+ ])
1850
+ processElement(rootView, rootView, options, meta)
1851
+ return rootView
1852
+ }
1793
1853
  }
1794
1854
  return getTempNode()
1795
1855
  }
@@ -1797,7 +1857,10 @@ function getVirtualHostRoot (options, meta) {
1797
1857
  function processShow (el, options, root) {
1798
1858
  let show = getAndRemoveAttr(el, config[mode].directive.show).val
1799
1859
  if (mode === 'swan') show = wrapMustache(show)
1800
- if (options.isComponent && el.parent === root && isRealNode(el)) {
1860
+ let processFlag = el.parent === root
1861
+ // 当ali且未开启virtualHost时,mpxShow打到根节点上
1862
+ if (mode === 'ali' && !options.hasVirtualHost) processFlag = el === root
1863
+ if (options.isComponent && processFlag && isRealNode(el)) {
1801
1864
  if (show !== undefined) {
1802
1865
  show = `{{${parseMustache(show).result}&&mpxShow}}`
1803
1866
  } else {
@@ -2279,5 +2342,6 @@ module.exports = {
2279
2342
  makeAttrsMap,
2280
2343
  stringifyAttr,
2281
2344
  parseMustache,
2282
- stringifyWithResolveComputed
2345
+ stringifyWithResolveComputed,
2346
+ addAttrs
2283
2347
  }
@@ -38,7 +38,7 @@ module.exports = function (raw) {
38
38
  )
39
39
  }
40
40
 
41
- const parsed = compiler.parse(raw, {
41
+ const { root: ast, meta } = compiler.parse(raw, {
42
42
  warn,
43
43
  error,
44
44
  usingComponents,
@@ -57,13 +57,10 @@ module.exports = function (raw) {
57
57
  i18n,
58
58
  checkUsingComponents: mpx.checkUsingComponents,
59
59
  globalComponents: Object.keys(mpx.usingComponents),
60
- forceProxyEvent: matchCondition(this.resourcePath, mpx.forceProxyEventRules),
61
- hasVirtualHost: matchCondition(this.resourcePath, mpx.autoVirtualHostRules)
60
+ forceProxyEvent: matchCondition(resourcePath, mpx.forceProxyEventRules),
61
+ hasVirtualHost: matchCondition(resourcePath, mpx.autoVirtualHostRules)
62
62
  })
63
63
 
64
- let ast = parsed.root
65
- let meta = parsed.meta
66
-
67
64
  if (meta.wxsContentMap) {
68
65
  for (let module in meta.wxsContentMap) {
69
66
  wxsContentMap[`${resourcePath}~${module}`] = meta.wxsContentMap[module]
@@ -1,6 +1,6 @@
1
- const babylon = require('babylon')
2
- const t = require('babel-types')
3
- const generate = require('babel-generator').default
1
+ const babylon = require('@babel/parser')
2
+ const t = require('@babel/types')
3
+ const generate = require('@babel/generator').default
4
4
  const dash2hump = require('../utils/hump-dash').dash2hump
5
5
 
6
6
  module.exports = function transDynamicClassExpr (expr) {
@@ -3,5 +3,7 @@ module.exports = {
3
3
  MPX_DISABLE_EXTRACTOR_CACHE: 'mpx_disable_extractor_cache',
4
4
  DEFAULT_RESULT_SOURCE: '',
5
5
  RESOLVE_IGNORED_ERR: new Error('Resolve ignored!'),
6
- JSON_JS_EXT: '.json.js'
6
+ JSON_JS_EXT: '.json.js',
7
+ MPX_ROOT_VIEW: 'mpx-root-view', // 根节点类名
8
+ MPX_APP_MODULE_ID: 'mpx-app-scope' // app文件moduleId
7
9
  }
@@ -7,18 +7,29 @@ const toPosix = require('../utils/to-posix')
7
7
  const addQuery = require('../utils/add-query')
8
8
  const parseComponent = require('../parser')
9
9
  const getJSONContent = require('../utils/get-json-content')
10
- const isUrlRequest = require('../utils/is-url-request')
11
10
  const resolve = require('../utils/resolve')
11
+ const createJSONHelper = require('../json-compiler/helper')
12
+ const { RESOLVE_IGNORED_ERR } = require('../utils/const')
13
+ const RecordResourceMapDependency = require('../dependencies/RecordResourceMapDependency')
12
14
 
13
- module.exports = function (json, { mode, env, loaderContext, resolveMode, pagesMap, componentsMap, pagesEntryMap, projectRoot, pathHash }, rawCallback) {
15
+ module.exports = function (json, {
16
+ loaderContext,
17
+ pagesMap,
18
+ componentsMap
19
+ }, rawCallback) {
14
20
  const localPagesMap = {}
15
21
  const localComponentsMap = {}
16
- const buildInfo = loaderContext._module.buildInfo
17
-
18
22
  let output = '/* json */\n'
19
23
  let jsonObj = {}
20
24
  let tabBarMap
21
25
  let tabBarStr
26
+ const mpx = loaderContext.getMpx()
27
+ const {
28
+ mode,
29
+ env,
30
+ projectRoot
31
+ } = mpx
32
+
22
33
  const context = loaderContext.context
23
34
 
24
35
  const emitWarning = (msg) => {
@@ -28,13 +39,31 @@ module.exports = function (json, { mode, env, loaderContext, resolveMode, pagesM
28
39
  }
29
40
 
30
41
  const emitError = (msg) => {
31
- this.emitError(
32
- new Error('[json compiler][' + this.resource + ']: ' + msg)
42
+ loaderContext.emitError(
43
+ new Error('[json compiler][' + loaderContext.resource + ']: ' + msg)
33
44
  )
34
45
  }
35
46
 
36
47
  const stringifyRequest = r => loaderUtils.stringifyRequest(loaderContext, r)
37
48
 
49
+ const {
50
+ isUrlRequest,
51
+ urlToRequest,
52
+ processPage,
53
+ processComponent
54
+ } = createJSONHelper({
55
+ loaderContext,
56
+ emitWarning,
57
+ emitError,
58
+ customGetDynamicEntry (resource, type, outputPath, packageRoot) {
59
+ return {
60
+ resource,
61
+ outputPath: toPosix(path.join(packageRoot, outputPath)),
62
+ packageRoot
63
+ }
64
+ }
65
+ })
66
+
38
67
  const callback = (err) => {
39
68
  return rawCallback(err, {
40
69
  output,
@@ -75,7 +104,7 @@ module.exports = function (json, { mode, env, loaderContext, resolveMode, pagesM
75
104
  tabBarStr = JSON.stringify(tabBar)
76
105
  tabBarStr = tabBarStr.replace(/"(iconPath|selectedIconPath)":"([^"]+)"/g, function (matched, $1, $2) {
77
106
  if (isUrlRequest($2, projectRoot)) {
78
- return `"${$1}":require(${stringifyRequest(loaderUtils.urlToRequest($2, projectRoot))})`
107
+ return `"${$1}":require(${stringifyRequest(urlToRequest($2, projectRoot))})`
79
108
  }
80
109
  return matched
81
110
  })
@@ -85,15 +114,14 @@ module.exports = function (json, { mode, env, loaderContext, resolveMode, pagesM
85
114
 
86
115
  const processPackages = (packages, context, callback) => {
87
116
  if (packages) {
88
- async.forEach(packages, (packagePath, callback) => {
89
- const parsed = parseRequest(packagePath)
90
- const queryObj = parsed.queryObj
91
- // readFile无法处理query
92
- packagePath = parsed.resourcePath
117
+ async.each(packages, (packagePath, callback) => {
118
+ const { queryObj } = parseRequest(packagePath)
93
119
  async.waterfall([
94
120
  (callback) => {
95
121
  resolve(context, packagePath, loaderContext, (err, result) => {
96
- callback(err, result)
122
+ if (err) return callback(err)
123
+ const { rawResourcePath } = parseRequest(result)
124
+ callback(err, rawResourcePath)
97
125
  })
98
126
  },
99
127
  (result, callback) => {
@@ -103,11 +131,10 @@ module.exports = function (json, { mode, env, loaderContext, resolveMode, pagesM
103
131
  })
104
132
  },
105
133
  (result, content, callback) => {
106
- const filePath = result
107
- const extName = path.extname(filePath)
134
+ const extName = path.extname(result)
108
135
  if (extName === '.mpx' || extName === '.vue') {
109
136
  const parts = parseComponent(content, {
110
- filePath,
137
+ filePath: result,
111
138
  needMap: loaderContext.sourceMap,
112
139
  mode,
113
140
  env
@@ -138,12 +165,17 @@ module.exports = function (json, { mode, env, loaderContext, resolveMode, pagesM
138
165
  pages: content.pages,
139
166
  ...queryObj
140
167
  }
168
+
169
+ if (content.plugins) {
170
+ subPackage.plugins = content.plugins
171
+ }
172
+
141
173
  processSelfQueue.push((callback) => {
142
174
  processSubPackage(subPackage, context, callback)
143
175
  })
144
176
  } else {
145
177
  processSelfQueue.push((callback) => {
146
- processPages(content.pages, '', '', context, callback)
178
+ processPages(content.pages, context, '', callback)
147
179
  })
148
180
  }
149
181
  }
@@ -158,77 +190,41 @@ module.exports = function (json, { mode, env, loaderContext, resolveMode, pagesM
158
190
  callback()
159
191
  }
160
192
  }
161
- ], callback)
193
+ ], (err) => {
194
+ callback(err === RESOLVE_IGNORED_ERR ? null : err)
195
+ })
162
196
  }, callback)
163
197
  } else {
164
198
  callback()
165
199
  }
166
200
  }
167
201
 
168
- const getPageName = (resourcePath, ext) => {
169
- const baseName = path.basename(resourcePath, ext)
170
- return path.join('pages', baseName + pathHash(resourcePath), baseName)
171
- }
202
+ const pageKeySet = new Set()
172
203
 
173
- const processPages = (pages, srcRoot = '', tarRoot = '', context, callback) => {
204
+ const processPages = (pages, context, tarRoot = '', callback) => {
174
205
  if (pages) {
175
- context = path.join(context, srcRoot)
176
- async.forEach(pages, (page, callback) => {
177
- let aliasPath = ''
178
- if (typeof page !== 'string') {
179
- aliasPath = page.path
180
- page = page.src
181
- }
182
- if (!isUrlRequest(page, projectRoot)) return callback()
183
- if (resolveMode === 'native') {
184
- page = loaderUtils.urlToRequest(page, projectRoot)
185
- }
186
- resolve(context, page, loaderContext, (err, resource) => {
187
- if (err) return callback(err)
206
+ async.each(pages, (page, callback) => {
207
+ processPage(page, context, tarRoot, (err, { resource, outputPath } = {}, { isFirst, key } = {}) => {
208
+ if (err) return callback(err === RESOLVE_IGNORED_ERR ? null : err)
209
+ if (pageKeySet.has(key)) return callback()
210
+ pageKeySet.add(key)
188
211
  const { resourcePath, queryObj } = parseRequest(resource)
189
- const ext = path.extname(resourcePath)
190
- // 获取pageName
191
- let pageName
192
- if (aliasPath) {
193
- pageName = toPosix(path.join(tarRoot, aliasPath))
194
- // 判断 key 存在重复情况直接报错
195
- for (let key in pagesMap) {
196
- if (pagesMap[key] === pageName && key !== resourcePath) {
197
- emitError(`Current page [${resourcePath}] registers a conflict page path [${pageName}] with existed page [${key}], which is not allowed, please rename it!`)
198
- return callback()
199
- }
200
- }
201
- } else {
202
- const relative = path.relative(context, resourcePath)
203
- if (/^\./.test(relative)) {
204
- // 如果当前page不存在于context中,对其进行重命名
205
- pageName = toPosix(path.join(tarRoot, getPageName(resourcePath, ext)))
206
- 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!`)
207
- } else {
208
- pageName = toPosix(path.join(tarRoot, /^(.*?)(\.[^.]*)?$/.exec(relative)[1]))
209
- // 如果当前page与已有page存在命名冲突,也进行重命名
210
- for (let key in pagesMap) {
211
- // 此处引入pagesEntryMap确保相同entry下路由路径重复注册才报错,不同entry下的路由路径重复则无影响
212
- if (pagesMap[key] === pageName && key !== resourcePath && pagesEntryMap[key] === loaderContext.resourcePath) {
213
- const pageNameRaw = pageName
214
- pageName = toPosix(path.join(tarRoot, getPageName(resourcePath, ext)))
215
- 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!`)
216
- break
217
- }
218
- }
212
+ if (localPagesMap[outputPath]) {
213
+ const { resourcePath: oldResourcePath } = parseRequest(localPagesMap[outputPath].resource)
214
+ if (oldResourcePath !== resourcePath) {
215
+ const oldOutputPath = outputPath
216
+ outputPath = mpx.getOutputPath(resourcePath, 'page', { conflictPath: outputPath })
217
+ emitWarning(new Error(`Current page [${resourcePath}] is registered with a conflict outputPath [${oldOutputPath}] which is already existed in system, will be renamed with [${outputPath}], use ?resolve to get the real outputPath!`))
219
218
  }
220
219
  }
221
- if (pagesMap[resourcePath]) {
222
- emitWarning(`Current page [${resourcePath}] which is imported from [${loaderContext.resourcePath}] has been registered in pagesMap already, it will be ignored, please check it and remove the redundant page declaration!`)
223
- return callback()
224
- }
225
- buildInfo.pagesMap = buildInfo.pagesMap || {}
226
- buildInfo.pagesMap[resourcePath] = pagesMap[resourcePath] = pageName
227
- pagesEntryMap[resourcePath] = loaderContext.resourcePath
228
- localPagesMap[pageName] = {
229
- resource: addQuery(resource, { page: true }),
220
+
221
+ pagesMap[resourcePath] = outputPath
222
+ loaderContext._module.addPresentationalDependency(new RecordResourceMapDependency(resourcePath, 'page', outputPath))
223
+
224
+ localPagesMap[outputPath] = {
225
+ resource: addQuery(resource, { isPage: true }),
230
226
  async: tarRoot || queryObj.async,
231
- isFirst: queryObj.isFirst
227
+ isFirst
232
228
  }
233
229
  callback()
234
230
  })
@@ -240,10 +236,15 @@ module.exports = function (json, { mode, env, loaderContext, resolveMode, pagesM
240
236
 
241
237
  const processSubPackage = (subPackage, context, callback) => {
242
238
  if (subPackage) {
239
+ if (typeof subPackage.root === 'string' && subPackage.root.startsWith('.')) {
240
+ emitError(`Current subpackage root [${subPackage.root}] is not allow starts with '.'`)
241
+ return callback()
242
+ }
243
243
  let tarRoot = subPackage.tarRoot || subPackage.root || ''
244
244
  let srcRoot = subPackage.srcRoot || subPackage.root || ''
245
245
  if (!tarRoot) return callback()
246
- processPages(subPackage.pages, srcRoot, tarRoot, context, callback)
246
+ context = path.join(context, srcRoot)
247
+ processPages(subPackage.pages, context, tarRoot, callback)
247
248
  } else {
248
249
  callback()
249
250
  }
@@ -251,7 +252,7 @@ module.exports = function (json, { mode, env, loaderContext, resolveMode, pagesM
251
252
 
252
253
  const processSubPackages = (subPackages, context, callback) => {
253
254
  if (subPackages) {
254
- async.forEach(subPackages, (subPackage, callback) => {
255
+ async.each(subPackages, (subPackage, callback) => {
255
256
  processSubPackage(subPackage, context, callback)
256
257
  }, callback)
257
258
  } else {
@@ -261,48 +262,38 @@ module.exports = function (json, { mode, env, loaderContext, resolveMode, pagesM
261
262
 
262
263
  const processComponents = (components, context, callback) => {
263
264
  if (components) {
264
- async.forEachOf(components, (component, name, callback) => {
265
- processComponent(component, name, context, callback)
265
+ async.eachOf(components, (component, name, callback) => {
266
+ processComponent(component, context, {}, (err, { resource, outputPath } = {}) => {
267
+ if (err === RESOLVE_IGNORED_ERR) {
268
+ return callback()
269
+ }
270
+ const { resourcePath, queryObj } = parseRequest(resource)
271
+ componentsMap[resourcePath] = outputPath
272
+ loaderContext._module.addPresentationalDependency(new RecordResourceMapDependency(resourcePath, 'component', outputPath))
273
+
274
+ localComponentsMap[name] = {
275
+ resource: addQuery(resource, {
276
+ isComponent: true,
277
+ outputPath
278
+ }),
279
+ async: queryObj.async
280
+ }
281
+ callback()
282
+ })
266
283
  }, callback)
267
284
  } else {
268
285
  callback()
269
286
  }
270
287
  }
271
288
 
272
- const processComponent = (component, name, context, callback) => {
273
- if (!isUrlRequest(component, projectRoot)) return callback()
274
-
275
- if (resolveMode === 'native') {
276
- component = loaderUtils.urlToRequest(component, projectRoot)
277
- }
278
-
279
- resolve(context, component, loaderContext, (err, resource) => {
280
- if (err) return callback(err)
281
- const { resourcePath, queryObj } = parseRequest(resource)
282
- const parsed = path.parse(resourcePath)
283
- const componentId = parsed.name + pathHash(resourcePath)
284
-
285
- buildInfo.packageName = 'main'
286
- buildInfo.componentsMap = buildInfo.componentsMap || {}
287
- buildInfo.componentsMap[resourcePath] = componentsMap[resourcePath] = componentId
288
-
289
- localComponentsMap[name] = {
290
- resource: addQuery(resource, { component: true, componentId }),
291
- async: queryObj.async
292
- }
293
- callback()
294
- })
295
- }
296
-
297
289
  const processGenerics = (generics, context, callback) => {
298
290
  if (generics) {
299
- async.forEachOf(generics, (generic, name, callback) => {
300
- if (generic.default) {
301
- processComponent(generic.default, `${name}default`, context, callback)
302
- } else {
303
- callback()
304
- }
305
- }, callback)
291
+ const genericsComponents = {}
292
+ Object.keys(generics).forEach((name) => {
293
+ const generic = generics[name]
294
+ if (generic.default) genericsComponents[`${name}default`] = generic.default
295
+ })
296
+ processComponents(genericsComponents, context, callback)
306
297
  } else {
307
298
  callback()
308
299
  }
@@ -310,6 +301,7 @@ module.exports = function (json, { mode, env, loaderContext, resolveMode, pagesM
310
301
 
311
302
  async.parallel([
312
303
  (callback) => {
304
+ // 添加首页标识
313
305
  if (jsonObj.pages && jsonObj.pages[0]) {
314
306
  if (typeof jsonObj.pages[0] !== 'string') {
315
307
  jsonObj.pages[0].src = addQuery(jsonObj.pages[0].src, { isFirst: true })
@@ -317,7 +309,7 @@ module.exports = function (json, { mode, env, loaderContext, resolveMode, pagesM
317
309
  jsonObj.pages[0] = addQuery(jsonObj.pages[0], { isFirst: true })
318
310
  }
319
311
  }
320
- processPages(jsonObj.pages, '', '', context, callback)
312
+ processPages(jsonObj.pages, context, '', callback)
321
313
  },
322
314
  (callback) => {
323
315
  processComponents(jsonObj.usingComponents, context, callback)