@mpxjs/webpack-plugin 2.10.6-beta.3 → 2.10.6-beta.4
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/file-loader.js +1 -1
- package/lib/index.js +13 -4
- package/lib/platform/json/wx/index.js +43 -25
- package/lib/platform/template/wx/component-config/fix-component-name.js +2 -2
- package/lib/platform/template/wx/index.js +2 -1
- package/lib/react/processJSON.js +66 -11
- package/lib/react/script-helper.js +12 -17
- package/lib/runtime/components/react/AsyncContainer.tsx +35 -7
- package/lib/runtime/components/react/AsyncSuspense.tsx +81 -0
- package/lib/runtime/components/react/dist/AsyncContainer.jsx +160 -0
- package/lib/runtime/components/react/dist/AsyncSuspense.jsx +68 -0
- package/lib/runtime/components/react/dist/getInnerListeners.js +1 -1
- package/lib/runtime/components/react/dist/mpx-input.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +53 -27
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +14 -28
- package/lib/runtime/components/react/dist/useAnimationHooks.js +2 -87
- package/lib/runtime/components/react/dist/utils.jsx +84 -0
- package/lib/runtime/components/react/mpx-swiper.tsx +0 -7
- package/lib/runtime/components/react/useAnimationHooks.ts +2 -85
- package/lib/runtime/components/react/utils.tsx +83 -1
- package/lib/template-compiler/compiler.js +2 -2
- package/lib/utils/dom-tag-config.js +2 -2
- package/package.json +1 -1
package/lib/file-loader.js
CHANGED
|
@@ -36,7 +36,7 @@ module.exports = function loader (content, prevOptions) {
|
|
|
36
36
|
let publicPath = `__webpack_public_path__ + ${JSON.stringify(url)}`
|
|
37
37
|
|
|
38
38
|
// todo 未来添加分包处理后相对地址不一定是./开头的,需要考虑通过dependency的方式在sourceModule时通过最终的chunkName得到准确的相对路径
|
|
39
|
-
if (isRN) publicPath = `__non_webpack_require__(${JSON.stringify(
|
|
39
|
+
if (isRN) publicPath = `__non_webpack_require__(${JSON.stringify(`_mpx_rn_img_relative_path_/${url}`)})`
|
|
40
40
|
|
|
41
41
|
if (options.publicPath) {
|
|
42
42
|
if (typeof options.publicPath === 'function') {
|
package/lib/index.js
CHANGED
|
@@ -1217,12 +1217,12 @@ class MpxWebpackPlugin {
|
|
|
1217
1217
|
// 自动使用分包配置修改splitChunksPlugin配置
|
|
1218
1218
|
if (splitChunksPlugin) {
|
|
1219
1219
|
let needInit = false
|
|
1220
|
-
if (isWeb(mpx.mode)) {
|
|
1220
|
+
if (isWeb(mpx.mode) || isReact(mpx.mode)) {
|
|
1221
1221
|
// web独立处理splitChunk
|
|
1222
|
-
if (!hasOwn(splitChunksOptions.cacheGroups, 'main')) {
|
|
1222
|
+
if (isWeb(mpx.mode) && !hasOwn(splitChunksOptions.cacheGroups, 'main')) {
|
|
1223
1223
|
splitChunksOptions.cacheGroups.main = {
|
|
1224
1224
|
chunks: 'initial',
|
|
1225
|
-
name: 'bundle',
|
|
1225
|
+
name: 'bundle/index', // web 输出 chunk 路径和 rn 输出分包格式拉齐
|
|
1226
1226
|
test: /[\\/]node_modules[\\/]/
|
|
1227
1227
|
}
|
|
1228
1228
|
needInit = true
|
|
@@ -1230,7 +1230,7 @@ class MpxWebpackPlugin {
|
|
|
1230
1230
|
if (!hasOwn(splitChunksOptions.cacheGroups, 'async')) {
|
|
1231
1231
|
splitChunksOptions.cacheGroups.async = {
|
|
1232
1232
|
chunks: 'async',
|
|
1233
|
-
name: 'async',
|
|
1233
|
+
name: 'async/index',
|
|
1234
1234
|
minChunks: 2
|
|
1235
1235
|
}
|
|
1236
1236
|
needInit = true
|
|
@@ -1333,6 +1333,15 @@ class MpxWebpackPlugin {
|
|
|
1333
1333
|
compilation.hooks.processAssets.tap({
|
|
1334
1334
|
name: 'MpxWebpackPlugin'
|
|
1335
1335
|
}, (assets) => {
|
|
1336
|
+
if (isReact(mpx.mode)) {
|
|
1337
|
+
Object.keys(assets).forEach((chunkName) => {
|
|
1338
|
+
if (/\.js$/.test(chunkName)) {
|
|
1339
|
+
let val = assets[chunkName].source()
|
|
1340
|
+
val = val.replace(/_mpx_rn_img_relative_path_/g, chunkName === 'app.js' ? '.' : '..')
|
|
1341
|
+
compilation.assets[chunkName] = new RawSource(val)
|
|
1342
|
+
}
|
|
1343
|
+
})
|
|
1344
|
+
}
|
|
1336
1345
|
try {
|
|
1337
1346
|
const dynamicAssets = {}
|
|
1338
1347
|
for (const packageName in mpx.runtimeInfo) {
|
|
@@ -3,7 +3,7 @@ const normalizeTest = require('../normalize-test')
|
|
|
3
3
|
const changeKey = require('../change-key')
|
|
4
4
|
const normalize = require('../../../utils/normalize')
|
|
5
5
|
const { capitalToHyphen } = require('../../../utils/string')
|
|
6
|
-
const { isOriginTag,
|
|
6
|
+
const { isOriginTag, isBuildInWebTag, isBuildInReactTag } = require('../../../utils/dom-tag-config')
|
|
7
7
|
|
|
8
8
|
const mpxViewPath = normalize.lib('runtime/components/ali/mpx-view.mpx')
|
|
9
9
|
const mpxTextPath = normalize.lib('runtime/components/ali/mpx-text.mpx')
|
|
@@ -128,19 +128,41 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
128
128
|
/**
|
|
129
129
|
* 将小程序代码中使用的与原生 HTML tag 或 内建组件 同名的组件进行转化,以解决与原生tag命名冲突问题。
|
|
130
130
|
*/
|
|
131
|
-
function fixComponentName (
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
131
|
+
function fixComponentName (input, { mode }) {
|
|
132
|
+
const isNeedFixTag = (tag) => {
|
|
133
|
+
switch (mode) {
|
|
134
|
+
case 'web': return isOriginTag(tag) || isBuildInWebTag(tag)
|
|
135
|
+
case 'ios':
|
|
136
|
+
case 'android':
|
|
137
|
+
case 'harmony': return isOriginTag(tag) || isBuildInReactTag(tag)
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const usingComponents = input.usingComponents
|
|
142
|
+
const componentPlaceholder = input.componentPlaceholder
|
|
143
|
+
if (usingComponents) {
|
|
144
|
+
const transfromKeys = []
|
|
145
|
+
Object.keys(usingComponents).forEach(tag => {
|
|
146
|
+
if (isNeedFixTag(tag)) {
|
|
147
|
+
usingComponents[`mpx-com-${tag}`] = usingComponents[tag]
|
|
148
|
+
delete usingComponents[tag]
|
|
149
|
+
transfromKeys.push(tag)
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
if (transfromKeys.length && componentPlaceholder) {
|
|
154
|
+
Object.keys(componentPlaceholder).forEach(key => {
|
|
155
|
+
if (transfromKeys.includes(componentPlaceholder[key])) {
|
|
156
|
+
componentPlaceholder[key] = `mpx-com-${componentPlaceholder[key]}`
|
|
157
|
+
}
|
|
158
|
+
if (transfromKeys.includes(key)) {
|
|
159
|
+
componentPlaceholder[`mpx-com-${key}`] = componentPlaceholder[key]
|
|
160
|
+
delete componentPlaceholder[key]
|
|
139
161
|
}
|
|
140
162
|
})
|
|
141
163
|
}
|
|
142
|
-
return input
|
|
143
164
|
}
|
|
165
|
+
return input
|
|
144
166
|
}
|
|
145
167
|
|
|
146
168
|
const componentRules = [
|
|
@@ -154,13 +176,6 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
154
176
|
swan: deletePath(),
|
|
155
177
|
jd: deletePath()
|
|
156
178
|
},
|
|
157
|
-
{
|
|
158
|
-
test: 'usingComponents',
|
|
159
|
-
web: fixComponentName('usingComponents'),
|
|
160
|
-
ios: fixComponentName('usingComponents'),
|
|
161
|
-
android: fixComponentName('usingComponents'),
|
|
162
|
-
harmony: fixComponentName('usingComponents')
|
|
163
|
-
},
|
|
164
179
|
{
|
|
165
180
|
test: 'usingComponents',
|
|
166
181
|
ali: componentNameCapitalToHyphen('usingComponents'),
|
|
@@ -170,7 +185,11 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
170
185
|
swan: addGlobalComponents,
|
|
171
186
|
qq: addGlobalComponents,
|
|
172
187
|
tt: addGlobalComponents,
|
|
173
|
-
jd: addGlobalComponents
|
|
188
|
+
jd: addGlobalComponents,
|
|
189
|
+
web: fixComponentName,
|
|
190
|
+
ios: fixComponentName,
|
|
191
|
+
android: fixComponentName,
|
|
192
|
+
harmony: fixComponentName
|
|
174
193
|
}
|
|
175
194
|
]
|
|
176
195
|
|
|
@@ -371,13 +390,6 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
371
390
|
tt: deletePath(),
|
|
372
391
|
jd: deletePath(true)
|
|
373
392
|
},
|
|
374
|
-
{
|
|
375
|
-
test: 'usingComponents',
|
|
376
|
-
web: fixComponentName('usingComponents'),
|
|
377
|
-
ios: fixComponentName('usingComponents'),
|
|
378
|
-
android: fixComponentName('usingComponents'),
|
|
379
|
-
harmony: fixComponentName('usingComponents')
|
|
380
|
-
},
|
|
381
393
|
{
|
|
382
394
|
test: 'usingComponents',
|
|
383
395
|
ali: componentNameCapitalToHyphen('usingComponents'),
|
|
@@ -442,6 +454,12 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
442
454
|
swan: getWindowRule(),
|
|
443
455
|
tt: getWindowRule(),
|
|
444
456
|
jd: getWindowRule()
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
web: fixComponentName,
|
|
460
|
+
ios: fixComponentName,
|
|
461
|
+
android: fixComponentName,
|
|
462
|
+
harmony: fixComponentName
|
|
445
463
|
}
|
|
446
464
|
]
|
|
447
465
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { isOriginTag,
|
|
1
|
+
const { isOriginTag, isBuildInWebTag } = require('../../../../utils/dom-tag-config')
|
|
2
2
|
|
|
3
3
|
module.exports = function () {
|
|
4
4
|
const handleComponentTag = (el, data) => {
|
|
@@ -16,7 +16,7 @@ module.exports = function () {
|
|
|
16
16
|
waterfall: true,
|
|
17
17
|
skipNormalize: true,
|
|
18
18
|
supportedModes: ['web', 'ios', 'android', 'harmony'],
|
|
19
|
-
test: (input) => isOriginTag(input) ||
|
|
19
|
+
test: (input) => isOriginTag(input) || isBuildInWebTag(input),
|
|
20
20
|
web: handleComponentTag,
|
|
21
21
|
ios: handleComponentTag,
|
|
22
22
|
android: handleComponentTag,
|
|
@@ -34,7 +34,8 @@ module.exports = function getSpec ({ warn, error }) {
|
|
|
34
34
|
touchstart: 'touchstart',
|
|
35
35
|
touchmove: 'touchmove',
|
|
36
36
|
touchend: 'touchend',
|
|
37
|
-
touchcancel: 'touchcancel'
|
|
37
|
+
touchcancel: 'touchcancel',
|
|
38
|
+
transitionend: 'transitionend'
|
|
38
39
|
}
|
|
39
40
|
if (eventMap[eventName]) {
|
|
40
41
|
return eventMap[eventName]
|
package/lib/react/processJSON.js
CHANGED
|
@@ -11,8 +11,11 @@ const resolve = require('../utils/resolve')
|
|
|
11
11
|
const createJSONHelper = require('../json-compiler/helper')
|
|
12
12
|
const getRulesRunner = require('../platform/index')
|
|
13
13
|
const { RESOLVE_IGNORED_ERR } = require('../utils/const')
|
|
14
|
+
const normalize = require('../utils/normalize')
|
|
14
15
|
const RecordResourceMapDependency = require('../dependencies/RecordResourceMapDependency')
|
|
15
16
|
const RecordPageConfigsMapDependency = require('../dependencies/RecordPageConfigsMapDependency')
|
|
17
|
+
const mpxViewPath = normalize.lib('runtime/components/react/dist/mpx-view.jsx')
|
|
18
|
+
const mpxTextPath = normalize.lib('runtime/components/react/dist/mpx-text.jsx')
|
|
16
19
|
|
|
17
20
|
module.exports = function (jsonContent, {
|
|
18
21
|
loaderContext,
|
|
@@ -133,6 +136,29 @@ module.exports = function (jsonContent, {
|
|
|
133
136
|
isShow: true
|
|
134
137
|
}
|
|
135
138
|
|
|
139
|
+
const fillInComponentPlaceholder = (name, placeholder, placeholderEntry) => {
|
|
140
|
+
const componentPlaceholder = jsonObj.componentPlaceholder || {}
|
|
141
|
+
if (componentPlaceholder[name]) return
|
|
142
|
+
componentPlaceholder[name] = placeholder
|
|
143
|
+
jsonObj.componentPlaceholder = componentPlaceholder
|
|
144
|
+
if (placeholderEntry && !jsonObj.usingComponents[placeholder]) jsonObj.usingComponents[placeholder] = placeholderEntry
|
|
145
|
+
}
|
|
146
|
+
const normalizePlaceholder = (placeholder) => {
|
|
147
|
+
if (typeof placeholder === 'string') {
|
|
148
|
+
const placeholderMap = mode === 'ali'
|
|
149
|
+
? {
|
|
150
|
+
view: { name: 'mpx-view', resource: mpxViewPath },
|
|
151
|
+
text: { name: 'mpx-text', resource: mpxTextPath }
|
|
152
|
+
}
|
|
153
|
+
: {}
|
|
154
|
+
placeholder = placeholderMap[placeholder] || { name: placeholder }
|
|
155
|
+
}
|
|
156
|
+
if (!placeholder.name) {
|
|
157
|
+
emitError('The asyncSubpackageRules configuration format of @mpxjs/webpack-plugin a is incorrect')
|
|
158
|
+
}
|
|
159
|
+
return placeholder
|
|
160
|
+
}
|
|
161
|
+
|
|
136
162
|
const processTabBar = (tabBar, callback) => {
|
|
137
163
|
if (tabBar) {
|
|
138
164
|
tabBar = Object.assign({}, defaultTabbar, tabBar)
|
|
@@ -301,19 +327,48 @@ module.exports = function (jsonContent, {
|
|
|
301
327
|
const processComponents = (components, context, callback) => {
|
|
302
328
|
if (components) {
|
|
303
329
|
async.eachOf(components, (component, name, callback) => {
|
|
304
|
-
processComponent(component, context, {}, (err,
|
|
330
|
+
processComponent(component, context, {}, (err, entry = {}, { tarRoot, placeholder } = {}) => {
|
|
305
331
|
if (err) return callback(err === RESOLVE_IGNORED_ERR ? null : err)
|
|
306
|
-
const
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
332
|
+
const fillComponentsMap = (name, entry, tarRoot) => {
|
|
333
|
+
const { resource, outputPath } = entry
|
|
334
|
+
const { resourcePath, queryObj } = parseRequest(resource)
|
|
335
|
+
componentsMap[resourcePath] = outputPath
|
|
336
|
+
loaderContext._module && loaderContext._module.addPresentationalDependency(new RecordResourceMapDependency(resourcePath, 'component', outputPath))
|
|
337
|
+
localComponentsMap[name] = {
|
|
338
|
+
resource: addQuery(resource, {
|
|
339
|
+
isComponent: true,
|
|
340
|
+
outputPath
|
|
341
|
+
}),
|
|
342
|
+
async: queryObj.async || tarRoot
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
fillComponentsMap(name, entry, tarRoot)
|
|
346
|
+
const { relativePath } = entry
|
|
347
|
+
|
|
348
|
+
if (tarRoot) {
|
|
349
|
+
if (placeholder) {
|
|
350
|
+
placeholder = normalizePlaceholder(placeholder)
|
|
351
|
+
if (placeholder.resource) {
|
|
352
|
+
processComponent(placeholder.resource, projectRoot, { relativePath }, (err, entry) => {
|
|
353
|
+
if (err) return callback(err)
|
|
354
|
+
fillInComponentPlaceholder(name, placeholder.name, entry)
|
|
355
|
+
fillComponentsMap(placeholder.name, entry, '')
|
|
356
|
+
callback()
|
|
357
|
+
})
|
|
358
|
+
} else {
|
|
359
|
+
fillInComponentPlaceholder(name, placeholder.name)
|
|
360
|
+
callback()
|
|
361
|
+
}
|
|
362
|
+
} else {
|
|
363
|
+
if (!jsonObj.componentPlaceholder || !jsonObj.componentPlaceholder[name]) {
|
|
364
|
+
const errMsg = `componentPlaceholder of "${name}" doesn't exist! \n\r`
|
|
365
|
+
emitError(errMsg)
|
|
366
|
+
}
|
|
367
|
+
callback()
|
|
368
|
+
}
|
|
369
|
+
} else {
|
|
370
|
+
callback()
|
|
315
371
|
}
|
|
316
|
-
callback()
|
|
317
372
|
})
|
|
318
373
|
}, callback)
|
|
319
374
|
} else {
|
|
@@ -15,7 +15,7 @@ function getMpxComponentRequest (component) {
|
|
|
15
15
|
return JSON.stringify(addQuery(`@mpxjs/webpack-plugin/lib/runtime/components/react/dist/${component}`, { isComponent: true }))
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
const
|
|
18
|
+
const mpxAsyncSuspense = getMpxComponentRequest('AsyncSuspense')
|
|
19
19
|
|
|
20
20
|
function getAsyncChunkName (chunkName) {
|
|
21
21
|
if (chunkName && typeof chunkName !== 'boolean') {
|
|
@@ -27,17 +27,14 @@ function getAsyncChunkName (chunkName) {
|
|
|
27
27
|
function getAsyncComponent (componentName, componentRequest, chunkName, fallback) {
|
|
28
28
|
return `getComponent(memo(forwardRef(function(props, ref) {
|
|
29
29
|
return createElement(
|
|
30
|
-
getComponent(require(${
|
|
30
|
+
getComponent(require(${mpxAsyncSuspense})),
|
|
31
31
|
{
|
|
32
32
|
type: 'component',
|
|
33
33
|
props: Object.assign({}, props, { ref }),
|
|
34
|
+
chunkName: ${JSON.stringify(chunkName)},
|
|
35
|
+
request: ${JSON.stringify(componentRequest)},
|
|
34
36
|
loading: getComponent(require(${fallback})),
|
|
35
|
-
|
|
36
|
-
getComponent(
|
|
37
|
-
lazy(function(){ return import(${getAsyncChunkName(chunkName)}${componentRequest}) }), { displayName: ${JSON.stringify(componentName)} }
|
|
38
|
-
),
|
|
39
|
-
props
|
|
40
|
-
)
|
|
37
|
+
getChildren: () => import(${getAsyncChunkName(chunkName)}${componentRequest})
|
|
41
38
|
}
|
|
42
39
|
)
|
|
43
40
|
})))`
|
|
@@ -48,18 +45,15 @@ function getAsyncPage (componentName, componentRequest, chunkName, fallback, loa
|
|
|
48
45
|
loading = loading && `getComponent(require('${loading}?isComponent=true'))`
|
|
49
46
|
return `getComponent(function(props) {
|
|
50
47
|
return createElement(
|
|
51
|
-
getComponent(require(${
|
|
48
|
+
getComponent(require(${mpxAsyncSuspense})),
|
|
52
49
|
{
|
|
53
50
|
type: 'page',
|
|
54
51
|
props: props,
|
|
52
|
+
chunkName: ${JSON.stringify(chunkName)},
|
|
53
|
+
request: ${JSON.stringify(componentRequest)},
|
|
55
54
|
fallback: ${fallback},
|
|
56
55
|
loading: ${loading},
|
|
57
|
-
|
|
58
|
-
getComponent(
|
|
59
|
-
lazy(function(){ return import(${getAsyncChunkName(chunkName)}${componentRequest}) }), { __mpxPageRoute: ${JSON.stringify(componentName)}, displayName: 'Page' }
|
|
60
|
-
),
|
|
61
|
-
props
|
|
62
|
-
)
|
|
56
|
+
getChildren: () => import(${getAsyncChunkName(chunkName)}${componentRequest})
|
|
63
57
|
}
|
|
64
58
|
)
|
|
65
59
|
})`
|
|
@@ -114,12 +108,13 @@ function buildComponentsMap ({ localComponentsMap, builtInComponentsMap, loaderC
|
|
|
114
108
|
const placeholderRequest = JSON.stringify(path.resolve(queryObj.context, rawResourcePath))
|
|
115
109
|
componentsMap[componentName] = getAsyncComponent(componentName, componentRequest, componentCfg.async, placeholderRequest)
|
|
116
110
|
} else {
|
|
117
|
-
|
|
111
|
+
const tag = `mpx-${placeholder}`
|
|
112
|
+
if (!isBuildInReactTag(tag)) {
|
|
118
113
|
loaderContext.emitError(
|
|
119
114
|
new Error(`[json processor][${loaderContext.resource}]: componentPlaceholder ${placeholder} is not built-in component, please check!`)
|
|
120
115
|
)
|
|
121
116
|
}
|
|
122
|
-
componentsMap[componentName] = getAsyncComponent(componentName, componentRequest, componentCfg.async, getMpxComponentRequest(
|
|
117
|
+
componentsMap[componentName] = getAsyncComponent(componentName, componentRequest, componentCfg.async, getMpxComponentRequest(tag))
|
|
123
118
|
}
|
|
124
119
|
} else {
|
|
125
120
|
loaderContext.emitError(
|
|
@@ -1,6 +1,29 @@
|
|
|
1
|
-
import { ComponentType, ReactNode, Component,
|
|
1
|
+
import { ComponentType, ReactNode, Component, Suspense } from 'react'
|
|
2
2
|
import { View, Text, Image, StyleSheet, TouchableOpacity } from 'react-native'
|
|
3
3
|
import FastImage from '@d11/react-native-fast-image'
|
|
4
|
+
import Animated, { useAnimatedStyle } from 'react-native-reanimated'
|
|
5
|
+
|
|
6
|
+
type PageWrapper = {
|
|
7
|
+
children: ReactNode
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const PageWrapper = ({ children }: PageWrapper) => {
|
|
11
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
12
|
+
transform: [{ translateY: -0 }],
|
|
13
|
+
flexBasis: 'auto',
|
|
14
|
+
flex: 1
|
|
15
|
+
}))
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Animated.View
|
|
19
|
+
style={[
|
|
20
|
+
animatedStyle
|
|
21
|
+
]}
|
|
22
|
+
>
|
|
23
|
+
{children}
|
|
24
|
+
</Animated.View>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
4
27
|
|
|
5
28
|
const styles = StyleSheet.create({
|
|
6
29
|
container: {
|
|
@@ -59,7 +82,7 @@ interface PropsType<T extends AsyncType> {
|
|
|
59
82
|
props: object
|
|
60
83
|
loading: ComponentType<unknown>
|
|
61
84
|
fallback: ComponentType<unknown>
|
|
62
|
-
children: (props:
|
|
85
|
+
children: (props: any) => ReactNode | ReactNode
|
|
63
86
|
}
|
|
64
87
|
|
|
65
88
|
interface StateType {
|
|
@@ -72,7 +95,7 @@ interface ComponentError extends Error {
|
|
|
72
95
|
type: 'timeout' | 'fail'
|
|
73
96
|
}
|
|
74
97
|
|
|
75
|
-
const DefaultLoading = () => {
|
|
98
|
+
export const DefaultLoading = () => {
|
|
76
99
|
return (
|
|
77
100
|
<View style={styles.container}>
|
|
78
101
|
<FastImage
|
|
@@ -83,11 +106,11 @@ const DefaultLoading = () => {
|
|
|
83
106
|
)
|
|
84
107
|
}
|
|
85
108
|
|
|
86
|
-
interface DefaultFallbackProps {
|
|
109
|
+
export interface DefaultFallbackProps {
|
|
87
110
|
onReload: () => void
|
|
88
111
|
}
|
|
89
112
|
|
|
90
|
-
const DefaultFallback = ({ onReload }: DefaultFallbackProps) => {
|
|
113
|
+
export const DefaultFallback = ({ onReload }: DefaultFallbackProps) => {
|
|
91
114
|
return (
|
|
92
115
|
<View style={styles.container}>
|
|
93
116
|
<Image
|
|
@@ -177,11 +200,16 @@ export default class AsyncContainer extends Component<PropsType<AsyncType>, Stat
|
|
|
177
200
|
|
|
178
201
|
render () {
|
|
179
202
|
if (this.state.hasError) {
|
|
180
|
-
|
|
203
|
+
if (this.props.type === 'component') {
|
|
204
|
+
return this.errorFallback
|
|
205
|
+
} else {
|
|
206
|
+
return (<PageWrapper>{this.errorFallback}</PageWrapper>)
|
|
207
|
+
}
|
|
181
208
|
} else {
|
|
182
209
|
return (
|
|
183
210
|
<Suspense fallback={this.suspenseFallback} key={this.state.key}>
|
|
184
|
-
{this.props.children(this.props.props)}
|
|
211
|
+
{typeof this.props.children === 'function' ? this.props.children(this.props.props) : this.props.children}
|
|
212
|
+
{/* {this.props.children(this.props.props)} */}
|
|
185
213
|
</Suspense>
|
|
186
214
|
)
|
|
187
215
|
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { useState, ComponentType, useEffect, useCallback, useRef } from 'react'
|
|
2
|
+
import { DefaultFallback, DefaultLoading, PageWrapper } from './AsyncContainer'
|
|
3
|
+
import type { DefaultFallbackProps } from './AsyncContainer'
|
|
4
|
+
|
|
5
|
+
const asyncChunkMap = new Map()
|
|
6
|
+
|
|
7
|
+
interface props {
|
|
8
|
+
type: 'component' | 'page'
|
|
9
|
+
chunkName: string
|
|
10
|
+
request: string
|
|
11
|
+
props: any,
|
|
12
|
+
loading: ComponentType<unknown>
|
|
13
|
+
fallback: ComponentType<unknown>
|
|
14
|
+
getChildren: () => Promise<unknown>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const AsyncSuspense: React.FC<props> = ({ type, props, chunkName, request, loading, fallback, getChildren }) => {
|
|
18
|
+
const [status, setStatus] = useState('pending')
|
|
19
|
+
const loaded = asyncChunkMap.has(request)
|
|
20
|
+
const [, setKey] = useState(0)
|
|
21
|
+
const chunkPromise = useRef<null | Promise<unknown>>(null)
|
|
22
|
+
|
|
23
|
+
const reloadPage = useCallback(() => {
|
|
24
|
+
setKey((preV) => preV + 1)
|
|
25
|
+
console.log('[mpxAsyncSuspense]: reload page')
|
|
26
|
+
setStatus('pending')
|
|
27
|
+
}, [])
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (!loaded && status === 'pending') {
|
|
31
|
+
// todo 清楚副作用?
|
|
32
|
+
console.log('the current :', chunkPromise.current)
|
|
33
|
+
chunkPromise.current!
|
|
34
|
+
.then((m: any) => {
|
|
35
|
+
console.log('[mpxAsyncSuspense]: load sucess')
|
|
36
|
+
asyncChunkMap.set(request, m.__esModule ? m.default : m)
|
|
37
|
+
setStatus('loaded')
|
|
38
|
+
})
|
|
39
|
+
.catch((e) => {
|
|
40
|
+
if (type === 'component') {
|
|
41
|
+
console.log(11111, e)
|
|
42
|
+
global.onLazyLoadError({
|
|
43
|
+
type: 'subpackage',
|
|
44
|
+
subpackage: [chunkName],
|
|
45
|
+
errMsg: `loadSubpackage: ${e.type}`
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
console.log('[mpxAsyncSuspense]: load eror', e)
|
|
49
|
+
chunkPromise.current = null
|
|
50
|
+
setStatus('error')
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
if (loaded) {
|
|
56
|
+
const Comp = asyncChunkMap.get(request)
|
|
57
|
+
return <Comp {...props}></Comp>
|
|
58
|
+
} else if (status === 'error') {
|
|
59
|
+
console.log('the status is:', status)
|
|
60
|
+
if (type === 'page') {
|
|
61
|
+
const Fallback = fallback as ComponentType<DefaultFallbackProps> || DefaultFallback
|
|
62
|
+
return <><PageWrapper><Fallback onReload={reloadPage}></Fallback></PageWrapper></>
|
|
63
|
+
} else {
|
|
64
|
+
const Fallback = loading
|
|
65
|
+
return <Fallback {...props}></Fallback>
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
if (!chunkPromise.current) {
|
|
69
|
+
chunkPromise.current = getChildren()
|
|
70
|
+
}
|
|
71
|
+
if (type === 'page') {
|
|
72
|
+
const Fallback = loading || DefaultLoading
|
|
73
|
+
return <PageWrapper><Fallback /></PageWrapper>
|
|
74
|
+
} else {
|
|
75
|
+
const Fallback = loading
|
|
76
|
+
return <Fallback {...props}></Fallback>
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export default AsyncSuspense
|