@mpxjs/webpack-plugin 2.10.6-beta.2 → 2.10.6-beta.3

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.
package/lib/index.js CHANGED
@@ -44,7 +44,6 @@ const FlagPluginDependency = require('./dependencies/FlagPluginDependency')
44
44
  const RemoveEntryDependency = require('./dependencies/RemoveEntryDependency')
45
45
  const RecordLoaderContentDependency = require('./dependencies/RecordLoaderContentDependency')
46
46
  const RecordRuntimeInfoDependency = require('./dependencies/RecordRuntimeInfoDependency')
47
- const WriteVfsDependency = require('./dependencies/WriteVfsDependency')
48
47
  const SplitChunksPlugin = require('webpack/lib/optimize/SplitChunksPlugin')
49
48
  const fixRelative = require('./utils/fix-relative')
50
49
  const parseRequest = require('./utils/parse-request')
@@ -73,6 +72,8 @@ const isEmptyObject = require('./utils/is-empty-object')
73
72
  const DynamicPlugin = require('./resolver/DynamicPlugin')
74
73
  const { isReact, isWeb } = require('./utils/env')
75
74
  const VirtualModulesPlugin = require('webpack-virtual-modules')
75
+ const RuntimeGlobals = require('webpack/lib/RuntimeGlobals')
76
+ const LoadAsyncChunkModule = require('./react/LoadAsyncChunkModule')
76
77
  require('./utils/check-core-version-match')
77
78
 
78
79
  const isProductionLikeMode = options => {
@@ -409,7 +410,7 @@ class MpxWebpackPlugin {
409
410
  let splitChunksOptions = null
410
411
  let splitChunksPlugin = null
411
412
  // 输出web ssr需要将optimization.splitChunks设置为false以关闭splitChunks
412
- if (optimization.splitChunks !== false && !isReact(this.options.mode)) {
413
+ if (optimization.splitChunks !== false) {
413
414
  splitChunksOptions = Object.assign({
414
415
  chunks: 'all',
415
416
  usedExports: optimization.usedExports === true,
@@ -607,6 +608,22 @@ class MpxWebpackPlugin {
607
608
  return mpx
608
609
  }
609
610
  })
611
+
612
+ if (isReact(this.options.mode)) {
613
+ compilation.hooks.runtimeRequirementInTree
614
+ .for(RuntimeGlobals.loadScript)
615
+ .tap({
616
+ stage: -1000,
617
+ name: 'LoadAsyncChunk'
618
+ }, (chunk, set) => {
619
+ compilation.addRuntimeModule(
620
+ chunk,
621
+ new LoadAsyncChunkModule(this.options.rnConfig && this.options.rnConfig.asyncChunk && this.options.rnConfig.asyncChunk.timeout)
622
+ )
623
+ return true
624
+ })
625
+ }
626
+
610
627
  compilation.dependencyFactories.set(ResolveDependency, new NullFactory())
611
628
  compilation.dependencyTemplates.set(ResolveDependency, new ResolveDependency.Template())
612
629
 
@@ -655,9 +672,6 @@ class MpxWebpackPlugin {
655
672
  compilation.dependencyFactories.set(RecordRuntimeInfoDependency, new NullFactory())
656
673
  compilation.dependencyTemplates.set(RecordRuntimeInfoDependency, new RecordRuntimeInfoDependency.Template())
657
674
 
658
- compilation.dependencyFactories.set(WriteVfsDependency, new NullFactory())
659
- compilation.dependencyTemplates.set(WriteVfsDependency, new WriteVfsDependency.Template())
660
-
661
675
  compilation.dependencyTemplates.set(ImportDependency, new ImportDependencyTemplate())
662
676
  })
663
677
 
@@ -681,8 +695,6 @@ class MpxWebpackPlugin {
681
695
  componentsMap: {
682
696
  main: {}
683
697
  },
684
- // 用于template模版获取父组件引用的自定义组件,目前仅输出web时下支持使用
685
- parentLocalComponentsMap: {},
686
698
  // 静态资源(图片,字体,独立样式)等,依照所属包进行记录
687
699
  staticResourcesMap: {
688
700
  main: {}
@@ -746,7 +758,7 @@ class MpxWebpackPlugin {
746
758
  removedChunks: [],
747
759
  forceProxyEventRules: this.options.forceProxyEventRules,
748
760
  // 若配置disableRequireAsync=true, 则全平台构建不支持异步分包
749
- supportRequireAsync: !this.options.disableRequireAsync && (this.options.mode === 'wx' || this.options.mode === 'ali' || this.options.mode === 'tt' || isWeb(this.options.mode)),
761
+ supportRequireAsync: !this.options.disableRequireAsync && (this.options.mode === 'wx' || this.options.mode === 'ali' || this.options.mode === 'tt' || isWeb(this.options.mode) || isReact(this.options.mode)),
750
762
  partialCompileRules: this.options.partialCompileRules,
751
763
  collectDynamicEntryInfo: ({ resource, packageName, filename, entryType, hasAsync }) => {
752
764
  const curInfo = mpx.dynamicEntryInfo[packageName] = mpx.dynamicEntryInfo[packageName] || {
@@ -1395,10 +1407,10 @@ class MpxWebpackPlugin {
1395
1407
  if (queryObj.root) request = addQuery(request, {}, false, ['root'])
1396
1408
  // wx、ali和web平台支持require.async,其余平台使用CommonJsAsyncDependency进行模拟抹平
1397
1409
  if (mpx.supportRequireAsync) {
1398
- if (isWeb(mpx.mode)) {
1410
+ if (isWeb(mpx.mode) || isReact(mpx.mode)) {
1399
1411
  const depBlock = new AsyncDependenciesBlock(
1400
1412
  {
1401
- name: tarRoot
1413
+ name: tarRoot + '/index'
1402
1414
  },
1403
1415
  expr.loc,
1404
1416
  request
@@ -9,7 +9,6 @@ module.exports = function getRulesRunner ({
9
9
  testKey,
10
10
  mainKey,
11
11
  waterfall,
12
- moduleId,
13
12
  warn,
14
13
  error
15
14
  }) {
@@ -24,14 +23,13 @@ module.exports = function getRulesRunner ({
24
23
  wx: require('./json/wx')
25
24
  }
26
25
  }
27
- const spec = specMap[type] && specMap[type][srcMode] && specMap[type][srcMode]({ warn, error, moduleId })
26
+ const spec = specMap[type] && specMap[type][srcMode] && specMap[type][srcMode]({ warn, error })
28
27
  if (spec && spec.supportedModes.indexOf(mode) > -1) {
29
28
  const normalizeTest = spec.normalizeTest
30
29
  const mainRules = mainKey ? spec[mainKey] : spec
31
30
  if (mainRules) {
32
31
  return function (input) {
33
- const a = runRules(mainRules, input, { mode, data, meta, testKey, waterfall, normalizeTest })
34
- return a
32
+ return runRules(mainRules, input, { mode, data, meta, testKey, waterfall, normalizeTest })
35
33
  }
36
34
  }
37
35
  }
@@ -45,7 +45,7 @@ const rootPortal = require('./root-portal')
45
45
  const stickyHeader = require('./sticky-header')
46
46
  const stickySection = require('./sticky-section')
47
47
 
48
- module.exports = function getComponentConfigs ({ warn, error, moduleId }) {
48
+ module.exports = function getComponentConfigs ({ warn, error }) {
49
49
  /**
50
50
  * universal print for detail component warn or error
51
51
  * @param {object} config
@@ -116,7 +116,7 @@ module.exports = function getComponentConfigs ({ warn, error, moduleId }) {
116
116
  map({ print }),
117
117
  canvas({ print }),
118
118
  wxs({ print }),
119
- template({ moduleId }),
119
+ template(),
120
120
  block(),
121
121
  icon(),
122
122
  webView({ print }),
@@ -1,13 +1,8 @@
1
1
  const TAG_NAME = 'template'
2
2
 
3
- module.exports = function ({ moduleId }) {
3
+ module.exports = function () {
4
4
  return {
5
5
  test: TAG_NAME,
6
- web (tag, { el }) {
7
- if (el.attrsMap[':is']) {
8
- return 'component'
9
- }
10
- },
11
6
  props: [
12
7
  {
13
8
  test: 'data',
@@ -16,26 +11,6 @@ module.exports = function ({ moduleId }) {
16
11
  name,
17
12
  value: `{${value}}`
18
13
  }
19
- },
20
- web ({ value }) {
21
- let bindValue = value
22
- if (moduleId) {
23
- const lastIndex = value.lastIndexOf('}}')
24
- bindValue = value ? value.slice(0, lastIndex) + `, _data_v_id: '${moduleId}'}}` : `{{ _data_v_id: '${moduleId}' }}`
25
- }
26
- return {
27
- name: 'v-bind',
28
- value: bindValue
29
- }
30
- }
31
- },
32
- {
33
- test: 'is',
34
- web ({ value }) {
35
- return {
36
- name: ':is',
37
- value: `'${value}'`
38
- }
39
14
  }
40
15
  }
41
16
  ]
@@ -3,11 +3,11 @@ const JSON5 = require('json5')
3
3
  const getComponentConfigs = require('./component-config')
4
4
  const normalizeComponentRules = require('../normalize-component-rules')
5
5
  const isValidIdentifierStr = require('../../../utils/is-valid-identifier-str')
6
- const { vbindMustache, parseMustacheWithContext, stringifyWithResolveComputed } = require('../../../template-compiler/compiler')
6
+ const { parseMustacheWithContext, stringifyWithResolveComputed } = require('../../../template-compiler/compiler')
7
7
  const normalize = require('../../../utils/normalize')
8
8
  const { dash2hump } = require('../../../utils/hump-dash')
9
9
 
10
- module.exports = function getSpec ({ warn, error, moduleId }) {
10
+ module.exports = function getSpec ({ warn, error }) {
11
11
  function getRnDirectiveEventHandle (mode) {
12
12
  return function ({ name, value }, { eventRules, el }) {
13
13
  const match = this.test.exec(name)
@@ -68,13 +68,6 @@ module.exports = function getSpec ({ warn, error, moduleId }) {
68
68
  postProps: [
69
69
  {
70
70
  web ({ name, value }) {
71
- if (name === 'v-bind') {
72
- const vbindValue = vbindMustache(value)
73
- return {
74
- name,
75
- value: vbindValue
76
- }
77
- }
78
71
  const parsed = parseMustacheWithContext(value)
79
72
  if (name.startsWith('data-')) {
80
73
  return {
@@ -574,6 +567,6 @@ module.exports = function getSpec ({ warn, error, moduleId }) {
574
567
  ]
575
568
  }
576
569
  }
577
- spec.rules = normalizeComponentRules(getComponentConfigs({ warn, error, moduleId }).concat({}), spec)
570
+ spec.rules = normalizeComponentRules(getComponentConfigs({ warn, error }).concat({}), spec)
578
571
  return spec
579
572
  }
@@ -0,0 +1,68 @@
1
+ const RuntimeGlobals = require('webpack/lib/RuntimeGlobals')
2
+ const Template = require('webpack/lib/Template')
3
+ const HelperRuntimeModule = require('webpack/lib/runtime/HelperRuntimeModule')
4
+
5
+ class LoadAsyncChunkRuntimeModule extends HelperRuntimeModule {
6
+ constructor (timeout) {
7
+ super('load async chunk')
8
+ this.timeout = timeout || 5000
9
+ }
10
+
11
+ generate () {
12
+ const { compilation } = this
13
+ const { runtimeTemplate } = compilation
14
+ const loadScriptFn = RuntimeGlobals.loadScript
15
+ return Template.asString([
16
+ 'var inProgress = {};',
17
+ `${loadScriptFn} = ${runtimeTemplate.basicFunction(
18
+ 'url, done, key, chunkId',
19
+ [
20
+ `var packageName = ${RuntimeGlobals.getChunkScriptFilename}(chunkId) || ''`,
21
+ 'packageName = packageName.split("/")[0]',
22
+ 'var config = {',
23
+ Template.indent([
24
+ 'url: url,',
25
+ 'package: packageName'
26
+ ]),
27
+ '}',
28
+ 'if(inProgress[url]) { inProgress[url].push(done); return; }',
29
+ 'inProgress[url] = [done];',
30
+ 'var callback = function (type, result) {',
31
+ Template.indent([
32
+ 'var event = {',
33
+ Template.indent([
34
+ 'type: type,',
35
+ 'target: {',
36
+ Template.indent(['src: url']),
37
+ '}'
38
+ ]),
39
+ '}'
40
+ ]),
41
+ Template.indent([
42
+ 'var doneFns = inProgress[url]',
43
+ 'clearTimeout(timeoutCallback)',
44
+ 'delete inProgress[url]',
45
+ `doneFns && doneFns.forEach(${runtimeTemplate.returningFunction(
46
+ 'fn(event)',
47
+ 'fn'
48
+ )})`
49
+ ]),
50
+ '}',
51
+ `var timeoutCallback = setTimeout(callback.bind(null, 'timeout'), ${this.timeout})`,
52
+ "var successCallback = callback.bind(null, 'load');",
53
+ "var failedCallback = callback.bind(null, 'fail')",
54
+ 'var loadChunkAsyncFn = global.__mpx.config.rnConfig && global.__mpx.config.rnConfig.loadChunkAsync',
55
+ 'if (typeof loadChunkAsyncFn !== \'function\') {',
56
+ Template.indent([
57
+ 'console.error("[Mpx runtime error]: please provide correct loadChunkAsync function")',
58
+ 'return'
59
+ ]),
60
+ '}',
61
+ 'loadChunkAsyncFn(config).then(successCallback).catch(failedCallback)'
62
+ ]
63
+ )}`
64
+ ])
65
+ }
66
+ }
67
+
68
+ module.exports = LoadAsyncChunkRuntimeModule
@@ -35,6 +35,7 @@ module.exports = function ({
35
35
  })
36
36
  }
37
37
  const mpx = loaderContext.getMpx()
38
+ const rnConfig = mpx.rnConfig
38
39
  // 通过RecordLoaderContentDependency和loaderContentCache确保子request不再重复生成loaderContent
39
40
  const cacheContent = mpx.loaderContentCache.get(loaderContext.resourcePath)
40
41
  if (cacheContent) return callback(null, cacheContent)
@@ -91,7 +92,8 @@ module.exports = function ({
91
92
  genericsInfo: templateRes.genericsInfo,
92
93
  wxsModuleMap: templateRes.wxsModuleMap,
93
94
  localComponentsMap: jsonRes.localComponentsMap,
94
- localPagesMap: jsonRes.localPagesMap
95
+ localPagesMap: jsonRes.localPagesMap,
96
+ rnConfig
95
97
  }, callback)
96
98
  }
97
99
  ], (err, scriptRes) => {
@@ -113,14 +113,14 @@ module.exports = function (jsonContent, {
113
113
  }
114
114
 
115
115
  if (ctorType === 'page') {
116
- // const keysToExtract = ['navigationStyle']
116
+ const keysToExtract = ['navigationStyle', 'navigationBarTitleText', 'navigationBarTextStyle', 'navigationBarBackgroundColor']
117
117
  const configObj = {}
118
118
  // 暂时先不注入数据,后续如需要使用再用
119
- // keysToExtract.forEach(key => {
120
- // if (jsonObj[key]) {
121
- // configObj[key] = jsonObj[key]
122
- // }
123
- // })
119
+ keysToExtract.forEach(key => {
120
+ if (jsonObj[key]) {
121
+ configObj[key] = jsonObj[key]
122
+ }
123
+ })
124
124
  loaderContext._module.addPresentationalDependency(new RecordPageConfigsMapDependency(parseRequest(loaderContext.resource).resourcePath, configObj))
125
125
  }
126
126
 
@@ -13,6 +13,7 @@ module.exports = function (script, {
13
13
  builtInComponentsMap,
14
14
  localComponentsMap,
15
15
  localPagesMap,
16
+ rnConfig,
16
17
  componentGenerics,
17
18
  genericsInfo
18
19
  }, callback) {
@@ -32,6 +33,7 @@ module.exports = function (script, {
32
33
  }
33
34
 
34
35
  let output = '/* script */\n'
36
+ output += "import { lazy, createElement, memo, forwardRef } from 'react'\n"
35
37
  if (ctorType === 'app') {
36
38
  output += `
37
39
  import { getComponent } from ${stringifyRequest(loaderContext, optionProcessorPath)}
@@ -39,7 +41,8 @@ import { getComponent } from ${stringifyRequest(loaderContext, optionProcessorPa
39
41
  const { pagesMap, firstPage } = buildPagesMap({
40
42
  localPagesMap,
41
43
  loaderContext,
42
- jsonConfig
44
+ jsonConfig,
45
+ rnConfig
43
46
  })
44
47
  const componentsMap = buildComponentsMap({
45
48
  localComponentsMap,
@@ -50,8 +53,6 @@ import { getComponent } from ${stringifyRequest(loaderContext, optionProcessorPa
50
53
  output += getRequireScript({ ctorType, script, loaderContext })
51
54
  output += `export default global.__mpxOptionsMap[${JSON.stringify(moduleId)}]\n`
52
55
  } else {
53
- // RN环境暂不支持异步加载
54
- // output += 'import { lazy } from \'react\'\n'
55
56
  output += `import { getComponent } from ${stringifyRequest(loaderContext, optionProcessorPath)}\n`
56
57
  // 获取组件集合
57
58
  const componentsMap = buildComponentsMap({
@@ -3,30 +3,80 @@ const createHelpers = require('../helpers')
3
3
  const parseRequest = require('../utils/parse-request')
4
4
  const shallowStringify = require('../utils/shallow-stringify')
5
5
  const normalize = require('../utils/normalize')
6
+ const addQuery = require('../utils/add-query')
7
+ const path = require('path')
8
+ const { isBuildInReactTag } = require('../utils/dom-tag-config')
6
9
 
7
10
  function stringifyRequest (loaderContext, request) {
8
11
  return loaderUtils.stringifyRequest(loaderContext, request)
9
12
  }
10
13
 
11
- // function getAsyncChunkName (chunkName) {
12
- // if (chunkName && typeof chunkName !== 'boolean') {
13
- // return `/* webpackChunkName: "${chunkName}" */`
14
- // }
15
- // return ''
16
- // }
14
+ function getMpxComponentRequest (component) {
15
+ return JSON.stringify(addQuery(`@mpxjs/webpack-plugin/lib/runtime/components/react/dist/${component}`, { isComponent: true }))
16
+ }
17
+
18
+ const mpxAsyncContainer = getMpxComponentRequest('AsyncContainer')
19
+
20
+ function getAsyncChunkName (chunkName) {
21
+ if (chunkName && typeof chunkName !== 'boolean') {
22
+ return `/* webpackChunkName: "${chunkName}/index" */`
23
+ }
24
+ return ''
25
+ }
17
26
 
18
- function buildPagesMap ({ localPagesMap, loaderContext, jsonConfig }) {
27
+ function getAsyncComponent (componentName, componentRequest, chunkName, fallback) {
28
+ return `getComponent(memo(forwardRef(function(props, ref) {
29
+ return createElement(
30
+ getComponent(require(${mpxAsyncContainer})),
31
+ {
32
+ type: 'component',
33
+ props: Object.assign({}, props, { ref }),
34
+ loading: getComponent(require(${fallback})),
35
+ children: (props) => createElement(
36
+ getComponent(
37
+ lazy(function(){ return import(${getAsyncChunkName(chunkName)}${componentRequest}) }), { displayName: ${JSON.stringify(componentName)} }
38
+ ),
39
+ props
40
+ )
41
+ }
42
+ )
43
+ })))`
44
+ }
45
+
46
+ function getAsyncPage (componentName, componentRequest, chunkName, fallback, loading) {
47
+ fallback = fallback && `getComponent(require('${fallback}?isComponent=true'))`
48
+ loading = loading && `getComponent(require('${loading}?isComponent=true'))`
49
+ return `getComponent(function(props) {
50
+ return createElement(
51
+ getComponent(require(${mpxAsyncContainer})),
52
+ {
53
+ type: 'page',
54
+ props: props,
55
+ fallback: ${fallback},
56
+ loading: ${loading},
57
+ children: (props) => createElement(
58
+ getComponent(
59
+ lazy(function(){ return import(${getAsyncChunkName(chunkName)}${componentRequest}) }), { __mpxPageRoute: ${JSON.stringify(componentName)}, displayName: 'Page' }
60
+ ),
61
+ props
62
+ )
63
+ }
64
+ )
65
+ })`
66
+ }
67
+
68
+ function buildPagesMap ({ localPagesMap, loaderContext, jsonConfig, rnConfig }) {
19
69
  let firstPage = ''
20
70
  const pagesMap = {}
21
71
  Object.keys(localPagesMap).forEach((pagePath) => {
22
72
  const pageCfg = localPagesMap[pagePath]
23
73
  const pageRequest = stringifyRequest(loaderContext, pageCfg.resource)
24
- // if (pageCfg.async) {
25
- // pagesMap[pagePath] = `lazy(function(){return import(${getAsyncChunkName(pageCfg.async)} ${pageRequest}).then(function(res){return getComponent(res, {__mpxPageRoute: ${JSON.stringify(pagePath)}, displayName: "Page"})})})`
26
- // } else {
74
+ if (pageCfg.async) {
75
+ pagesMap[pagePath] = getAsyncPage(pagePath, pageRequest, pageCfg.async, rnConfig.asyncChunk && rnConfig.asyncChunk.fallback, rnConfig.asyncChunk && rnConfig.asyncChunk.loading)
76
+ } else {
27
77
  // 为了保持小程序中app->page->component的js执行顺序,所有的page和component都改为require引入
28
- pagesMap[pagePath] = `getComponent(require(${pageRequest}), {__mpxPageRoute: ${JSON.stringify(pagePath)}, displayName: "Page"})`
29
- // }
78
+ pagesMap[pagePath] = `getComponent(require(${pageRequest}), {__mpxPageRoute: ${JSON.stringify(pagePath)}, displayName: "Page"})`
79
+ }
30
80
  if (pagePath === jsonConfig.entryPagePath) {
31
81
  firstPage = pagePath
32
82
  }
@@ -42,16 +92,44 @@ function buildPagesMap ({ localPagesMap, loaderContext, jsonConfig }) {
42
92
 
43
93
  function buildComponentsMap ({ localComponentsMap, builtInComponentsMap, loaderContext, jsonConfig }) {
44
94
  const componentsMap = {}
95
+ const mpx = loaderContext.getMpx()
45
96
  if (localComponentsMap) {
46
97
  Object.keys(localComponentsMap).forEach((componentName) => {
47
98
  const componentCfg = localComponentsMap[componentName]
48
99
  const componentRequest = stringifyRequest(loaderContext, componentCfg.resource)
49
- // RN中暂不支持异步加载
50
- // if (componentCfg.async) {
51
- // componentsMap[componentName] = `lazy(function(){return import(${getAsyncChunkName(componentCfg.async)}${componentRequest}).then(function(res){return getComponent(res, {displayName: ${JSON.stringify(componentName)}})})})`
52
- // } else {
53
- componentsMap[componentName] = `getComponent(require(${componentRequest}), {displayName: ${JSON.stringify(componentName)}})`
54
- // }
100
+ if (componentCfg.async) {
101
+ const placeholder = jsonConfig.componentPlaceholder && jsonConfig.componentPlaceholder[componentName]
102
+ if (placeholder) {
103
+ if (localComponentsMap[placeholder]) {
104
+ const placeholderCfg = localComponentsMap[placeholder]
105
+ const placeholderRequest = stringifyRequest(loaderContext, placeholderCfg.resource)
106
+ if (placeholderCfg.async) {
107
+ loaderContext.emitWarning(
108
+ new Error(`[json processor][${loaderContext.resource}]: componentPlaceholder ${placeholder} should not be a async component, please check!`)
109
+ )
110
+ }
111
+ componentsMap[componentName] = getAsyncComponent(componentName, componentRequest, componentCfg.async, placeholderRequest)
112
+ } else if (mpx.globalComponents[placeholder]) {
113
+ const { queryObj, rawResourcePath } = parseRequest(mpx.globalComponents[placeholder])
114
+ const placeholderRequest = JSON.stringify(path.resolve(queryObj.context, rawResourcePath))
115
+ componentsMap[componentName] = getAsyncComponent(componentName, componentRequest, componentCfg.async, placeholderRequest)
116
+ } else {
117
+ if (!isBuildInReactTag(placeholder)) {
118
+ loaderContext.emitError(
119
+ new Error(`[json processor][${loaderContext.resource}]: componentPlaceholder ${placeholder} is not built-in component, please check!`)
120
+ )
121
+ }
122
+ componentsMap[componentName] = getAsyncComponent(componentName, componentRequest, componentCfg.async, getMpxComponentRequest(`mpx-${placeholder}`))
123
+ }
124
+ } else {
125
+ loaderContext.emitError(
126
+ new Error(`[json processor][${loaderContext.resource}]: ${componentName} has no componentPlaceholder, please check!`)
127
+ )
128
+ componentsMap[componentName] = getAsyncComponent(componentName, componentRequest, componentCfg.async)
129
+ }
130
+ } else {
131
+ componentsMap[componentName] = `getComponent(require(${componentRequest}), {displayName: ${JSON.stringify(componentName)}})`
132
+ }
55
133
  })
56
134
  }
57
135
  if (builtInComponentsMap) {
@@ -107,6 +185,7 @@ global.__mpxPageConfig = ${JSON.stringify(jsonConfig.window)}
107
185
  global.__getAppComponents = function () {
108
186
  return ${shallowStringify(componentsMap)}
109
187
  }
188
+ global.__preloadRule = ${JSON.stringify(jsonConfig.preloadRule)}
110
189
  global.currentInject.getPages = function () {
111
190
  return ${shallowStringify(pagesMap)}
112
191
  }