@mpxjs/webpack-plugin 2.10.6-beta.7 → 2.10.7-beta.1
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 +2 -3
- package/lib/index.js +21 -23
- package/lib/react/processJSON.js +0 -4
- package/lib/react/processScript.js +2 -2
- package/lib/react/script-helper.js +44 -22
- package/lib/runtime/components/react/AsyncContainer.tsx +217 -0
- package/lib/runtime/components/react/AsyncSuspense.tsx +51 -164
- package/lib/runtime/components/react/dist/AsyncContainer.jsx +160 -0
- package/lib/runtime/components/react/dist/AsyncSuspense.jsx +44 -113
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +13 -2
- package/lib/runtime/components/react/dist/mpx-rich-text/index.jsx +3 -0
- package/lib/runtime/components/react/dist/mpx-view.jsx +21 -7
- package/lib/runtime/components/react/dist/utils.jsx +9 -0
- package/lib/runtime/components/react/mpx-movable-view.tsx +15 -1
- package/lib/runtime/components/react/mpx-rich-text/index.tsx +3 -0
- package/lib/runtime/components/react/mpx-view.tsx +20 -7
- package/lib/runtime/components/react/utils.tsx +10 -0
- package/lib/runtime/optionProcessor.js +0 -2
- package/lib/runtime/optionProcessorReact.d.ts +0 -18
- package/lib/runtime/optionProcessorReact.js +0 -24
- package/package.json +3 -3
- package/lib/dependencies/RecordFileUrlDependency.js +0 -58
- package/lib/utils/trans-async-sub-rules.js +0 -34
|
@@ -1,192 +1,79 @@
|
|
|
1
|
-
import { useState, ComponentType, useEffect, useCallback, useRef
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
1
|
+
import { useState, ComponentType, useEffect, useCallback, useRef } from 'react'
|
|
2
|
+
import { DefaultFallback, DefaultLoading, PageWrapper } from './AsyncContainer'
|
|
3
|
+
import type { DefaultFallbackProps } from './AsyncContainer'
|
|
4
4
|
|
|
5
5
|
const asyncChunkMap = new Map()
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
container: {
|
|
9
|
-
flex: 1,
|
|
10
|
-
padding: 20,
|
|
11
|
-
backgroundColor: '#fff'
|
|
12
|
-
},
|
|
13
|
-
loadingImage: {
|
|
14
|
-
width: 100,
|
|
15
|
-
height: 100,
|
|
16
|
-
marginTop: 220,
|
|
17
|
-
alignSelf: 'center'
|
|
18
|
-
},
|
|
19
|
-
buttonText: {
|
|
20
|
-
color: '#fff',
|
|
21
|
-
fontSize: 16,
|
|
22
|
-
fontWeight: '500',
|
|
23
|
-
textAlign: 'center'
|
|
24
|
-
},
|
|
25
|
-
errorImage: {
|
|
26
|
-
marginTop: 80,
|
|
27
|
-
width: 220,
|
|
28
|
-
aspectRatio: 1,
|
|
29
|
-
alignSelf: 'center'
|
|
30
|
-
},
|
|
31
|
-
errorText: {
|
|
32
|
-
fontSize: 16,
|
|
33
|
-
textAlign: 'center',
|
|
34
|
-
color: '#333',
|
|
35
|
-
marginBottom: 20
|
|
36
|
-
},
|
|
37
|
-
retryButton: {
|
|
38
|
-
position: 'absolute',
|
|
39
|
-
bottom: 54,
|
|
40
|
-
left: 20,
|
|
41
|
-
right: 20,
|
|
42
|
-
backgroundColor: '#fff',
|
|
43
|
-
paddingVertical: 15,
|
|
44
|
-
borderRadius: 30,
|
|
45
|
-
marginTop: 40,
|
|
46
|
-
borderWidth: 1,
|
|
47
|
-
borderColor: '#FF5F00'
|
|
48
|
-
},
|
|
49
|
-
retryButtonText: {
|
|
50
|
-
color: '#FF5F00',
|
|
51
|
-
fontSize: 16,
|
|
52
|
-
fontWeight: '500',
|
|
53
|
-
textAlign: 'center'
|
|
54
|
-
}
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
interface LayoutViewProps {
|
|
58
|
-
children: ReactNode
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
interface AsyncModule {
|
|
62
|
-
__esModule: boolean
|
|
63
|
-
default: ReactNode
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
interface DefaultFallbackProps {
|
|
67
|
-
onReload: () => void
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const DefaultFallback = ({ onReload }: DefaultFallbackProps) => {
|
|
71
|
-
return (
|
|
72
|
-
<View style={styles.container}>
|
|
73
|
-
<Image
|
|
74
|
-
source={{
|
|
75
|
-
uri: 'https://dpubstatic.udache.com/static/dpubimg/Vak5mZvezPpKV5ZJI6P9b_drn-fallbak.png'
|
|
76
|
-
}}
|
|
77
|
-
style={styles.errorImage}
|
|
78
|
-
resizeMode="contain"
|
|
79
|
-
/>
|
|
80
|
-
<Text style={styles.errorText}>网络出了点问题,请查看网络环境</Text>
|
|
81
|
-
<TouchableOpacity
|
|
82
|
-
style={styles.retryButton}
|
|
83
|
-
onPress={onReload}
|
|
84
|
-
activeOpacity={0.7}
|
|
85
|
-
>
|
|
86
|
-
<Text style={styles.retryButtonText}>点击重试</Text>
|
|
87
|
-
</TouchableOpacity>
|
|
88
|
-
</View>
|
|
89
|
-
)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const LayoutView = (props: LayoutViewProps) => {
|
|
93
|
-
return (
|
|
94
|
-
<View style={{ flex: 1 }} collapsable={false}>{props.children}</View>
|
|
95
|
-
)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const DefaultLoading = () => {
|
|
99
|
-
return (
|
|
100
|
-
<View style={styles.container}>
|
|
101
|
-
<FastImage
|
|
102
|
-
style={styles.loadingImage}
|
|
103
|
-
source={{
|
|
104
|
-
uri: 'https://dpubstatic.udache.com/static/dpubimg/439jiCVOtNOnEv9F2LaDs_loading.gif'
|
|
105
|
-
}}
|
|
106
|
-
resizeMode={FastImage.resizeMode.contain}
|
|
107
|
-
></FastImage>
|
|
108
|
-
</View>
|
|
109
|
-
)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
interface AsyncSuspenseProps {
|
|
7
|
+
interface props {
|
|
113
8
|
type: 'component' | 'page'
|
|
114
9
|
chunkName: string
|
|
115
|
-
|
|
116
|
-
|
|
10
|
+
request: string
|
|
11
|
+
props: any,
|
|
117
12
|
loading: ComponentType<unknown>
|
|
118
13
|
fallback: ComponentType<unknown>
|
|
119
|
-
getChildren: () => Promise<
|
|
14
|
+
getChildren: () => Promise<unknown>
|
|
120
15
|
}
|
|
121
16
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
chunkName,
|
|
128
|
-
moduleId,
|
|
129
|
-
loading,
|
|
130
|
-
fallback,
|
|
131
|
-
getChildren
|
|
132
|
-
}) => {
|
|
133
|
-
const [status, setStatus] = useState<ComponentStauts>('pending')
|
|
134
|
-
const chunkLoaded = asyncChunkMap.has(moduleId)
|
|
135
|
-
const loadChunkPromise = useRef<null | Promise<AsyncModule>>(null)
|
|
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)
|
|
136
22
|
|
|
137
23
|
const reloadPage = useCallback(() => {
|
|
24
|
+
setKey((preV) => preV + 1)
|
|
25
|
+
console.log('[mpxAsyncSuspense]: reload page')
|
|
138
26
|
setStatus('pending')
|
|
139
27
|
}, [])
|
|
140
28
|
|
|
141
29
|
useEffect(() => {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return () => {
|
|
167
|
-
cancelled = true
|
|
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
|
+
})
|
|
168
52
|
}
|
|
169
|
-
}
|
|
53
|
+
})
|
|
170
54
|
|
|
171
|
-
if (
|
|
172
|
-
const Comp = asyncChunkMap.get(
|
|
173
|
-
return
|
|
55
|
+
if (loaded) {
|
|
56
|
+
const Comp = asyncChunkMap.get(request)
|
|
57
|
+
return <Comp {...props}></Comp>
|
|
174
58
|
} else if (status === 'error') {
|
|
59
|
+
console.log('the status is:', status)
|
|
175
60
|
if (type === 'page') {
|
|
176
|
-
const Fallback =
|
|
177
|
-
|
|
178
|
-
return createElement(LayoutView, null, createElement(Fallback, { onReload: reloadPage }))
|
|
61
|
+
const Fallback = fallback as ComponentType<DefaultFallbackProps> || DefaultFallback
|
|
62
|
+
return <><PageWrapper><Fallback onReload={reloadPage}></Fallback></PageWrapper></>
|
|
179
63
|
} else {
|
|
180
|
-
|
|
64
|
+
const Fallback = loading
|
|
65
|
+
return <Fallback {...props}></Fallback>
|
|
181
66
|
}
|
|
182
67
|
} else {
|
|
183
|
-
if (!
|
|
184
|
-
|
|
68
|
+
if (!chunkPromise.current) {
|
|
69
|
+
chunkPromise.current = getChildren()
|
|
185
70
|
}
|
|
186
71
|
if (type === 'page') {
|
|
187
|
-
|
|
72
|
+
const Fallback = loading || DefaultLoading
|
|
73
|
+
return <PageWrapper><Fallback /></PageWrapper>
|
|
188
74
|
} else {
|
|
189
|
-
|
|
75
|
+
const Fallback = loading
|
|
76
|
+
return <Fallback {...props}></Fallback>
|
|
190
77
|
}
|
|
191
78
|
}
|
|
192
79
|
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Component, Suspense } from 'react';
|
|
2
|
+
import { View, Text, Image, StyleSheet, TouchableOpacity } from 'react-native';
|
|
3
|
+
import FastImage from '@d11/react-native-fast-image';
|
|
4
|
+
import Animated, { useAnimatedStyle } from 'react-native-reanimated';
|
|
5
|
+
export const PageWrapper = ({ children }) => {
|
|
6
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
7
|
+
transform: [{ translateY: -0 }],
|
|
8
|
+
flexBasis: 'auto',
|
|
9
|
+
flex: 1
|
|
10
|
+
}));
|
|
11
|
+
return (<Animated.View style={[
|
|
12
|
+
animatedStyle
|
|
13
|
+
]}>
|
|
14
|
+
{children}
|
|
15
|
+
</Animated.View>);
|
|
16
|
+
};
|
|
17
|
+
const styles = StyleSheet.create({
|
|
18
|
+
container: {
|
|
19
|
+
flex: 1,
|
|
20
|
+
padding: 20,
|
|
21
|
+
backgroundColor: '#fff'
|
|
22
|
+
},
|
|
23
|
+
loadingImage: {
|
|
24
|
+
width: 100,
|
|
25
|
+
height: 100,
|
|
26
|
+
marginTop: 220,
|
|
27
|
+
alignSelf: 'center'
|
|
28
|
+
},
|
|
29
|
+
buttonText: {
|
|
30
|
+
color: '#fff',
|
|
31
|
+
fontSize: 16,
|
|
32
|
+
fontWeight: '500',
|
|
33
|
+
textAlign: 'center'
|
|
34
|
+
},
|
|
35
|
+
errorImage: {
|
|
36
|
+
marginTop: 80,
|
|
37
|
+
width: 220,
|
|
38
|
+
aspectRatio: 1,
|
|
39
|
+
alignSelf: 'center'
|
|
40
|
+
},
|
|
41
|
+
errorText: {
|
|
42
|
+
fontSize: 16,
|
|
43
|
+
textAlign: 'center',
|
|
44
|
+
color: '#333',
|
|
45
|
+
marginBottom: 20
|
|
46
|
+
},
|
|
47
|
+
retryButton: {
|
|
48
|
+
position: 'absolute',
|
|
49
|
+
bottom: 54,
|
|
50
|
+
left: 20,
|
|
51
|
+
right: 20,
|
|
52
|
+
backgroundColor: '#fff',
|
|
53
|
+
paddingVertical: 15,
|
|
54
|
+
borderRadius: 30,
|
|
55
|
+
marginTop: 40,
|
|
56
|
+
borderWidth: 1,
|
|
57
|
+
borderColor: '#FF5F00'
|
|
58
|
+
},
|
|
59
|
+
retryButtonText: {
|
|
60
|
+
color: '#FF5F00',
|
|
61
|
+
fontSize: 16,
|
|
62
|
+
fontWeight: '500',
|
|
63
|
+
textAlign: 'center'
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
export const DefaultLoading = () => {
|
|
67
|
+
return (<View style={styles.container}>
|
|
68
|
+
<FastImage style={styles.loadingImage} source={{ uri: 'https://dpubstatic.udache.com/static/dpubimg/439jiCVOtNOnEv9F2LaDs_loading.gif' }} resizeMode={FastImage.resizeMode.contain}></FastImage>
|
|
69
|
+
</View>);
|
|
70
|
+
};
|
|
71
|
+
export const DefaultFallback = ({ onReload }) => {
|
|
72
|
+
return (<View style={styles.container}>
|
|
73
|
+
<Image source={{ uri: 'https://dpubstatic.udache.com/static/dpubimg/Vak5mZvezPpKV5ZJI6P9b_drn-fallbak.png' }} style={styles.errorImage} resizeMode="contain"/>
|
|
74
|
+
<Text style={styles.errorText}>网络出了点问题,请查看网络环境</Text>
|
|
75
|
+
<TouchableOpacity style={styles.retryButton} onPress={onReload} activeOpacity={0.7}>
|
|
76
|
+
<Text style={styles.retryButtonText}>点击重试</Text>
|
|
77
|
+
</TouchableOpacity>
|
|
78
|
+
</View>);
|
|
79
|
+
};
|
|
80
|
+
export default class AsyncContainer extends Component {
|
|
81
|
+
suspenseFallback;
|
|
82
|
+
errorFallback;
|
|
83
|
+
constructor(props) {
|
|
84
|
+
super(props);
|
|
85
|
+
this.state = {
|
|
86
|
+
hasError: false,
|
|
87
|
+
key: 0
|
|
88
|
+
};
|
|
89
|
+
this.suspenseFallback = this.getSuspenseFallback();
|
|
90
|
+
this.errorFallback = this.getErrorFallback();
|
|
91
|
+
}
|
|
92
|
+
// render 阶段收集到的错误
|
|
93
|
+
static getDerivedStateFromError(error) {
|
|
94
|
+
if (error.name === 'ChunkLoadError') {
|
|
95
|
+
return {
|
|
96
|
+
hasError: true,
|
|
97
|
+
key: 0
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// 被外层捕获
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
componentDidCatch(error) {
|
|
106
|
+
if (error.name === 'ChunkLoadError' && this.props.type === 'component') {
|
|
107
|
+
const request = error.request || '';
|
|
108
|
+
const subpackage = request.split('/').filter((i) => !!i)[0];
|
|
109
|
+
global.onLazyLoadError({
|
|
110
|
+
type: 'subpackage',
|
|
111
|
+
subpackage: [subpackage],
|
|
112
|
+
errMsg: `loadSubpackage: ${error.type}`
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
reloadPage() {
|
|
117
|
+
this.setState((prevState) => {
|
|
118
|
+
return {
|
|
119
|
+
hasError: false,
|
|
120
|
+
key: prevState.key + 1
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
getSuspenseFallback() {
|
|
125
|
+
if (this.props.type === 'page') {
|
|
126
|
+
const Fallback = this.props.loading || DefaultLoading;
|
|
127
|
+
return <Fallback />;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
const Fallback = this.props.loading;
|
|
131
|
+
return <Fallback {...this.props.props}></Fallback>;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
getErrorFallback() {
|
|
135
|
+
if (this.props.type === 'page') {
|
|
136
|
+
const Fallback = this.props.fallback || DefaultFallback;
|
|
137
|
+
return <Fallback onReload={this.reloadPage.bind(this)}></Fallback>;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
const Fallback = this.props.loading;
|
|
141
|
+
return <Fallback {...this.props.props}></Fallback>;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
render() {
|
|
145
|
+
if (this.state.hasError) {
|
|
146
|
+
if (this.props.type === 'component') {
|
|
147
|
+
return this.errorFallback;
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
return (<PageWrapper>{this.errorFallback}</PageWrapper>);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
return (<Suspense fallback={this.suspenseFallback} key={this.state.key}>
|
|
155
|
+
{typeof this.props.children === 'function' ? this.props.children(this.props.props) : this.props.children}
|
|
156
|
+
{/* {this.props.children(this.props.props)} */}
|
|
157
|
+
</Suspense>);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -1,136 +1,67 @@
|
|
|
1
|
-
import { useState, useEffect, useCallback, useRef
|
|
2
|
-
import {
|
|
3
|
-
import FastImage from '@d11/react-native-fast-image';
|
|
1
|
+
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
2
|
+
import { DefaultFallback, DefaultLoading, PageWrapper } from './AsyncContainer';
|
|
4
3
|
const asyncChunkMap = new Map();
|
|
5
|
-
const
|
|
6
|
-
container: {
|
|
7
|
-
flex: 1,
|
|
8
|
-
padding: 20,
|
|
9
|
-
backgroundColor: '#fff'
|
|
10
|
-
},
|
|
11
|
-
loadingImage: {
|
|
12
|
-
width: 100,
|
|
13
|
-
height: 100,
|
|
14
|
-
marginTop: 220,
|
|
15
|
-
alignSelf: 'center'
|
|
16
|
-
},
|
|
17
|
-
buttonText: {
|
|
18
|
-
color: '#fff',
|
|
19
|
-
fontSize: 16,
|
|
20
|
-
fontWeight: '500',
|
|
21
|
-
textAlign: 'center'
|
|
22
|
-
},
|
|
23
|
-
errorImage: {
|
|
24
|
-
marginTop: 80,
|
|
25
|
-
width: 220,
|
|
26
|
-
aspectRatio: 1,
|
|
27
|
-
alignSelf: 'center'
|
|
28
|
-
},
|
|
29
|
-
errorText: {
|
|
30
|
-
fontSize: 16,
|
|
31
|
-
textAlign: 'center',
|
|
32
|
-
color: '#333',
|
|
33
|
-
marginBottom: 20
|
|
34
|
-
},
|
|
35
|
-
retryButton: {
|
|
36
|
-
position: 'absolute',
|
|
37
|
-
bottom: 54,
|
|
38
|
-
left: 20,
|
|
39
|
-
right: 20,
|
|
40
|
-
backgroundColor: '#fff',
|
|
41
|
-
paddingVertical: 15,
|
|
42
|
-
borderRadius: 30,
|
|
43
|
-
marginTop: 40,
|
|
44
|
-
borderWidth: 1,
|
|
45
|
-
borderColor: '#FF5F00'
|
|
46
|
-
},
|
|
47
|
-
retryButtonText: {
|
|
48
|
-
color: '#FF5F00',
|
|
49
|
-
fontSize: 16,
|
|
50
|
-
fontWeight: '500',
|
|
51
|
-
textAlign: 'center'
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
const DefaultFallback = ({ onReload }) => {
|
|
55
|
-
return (<View style={styles.container}>
|
|
56
|
-
<Image source={{
|
|
57
|
-
uri: 'https://dpubstatic.udache.com/static/dpubimg/Vak5mZvezPpKV5ZJI6P9b_drn-fallbak.png'
|
|
58
|
-
}} style={styles.errorImage} resizeMode="contain"/>
|
|
59
|
-
<Text style={styles.errorText}>网络出了点问题,请查看网络环境</Text>
|
|
60
|
-
<TouchableOpacity style={styles.retryButton} onPress={onReload} activeOpacity={0.7}>
|
|
61
|
-
<Text style={styles.retryButtonText}>点击重试</Text>
|
|
62
|
-
</TouchableOpacity>
|
|
63
|
-
</View>);
|
|
64
|
-
};
|
|
65
|
-
const LayoutView = (props) => {
|
|
66
|
-
return (<View style={{ flex: 1 }} collapsable={false}>{props.children}</View>);
|
|
67
|
-
};
|
|
68
|
-
const DefaultLoading = () => {
|
|
69
|
-
return (<View style={styles.container}>
|
|
70
|
-
<FastImage style={styles.loadingImage} source={{
|
|
71
|
-
uri: 'https://dpubstatic.udache.com/static/dpubimg/439jiCVOtNOnEv9F2LaDs_loading.gif'
|
|
72
|
-
}} resizeMode={FastImage.resizeMode.contain}></FastImage>
|
|
73
|
-
</View>);
|
|
74
|
-
};
|
|
75
|
-
const AsyncSuspense = ({ type, innerProps, chunkName, moduleId, loading, fallback, getChildren }) => {
|
|
4
|
+
const AsyncSuspense = ({ type, props, chunkName, request, loading, fallback, getChildren }) => {
|
|
76
5
|
const [status, setStatus] = useState('pending');
|
|
77
|
-
const
|
|
78
|
-
const
|
|
6
|
+
const loaded = asyncChunkMap.has(request);
|
|
7
|
+
const [, setKey] = useState(0);
|
|
8
|
+
const chunkPromise = useRef(null);
|
|
79
9
|
const reloadPage = useCallback(() => {
|
|
10
|
+
setKey((preV) => preV + 1);
|
|
11
|
+
console.log('[mpxAsyncSuspense]: reload page');
|
|
80
12
|
setStatus('pending');
|
|
81
13
|
}, []);
|
|
82
14
|
useEffect(() => {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
});
|
|
106
|
-
}
|
|
15
|
+
if (!loaded && status === 'pending') {
|
|
16
|
+
// todo 清楚副作用?
|
|
17
|
+
console.log('the current :', chunkPromise.current);
|
|
18
|
+
chunkPromise.current
|
|
19
|
+
.then((m) => {
|
|
20
|
+
console.log('[mpxAsyncSuspense]: load sucess');
|
|
21
|
+
asyncChunkMap.set(request, m.__esModule ? m.default : m);
|
|
22
|
+
setStatus('loaded');
|
|
23
|
+
})
|
|
24
|
+
.catch((e) => {
|
|
25
|
+
if (type === 'component') {
|
|
26
|
+
console.log(11111, e);
|
|
27
|
+
global.onLazyLoadError({
|
|
28
|
+
type: 'subpackage',
|
|
29
|
+
subpackage: [chunkName],
|
|
30
|
+
errMsg: `loadSubpackage: ${e.type}`
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
console.log('[mpxAsyncSuspense]: load eror', e);
|
|
34
|
+
chunkPromise.current = null;
|
|
35
|
+
setStatus('error');
|
|
36
|
+
});
|
|
107
37
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (chunkLoaded) {
|
|
113
|
-
const Comp = asyncChunkMap.get(moduleId);
|
|
114
|
-
return createElement(Comp, innerProps);
|
|
38
|
+
});
|
|
39
|
+
if (loaded) {
|
|
40
|
+
const Comp = asyncChunkMap.get(request);
|
|
41
|
+
return <Comp {...props}></Comp>;
|
|
115
42
|
}
|
|
116
43
|
else if (status === 'error') {
|
|
44
|
+
console.log('the status is:', status);
|
|
117
45
|
if (type === 'page') {
|
|
118
46
|
const Fallback = fallback || DefaultFallback;
|
|
119
|
-
return
|
|
47
|
+
return <><PageWrapper><Fallback onReload={reloadPage}></Fallback></PageWrapper></>;
|
|
120
48
|
}
|
|
121
49
|
else {
|
|
122
|
-
|
|
50
|
+
const Fallback = loading;
|
|
51
|
+
return <Fallback {...props}></Fallback>;
|
|
123
52
|
}
|
|
124
53
|
}
|
|
125
54
|
else {
|
|
126
|
-
if (!
|
|
127
|
-
|
|
55
|
+
if (!chunkPromise.current) {
|
|
56
|
+
chunkPromise.current = getChildren();
|
|
128
57
|
}
|
|
129
58
|
if (type === 'page') {
|
|
130
|
-
|
|
59
|
+
const Fallback = loading || DefaultLoading;
|
|
60
|
+
return <PageWrapper><Fallback /></PageWrapper>;
|
|
131
61
|
}
|
|
132
62
|
else {
|
|
133
|
-
|
|
63
|
+
const Fallback = loading;
|
|
64
|
+
return <Fallback {...props}></Fallback>;
|
|
134
65
|
}
|
|
135
66
|
}
|
|
136
67
|
};
|
|
@@ -41,7 +41,7 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
|
|
|
41
41
|
const hasLayoutRef = useRef(false);
|
|
42
42
|
const propsRef = useRef({});
|
|
43
43
|
propsRef.current = (props || {});
|
|
44
|
-
const { x = 0, y = 0, inertia = false, disabled = false, animation = true, 'out-of-bounds': outOfBounds = false, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, direction = 'none', 'simultaneous-handlers': originSimultaneousHandlers = [], 'wait-for': waitFor = [], style = {}, bindtouchstart, catchtouchstart, bindhtouchmove, bindvtouchmove, bindtouchmove, catchhtouchmove, catchvtouchmove, catchtouchmove, bindtouchend, catchtouchend, bindchange } = props;
|
|
44
|
+
const { x = 0, y = 0, inertia = false, disabled = false, animation = true, 'out-of-bounds': outOfBounds = false, 'enable-var': enableVar, 'external-var-context': externalVarContext, 'parent-font-size': parentFontSize, 'parent-width': parentWidth, 'parent-height': parentHeight, direction = 'none', 'simultaneous-handlers': originSimultaneousHandlers = [], 'wait-for': waitFor = [], style = {}, changeThrottleTime = 60, bindtouchstart, catchtouchstart, bindhtouchmove, bindvtouchmove, bindtouchmove, catchhtouchmove, catchvtouchmove, catchtouchmove, bindtouchend, catchtouchend, bindchange } = props;
|
|
45
45
|
const { hasSelfPercent, normalStyle, hasVarDec, varContextRef, setWidth, setHeight } = useTransformStyle(Object.assign({}, style, styles.container), { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight });
|
|
46
46
|
const navigation = useNavigation();
|
|
47
47
|
const prevSimultaneousHandlersRef = useRef(originSimultaneousHandlers || []);
|
|
@@ -62,6 +62,7 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
|
|
|
62
62
|
const isFirstTouch = useSharedValue(true);
|
|
63
63
|
const touchEvent = useSharedValue('');
|
|
64
64
|
const initialViewPosition = useSharedValue({ x: x || 0, y: y || 0 });
|
|
65
|
+
const lastChangeTime = useSharedValue(0);
|
|
65
66
|
const MovableAreaLayout = useContext(MovableAreaContext);
|
|
66
67
|
const simultaneousHandlers = flatGesture(originSimultaneousHandlers);
|
|
67
68
|
const waitForHandlers = flatGesture(waitFor);
|
|
@@ -99,6 +100,15 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
|
|
|
99
100
|
layoutRef
|
|
100
101
|
}, propsRef.current));
|
|
101
102
|
}, []);
|
|
103
|
+
// 节流版本的 change 事件触发
|
|
104
|
+
const handleTriggerChangeThrottled = useCallback(({ x, y, type }) => {
|
|
105
|
+
'worklet';
|
|
106
|
+
const now = Date.now();
|
|
107
|
+
if (now - lastChangeTime.value >= changeThrottleTime) {
|
|
108
|
+
lastChangeTime.value = now;
|
|
109
|
+
runOnJS(handleTriggerChange)({ x, y, type });
|
|
110
|
+
}
|
|
111
|
+
}, [changeThrottleTime]);
|
|
102
112
|
useEffect(() => {
|
|
103
113
|
runOnUI(() => {
|
|
104
114
|
if (offsetX.value !== x || offsetY.value !== y) {
|
|
@@ -354,7 +364,8 @@ const _MovableView = forwardRef((movableViewProps, ref) => {
|
|
|
354
364
|
}
|
|
355
365
|
}
|
|
356
366
|
if (bindchange) {
|
|
357
|
-
runOnJS
|
|
367
|
+
// 使用节流版本减少 runOnJS 调用
|
|
368
|
+
handleTriggerChangeThrottled({
|
|
358
369
|
x: offsetX.value,
|
|
359
370
|
y: offsetY.value
|
|
360
371
|
});
|