Skip to content

Commit 79af8cd

Browse files
authored
Merge branch 'master' into feat-build-component-i18n
2 parents 97a2597 + a94dca3 commit 79af8cd

File tree

14 files changed

+175
-36
lines changed

14 files changed

+175
-36
lines changed

docs-vitepress/guide/platform/rn.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2590,6 +2590,21 @@ mpx.config.rnConfig.downloadChunkAsync = function (packages) {
25902590
}
25912591
```
25922592

2593+
针对异步分包加载异常的场景:
2594+
2595+
* 异步组件加载失败:微信小程序提供了 [`wx.onLazyLoadError`](https://developers.weixin.qq.com/miniprogram/dev/api/base/app/app-event/wx.onLazyLoadError.html) 的全局 api 来监听异步组件加载失败,这个 api 同样在Mpx转RN场景下生效;
2596+
* 异步页面加载失败:微信小程序未提供相关的监听异常的 api,Mpx转RN提供了一个额外的全局监听函数:
2597+
2598+
```javascript
2599+
// RN 场景下监听异步页面加载失败的全局配置
2600+
mpx.config.rnConfig.lazyLoadPageErrorHandler = function (error) {
2601+
console.log(
2602+
error.subpackage, // 加载失败的分包名
2603+
error.errType // 加载失败的类型:'timeout' | 'fail'
2604+
)
2605+
}
2606+
```
2607+
25932608
此外针对Mpx转RN的场景,还提供了一些异步分包的配置选项:
25942609

25952610
```javascript
@@ -2650,7 +2665,7 @@ module.exports = defineConfig({
26502665
其参数为当前页面的 onShareAppMessage 钩子返回内容,如果返回返回内容中包含 promise,将会在 fulfilled 后将其结果合并再触发 onShareAppMessage
26512666

26522667
`(shareInfo: { title: string, path: string, imageUrl?: string }) => void`
2653-
2668+
26542669

26552670

26562671
#### 路由
@@ -2712,4 +2727,4 @@ module.exports = defineConfig({
27122727
可在此方法中返回修改后的 dimensions,如果无返回或返回undefined,则以入参作为返回值
27132728

27142729

2715-
例如在折叠屏中我们期望只在其中一半屏上展示,可在customDimensions中判断当前是否为折叠屏展开状态,如果是则将 ScreenWidth 设置为原来的一半。
2730+
例如在折叠屏中我们期望只在其中一半屏上展示,可在customDimensions中判断当前是否为折叠屏展开状态,如果是则将 ScreenWidth 设置为原来的一半。

packages/core/@types/index.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ interface Context {
123123
getPageId: WechatMiniprogram.Component.InstanceMethods<Record<string, any>>['getPageId']
124124
}
125125
type ExtendedComponentOptions = {
126-
disconnectOnUnmounted: boolean
127-
shallowReactivePattern: RegExp
126+
disconnectOnUnmounted?: boolean
127+
shallowReactivePattern?: RegExp
128128
} & WechatMiniprogram.Component.ComponentOptions
129129

130130
interface ComponentOpt<D extends Data, P extends Properties, C, M extends Methods, Mi extends Array<any>, S extends Record<any, any>> extends Partial<WechatMiniprogram.Component.Lifetimes & WechatMiniprogram.Component.OtherOption> {

packages/core/src/platform/env/index.ios.js

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ export function init (Mpx) {
1818
Mpx.i18n = createI18n(global.i18n)
1919
}
2020
initGlobalErrorHandling()
21-
initGlobalLazyLoadHandling()
2221
}
2322

2423
function initGlobalErrorHandling () {
@@ -65,13 +64,3 @@ function initGlobalErrorHandling () {
6564
require('promise/setimmediate/rejection-tracking').enable(rejectionTrackingOptions)
6665
}
6766
}
68-
69-
function initGlobalLazyLoadHandling () {
70-
global.onLazyLoadError = function (error) {
71-
if (global.__mpxAppCbs?.lazyLoad?.length) {
72-
global.__mpxAppCbs.lazyLoad.forEach((cb) => {
73-
cb(error)
74-
})
75-
}
76-
}
77-
}

packages/core/src/platform/patch/getDefaultOptions.ios.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as ReactNative from 'react-native'
33
import { ReactiveEffect } from '../../observer/effect'
44
import { watch } from '../../observer/watch'
55
import { del, reactive, set } from '../../observer/reactive'
6-
import { hasOwn, isFunction, noop, isObject, isArray, getByPath, collectDataset, hump2dash, dash2hump, callWithErrorHandling, wrapMethodsWithErrorHandling, error } from '@mpxjs/utils'
6+
import { hasOwn, isFunction, noop, isObject, isArray, getByPath, collectDataset, hump2dash, dash2hump, callWithErrorHandling, wrapMethodsWithErrorHandling, error, setFocusedNavigation } from '@mpxjs/utils'
77
import MpxProxy from '../../core/proxy'
88
import { BEFOREUPDATE, ONLOAD, UPDATED, ONSHOW, ONHIDE, ONRESIZE, REACTHOOKSEXEC } from '../../core/innerLifecycle'
99
import mergeOptions from '../../core/mergeOptions'
@@ -301,6 +301,7 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps
301301
instance.route = props.route.name
302302
global.__mpxPagesMap = global.__mpxPagesMap || {}
303303
global.__mpxPagesMap[props.route.key] = [instance, props.navigation]
304+
setFocusedNavigation(props.navigation)
304305
// App onLaunch 在 Page created 之前执行
305306
if (!global.__mpxAppHotLaunched && global.__mpxAppOnLaunch) {
306307
global.__mpxAppOnLaunch(props.navigation)

packages/utils/src/env.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,24 @@ export const isReact = __mpx_mode__ === 'ios' || __mpx_mode__ === 'android' || _
2929

3030
export const isWeb = __mpx_mode__ === 'web'
3131

32+
let focusedNavigation
33+
34+
export function setFocusedNavigation (navigation) {
35+
focusedNavigation = navigation
36+
}
37+
3238
export function getFocusedNavigation () {
39+
if (focusedNavigation && focusedNavigation.isFocused()) {
40+
return focusedNavigation
41+
}
3342
if (global.__mpxPagesMap) {
3443
for (const key in global.__mpxPagesMap) {
3544
const navigation = global.__mpxPagesMap[key][1]
3645
if (navigation && navigation.isFocused()) {
46+
focusedNavigation = navigation
3747
return navigation
3848
}
3949
}
4050
}
51+
return focusedNavigation
4152
}

packages/webpack-plugin/lib/dependencies/DynamicEntryDependency.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const toPosix = require('../utils/to-posix')
66
const async = require('async')
77
const parseRequest = require('../utils/parse-request')
88
const hasOwn = require('../utils/has-own')
9+
const { RetryRuntimeGlobal } = require('../retry-runtime-module')
910

1011
class DynamicEntryDependency extends NullDependency {
1112
constructor (range, request, entryType, outputPath = '', packageRoot = '', relativePath = '', context = '', extraOptions = {}) {
@@ -201,9 +202,11 @@ class DynamicEntryDependency extends NullDependency {
201202
DynamicEntryDependency.Template = class DynamicEntryDependencyTemplate {
202203
apply (dep, source, {
203204
module,
204-
chunkGraph
205+
chunkGraph,
206+
runtimeRequirements
205207
}) {
206-
const { resultPath, range, key, publicPath, extraOptions } = dep
208+
const { resultPath, key, publicPath, extraOptions } = dep
209+
let range = dep.range
207210

208211
let replaceContent = ''
209212

@@ -214,10 +217,10 @@ DynamicEntryDependency.Template = class DynamicEntryDependencyTemplate {
214217
let relativePath = toPosix(path.relative(publicPath + path.dirname(chunkGraph.getModuleChunks(module)[0].name), resultPath))
215218
if (!relativePath.startsWith('.')) relativePath = './' + relativePath
216219
replaceContent = JSON.stringify(relativePath)
217-
if (extraOptions.retryRequireAsync) {
218-
replaceContent += `).catch(function (e) {
219-
return require.async(${JSON.stringify(relativePath)});
220-
}`
220+
if (extraOptions.retryRequireAsync && extraOptions.retryRequireAsync.times > 0) {
221+
range = extraOptions.requireAsyncRange
222+
runtimeRequirements.add(RetryRuntimeGlobal)
223+
replaceContent = `${RetryRuntimeGlobal}(function() { return require.async(${JSON.stringify(relativePath)}) }, ${extraOptions.retryRequireAsync.times}, ${extraOptions.retryRequireAsync.interval})`
221224
}
222225
} else {
223226
replaceContent = JSON.stringify(resultPath)

packages/webpack-plugin/lib/dependencies/ImportDependencyTemplate.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
const ModuleDependency = require('webpack/lib/dependencies/ModuleDependency')
2+
const { RetryRuntimeGlobal } = require('../retry-runtime-module')
3+
const parseRequest = require('../utils/parse-request')
24

35
class ImportDependencyTemplate extends (
46
ModuleDependency.Template
@@ -31,6 +33,16 @@ class ImportDependencyTemplate extends (
3133
content = content.replace(/(__webpack_require__\.t\.bind\(.+,\s*)(\d+)(\s*\))/, (_, p1, p2, p3) => {
3234
return p1 + '9' + p3
3335
})
36+
37+
const { queryObj } = parseRequest(dep.request)
38+
const retryRequireAsync = queryObj.retryRequireAsync && JSON.parse(queryObj.retryRequireAsync)
39+
40+
// require.async 的场景且配置了重试次数才注入 RetryRuntimeModule
41+
if (queryObj.isRequireAsync && retryRequireAsync && retryRequireAsync.times > 0) {
42+
runtimeRequirements.add(RetryRuntimeGlobal)
43+
content = `${RetryRuntimeGlobal}(function() { return ${content} }, ${retryRequireAsync.times}, ${retryRequireAsync.interval})`
44+
}
45+
3446
source.replace(dep.range[0], dep.range[1] - 1, content)
3547
}
3648
}

packages/webpack-plugin/lib/index.js

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ const VirtualModulesPlugin = require('webpack-virtual-modules')
7777
const RuntimeGlobals = require('webpack/lib/RuntimeGlobals')
7878
const LoadAsyncChunkModule = require('./react/LoadAsyncChunkModule')
7979
const ExternalModule = require('webpack/lib/ExternalModule')
80+
const { RetryRuntimeModule, RetryRuntimeGlobal } = require('./retry-runtime-module')
8081
require('./utils/check-core-version-match')
8182

8283
const isProductionLikeMode = options => {
@@ -202,6 +203,12 @@ class MpxWebpackPlugin {
202203
options.asyncSubpackageRules = options.asyncSubpackageRules || []
203204
options.optimizeRenderRules = options.optimizeRenderRules ? (Array.isArray(options.optimizeRenderRules) ? options.optimizeRenderRules : [options.optimizeRenderRules]) : []
204205
options.retryRequireAsync = options.retryRequireAsync || false
206+
if (options.retryRequireAsync === true) {
207+
options.retryRequireAsync = {
208+
times: 1,
209+
interval: 0
210+
}
211+
}
205212
options.optimizeSize = options.optimizeSize || false
206213
options.dynamicComponentRules = options.dynamicComponentRules || {}// 运行时组件配置
207214
this.options = options
@@ -615,6 +622,13 @@ class MpxWebpackPlugin {
615622
}
616623
})
617624

625+
compilation.hooks.runtimeRequirementInTree
626+
.for(RetryRuntimeGlobal)
627+
.tap('MpxWebpackPlugin', (chunk) => {
628+
compilation.addRuntimeModule(chunk, new RetryRuntimeModule())
629+
return true
630+
})
631+
618632
if (isReact(this.options.mode)) {
619633
compilation.hooks.runtimeRequirementInTree
620634
.for(RuntimeGlobals.loadScript)
@@ -1436,6 +1450,10 @@ class MpxWebpackPlugin {
14361450
if (mpx.supportRequireAsync) {
14371451
if (isWeb(mpx.mode) || isReact(mpx.mode)) {
14381452
if (isReact(mpx.mode)) tarRoot = transSubpackage(mpx.transSubpackageRules, tarRoot)
1453+
request = addQuery(request, {
1454+
isRequireAsync: true,
1455+
retryRequireAsync: JSON.stringify(this.options.retryRequireAsync)
1456+
})
14391457
const depBlock = new AsyncDependenciesBlock(
14401458
{
14411459
name: tarRoot + '/index'
@@ -1451,7 +1469,8 @@ class MpxWebpackPlugin {
14511469
const dep = new DynamicEntryDependency(range, request, 'export', '', tarRoot, '', context, {
14521470
isAsync: true,
14531471
isRequireAsync: true,
1454-
retryRequireAsync: !!this.options.retryRequireAsync
1472+
retryRequireAsync: this.options.retryRequireAsync,
1473+
requireAsyncRange: expr.range
14551474
})
14561475

14571476
parser.state.current.addPresentationalDependency(dep)
@@ -1606,7 +1625,7 @@ class MpxWebpackPlugin {
16061625
target = expr.object
16071626
}
16081627

1609-
if (!matchCondition(resourcePath, this.options.transMpxRules) || resourcePath.indexOf('node_modules/@mpxjs') !== -1 || !target || mode === srcMode) return
1628+
if (!matchCondition(resourcePath, this.options.transMpxRules) || toPosix(resourcePath).indexOf('node_modules/@mpxjs') !== -1 || !target || mode === srcMode) return
16101629

16111630
const type = target.name
16121631
const name = type === 'wx' ? 'mpx' : 'createFactory'

packages/webpack-plugin/lib/react/LoadAsyncChunkModule.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const HelperRuntimeModule = require('webpack/lib/runtime/HelperRuntimeModule')
55
class LoadAsyncChunkRuntimeModule extends HelperRuntimeModule {
66
constructor (timeout) {
77
super('load async chunk')
8-
this.timeout = timeout || 5000
8+
this.timeout = timeout || 10000
99
}
1010

1111
generate () {
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
const Template = require('webpack/lib/Template')
2+
const RuntimeModule = require('webpack/lib/RuntimeModule')
3+
4+
const RetryRuntimeGlobal = '__webpack_require__.__retry'
5+
6+
class RetryRuntimeModule extends RuntimeModule {
7+
constructor () {
8+
super('mpx retry module')
9+
}
10+
11+
generate () {
12+
const { compilation } = this
13+
const { runtimeTemplate } = compilation
14+
return Template.asString([
15+
`${RetryRuntimeGlobal} = ${runtimeTemplate.basicFunction(
16+
'fn, times, interval',
17+
[
18+
'times = times || 1;',
19+
'interval = interval || 0;',
20+
`return new Promise(${runtimeTemplate.basicFunction(
21+
'resolve, reject',
22+
[
23+
Template.indent([
24+
'var _t = 0;',
25+
`var _retry = ${runtimeTemplate.basicFunction('', [
26+
Template.indent([
27+
`fn().then(resolve).catch(${runtimeTemplate.basicFunction('err', [
28+
Template.indent([
29+
'if (_t < times) {',
30+
Template.indent([
31+
'++_t;',
32+
'interval > 0 ? setTimeout(_retry, interval) : _retry()'
33+
]),
34+
'} else {',
35+
Template.indent([
36+
'reject(err);'
37+
]),
38+
'}'
39+
])
40+
])})`
41+
])
42+
])};`,
43+
'_retry();'
44+
])
45+
]
46+
)})`
47+
]
48+
)}`
49+
])
50+
}
51+
}
52+
53+
module.exports = {
54+
RetryRuntimeModule,
55+
RetryRuntimeGlobal
56+
}

0 commit comments

Comments
 (0)