@bm-fe/react-native-multi-bundle 1.0.0-beta.0 → 1.0.0-beta.2
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/INTEGRATION.md +101 -65
- package/android/moduleloader/build.gradle +93 -0
- package/android/moduleloader/src/main/AndroidManifest.xml +4 -0
- package/android/moduleloader/src/main/AndroidManifestNew.xml +3 -0
- package/android/moduleloader/src/main/java/com/bitmart/exchange/module/loader/ModuleLoaderModule.kt +449 -0
- package/android/moduleloader/src/main/java/com/bitmart/exchange/module/loader/ModuleLoaderPackage.kt +24 -0
- package/package.json +11 -3
- package/react-native.config.js +23 -0
- package/scripts/build-multi-bundle.js +29 -5
- package/src/multi-bundle/LocalBundleManager.ts +25 -13
- package/src/multi-bundle/ModuleLoaderMock.ts +105 -17
- package/src/multi-bundle/ModuleRegistry.ts +0 -2
- package/src/multi-bundle/README.md +1 -0
- package/src/multi-bundle/init.ts +94 -51
- package/templates/metro.config.js.template +157 -5
package/INTEGRATION.md
CHANGED
|
@@ -55,93 +55,70 @@ npx react-native start
|
|
|
55
55
|
|
|
56
56
|
## Native 模块集成
|
|
57
57
|
|
|
58
|
-
### Android
|
|
58
|
+
### Android(自动链接,无需手动配置)
|
|
59
59
|
|
|
60
|
-
####
|
|
60
|
+
#### 自动链接工作原理
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
安装包后,React Native CLI 会自动:
|
|
63
|
+
1. 读取包中的 `react-native.config.js` 配置
|
|
64
|
+
2. 将 `ModuleLoaderPackage` 添加到 `PackageList` 中
|
|
65
|
+
3. 在构建时自动集成原生模块
|
|
63
66
|
|
|
64
|
-
|
|
65
|
-
- `ModuleLoaderPackage.kt` → `android/app/src/main/java/com/yourpackage/ModuleLoaderPackage.kt`
|
|
67
|
+
#### 验证自动链接
|
|
66
68
|
|
|
67
|
-
|
|
69
|
+
安装包后,可以通过以下命令验证自动链接是否生效:
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
```bash
|
|
72
|
+
npx react-native config
|
|
73
|
+
```
|
|
70
74
|
|
|
71
|
-
|
|
75
|
+
在输出中应该能看到 `@bm-fe/react-native-multi-bundle` 的配置信息。
|
|
72
76
|
|
|
73
|
-
|
|
77
|
+
#### 确保 assets 目录存在
|
|
74
78
|
|
|
75
|
-
|
|
79
|
+
确保 `android/app/src/main/assets/` 目录存在,bundle 文件将放在这里:
|
|
76
80
|
|
|
77
|
-
```
|
|
78
|
-
|
|
81
|
+
```bash
|
|
82
|
+
mkdir -p android/app/src/main/assets/modules
|
|
83
|
+
```
|
|
79
84
|
|
|
80
|
-
|
|
81
|
-
import com.yourpackage.ModuleLoaderPackage
|
|
82
|
-
import com.facebook.react.PackageList
|
|
83
|
-
import com.facebook.react.ReactApplication
|
|
84
|
-
import com.facebook.react.ReactHost
|
|
85
|
-
import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
|
|
86
|
-
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
|
|
85
|
+
#### 手动集成(可选,仅在自动链接不工作时使用)
|
|
87
86
|
|
|
88
|
-
|
|
89
|
-
override val reactHost: ReactHost by lazy {
|
|
90
|
-
getDefaultReactHost(
|
|
91
|
-
context = applicationContext,
|
|
92
|
-
packageList =
|
|
93
|
-
PackageList(this).packages.apply {
|
|
94
|
-
// Packages that cannot be autolinked yet can be added manually here
|
|
95
|
-
add(ModuleLoaderPackage())
|
|
96
|
-
},
|
|
97
|
-
)
|
|
98
|
-
}
|
|
87
|
+
如果自动链接不工作(极少数情况),可以手动集成:
|
|
99
88
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
loadReactNative(this)
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
```
|
|
89
|
+
<details>
|
|
90
|
+
<summary>点击展开手动集成步骤</summary>
|
|
106
91
|
|
|
107
|
-
#####
|
|
92
|
+
##### 1. 复制 Native 模块文件
|
|
108
93
|
|
|
109
|
-
|
|
94
|
+
将以下文件从 `node_modules/@bm-fe/react-native-multi-bundle/templates/native/android/` 复制到你的 Android 项目:
|
|
110
95
|
|
|
111
|
-
|
|
112
|
-
|
|
96
|
+
- `ModuleLoaderModule.kt` → `android/app/src/main/java/com/yourpackage/ModuleLoaderModule.kt`
|
|
97
|
+
- `ModuleLoaderPackage.kt` → `android/app/src/main/java/com/yourpackage/ModuleLoaderPackage.kt`
|
|
98
|
+
|
|
99
|
+
**重要**:修改文件中的包名 `com.yourpackage` 为你的实际包名。
|
|
100
|
+
|
|
101
|
+
##### 2. 注册 ModuleLoaderPackage
|
|
102
|
+
|
|
103
|
+
在 `MainApplication.kt` 中添加:
|
|
113
104
|
|
|
114
|
-
|
|
105
|
+
```kotlin
|
|
115
106
|
import com.yourpackage.ModuleLoaderPackage
|
|
116
|
-
import com.facebook.react.ReactApplication
|
|
117
|
-
import com.facebook.react.ReactPackage
|
|
118
|
-
import com.facebook.react.PackageList
|
|
119
|
-
import com.facebook.react.ReactNativeHost
|
|
120
|
-
import com.facebook.react.defaults.DefaultReactNativeHost
|
|
121
107
|
|
|
122
108
|
class MainApplication : Application(), ReactApplication {
|
|
123
|
-
override val
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
|
|
133
|
-
// ... 其他配置
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// ... 其他代码
|
|
109
|
+
override val reactHost: ReactHost by lazy {
|
|
110
|
+
getDefaultReactHost(
|
|
111
|
+
context = applicationContext,
|
|
112
|
+
packageList = PackageList(this).packages.apply {
|
|
113
|
+
add(ModuleLoaderPackage()) // 手动添加
|
|
114
|
+
},
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
// ...
|
|
137
118
|
}
|
|
138
119
|
```
|
|
139
120
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
#### 3. 确保 assets 目录存在
|
|
143
|
-
|
|
144
|
-
确保 `android/app/src/main/assets/` 目录存在,bundle 文件将放在这里。
|
|
121
|
+
</details>
|
|
145
122
|
|
|
146
123
|
### iOS
|
|
147
124
|
|
|
@@ -326,6 +303,53 @@ export const createHomeScreen = createModuleRouteLoader('home', 'Home');
|
|
|
326
303
|
<Stack.Screen name="Home" getComponent={createHomeScreen} />
|
|
327
304
|
```
|
|
328
305
|
|
|
306
|
+
**路由 Props 传递说明:**
|
|
307
|
+
|
|
308
|
+
`createModuleRouteLoader` 会自动将 React Navigation 的路由 props 传递给模块组件,包括:
|
|
309
|
+
|
|
310
|
+
- `navigation`:导航对象,用于页面跳转
|
|
311
|
+
- `route`:路由对象,包含路由参数和配置
|
|
312
|
+
|
|
313
|
+
模块组件可以直接使用这些 props:
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
// 在模块组件中(如 HomeScreen.tsx)
|
|
317
|
+
import React from 'react';
|
|
318
|
+
import { View, Text } from 'react-native';
|
|
319
|
+
import { NativeStackScreenProps } from '@react-navigation/native-stack';
|
|
320
|
+
|
|
321
|
+
type Props = NativeStackScreenProps<RootStackParamList, 'Home'>;
|
|
322
|
+
|
|
323
|
+
const HomeScreen = ({ navigation, route }: Props) => {
|
|
324
|
+
// 可以使用 navigation 进行页面跳转
|
|
325
|
+
const handleNavigate = () => {
|
|
326
|
+
navigation.navigate('Details', { id: '123' });
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
// 可以使用 route.params 获取路由参数
|
|
330
|
+
const params = route.params;
|
|
331
|
+
|
|
332
|
+
return (
|
|
333
|
+
<View>
|
|
334
|
+
<Text>Home Screen</Text>
|
|
335
|
+
{/* ... */}
|
|
336
|
+
</View>
|
|
337
|
+
);
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
export default HomeScreen;
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
如果需要传递额外的 props,可以通过 React Navigation 的 `initialParams` 或 `getInitialProps`:
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
<Stack.Screen
|
|
347
|
+
name="Home"
|
|
348
|
+
getComponent={createHomeScreen}
|
|
349
|
+
initialParams={{ customProp: 'value' }}
|
|
350
|
+
/>
|
|
351
|
+
```
|
|
352
|
+
|
|
329
353
|
### 方式二:使用路由注册系统
|
|
330
354
|
|
|
331
355
|
```typescript
|
|
@@ -364,6 +388,18 @@ const HomeScreen = getModuleRoute('home', 'Home');
|
|
|
364
388
|
- 检查 `devServer` 配置是否正确
|
|
365
389
|
- 验证 manifest URL 是否可访问
|
|
366
390
|
|
|
391
|
+
### 5. 配置文件找不到
|
|
392
|
+
|
|
393
|
+
如果执行打包命令时提示 `Config file not found`:
|
|
394
|
+
|
|
395
|
+
- **确认配置文件位置**:`multi-bundle.config.json` 应该在项目根目录(与 `package.json` 同级)
|
|
396
|
+
- **确认执行目录**:打包命令应该在项目根目录执行,或者通过 npm scripts 执行
|
|
397
|
+
- **手动指定项目根目录**:如果仍有问题,可以通过环境变量指定:
|
|
398
|
+
```bash
|
|
399
|
+
PROJECT_ROOT=/path/to/your/project node node_modules/@bm-fe/react-native-multi-bundle/scripts/build-multi-bundle.js ios
|
|
400
|
+
```
|
|
401
|
+
- **检查文件路径**:确认错误信息中的路径是否正确指向你的项目根目录
|
|
402
|
+
|
|
367
403
|
## 更多信息
|
|
368
404
|
|
|
369
405
|
- [API 参考](./src/multi-bundle/README.md)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
def isNewArchitectureEnabled() {
|
|
2
|
+
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
apply plugin: "com.android.library"
|
|
6
|
+
apply plugin: "org.jetbrains.kotlin.android"
|
|
7
|
+
|
|
8
|
+
if (isNewArchitectureEnabled()) {
|
|
9
|
+
apply plugin: "com.facebook.react"
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
def getExtOrDefault(name) {
|
|
13
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["ModuleLoader_" + name]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
def getExtOrIntegerDefault(name) {
|
|
17
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["ModuleLoader_" + name]).toInteger()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
def supportsNamespace() {
|
|
21
|
+
def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
|
|
22
|
+
def major = parsed[0].toInteger()
|
|
23
|
+
def minor = parsed[1].toInteger()
|
|
24
|
+
|
|
25
|
+
// Namespace support was added in 7.3.0
|
|
26
|
+
return (major == 7 && minor >= 3) || major >= 8
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
android {
|
|
30
|
+
if (supportsNamespace()) {
|
|
31
|
+
namespace "com.bitmart.exchange.module.loader"
|
|
32
|
+
|
|
33
|
+
sourceSets {
|
|
34
|
+
main {
|
|
35
|
+
manifest.srcFile "src/main/AndroidManifestNew.xml"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
41
|
+
|
|
42
|
+
defaultConfig {
|
|
43
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
44
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
45
|
+
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
buildFeatures {
|
|
49
|
+
buildConfig true
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
buildTypes {
|
|
53
|
+
release {
|
|
54
|
+
minifyEnabled false
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
lintOptions {
|
|
59
|
+
disable "GradleCompatible"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
compileOptions {
|
|
63
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
64
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
kotlinOptions {
|
|
68
|
+
jvmTarget = "17"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
repositories {
|
|
73
|
+
mavenCentral()
|
|
74
|
+
google()
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
def isInDevelopment = project.hasProperty('ModuleLoader_development') && project.property('ModuleLoader_development') == "true"
|
|
78
|
+
|
|
79
|
+
dependencies {
|
|
80
|
+
if (isInDevelopment) {
|
|
81
|
+
implementation("com.facebook.react:react-android:0.71.+")
|
|
82
|
+
} else {
|
|
83
|
+
// For < 0.71, this will be from the local maven repo
|
|
84
|
+
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
|
85
|
+
//noinspection GradleDynamicVersion
|
|
86
|
+
implementation "com.facebook.react:react-native:+"
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Kotlin Coroutines
|
|
90
|
+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
|
|
91
|
+
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
|
|
92
|
+
}
|
|
93
|
+
|