@flun/node-mobile-app 1.0.2 → 2.0.0
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/Android /346/236/204/345/273/272/346/214/207/345/215/227.md" +348 -315
- package/CHANGELOG.md +89 -0
- package/README.md +450 -447
- package/mobileAppConfig.js +13 -15
- package/package.json +7 -7
- package/src/commands/build.js +1 -1
- package/src/commands/clean.js +1 -1
- package/src/commands/test.js +1 -1
- package/src/config.js +1 -3
- package/src/copy.js +50 -0
- package/src/fingerprint.js +3 -3
- package/src/generate.js +6 -4
- package/src/install.js +51 -14
- package/template/App.tsx +1 -1
- package/template/package.json +18 -18
- package//350/207/252/345/256/232/344/271/211libnode/346/214/207/345/215/227.md +444 -446
- package/template/@types/nodejs-mobile-react-native/index.d.ts +0 -9
package/README.md
CHANGED
|
@@ -1,447 +1,450 @@
|
|
|
1
|
-
# @flun/node-mobile-app
|
|
2
|
-
|
|
3
|
-
将 Node.js 项目一键打包为 Android / iOS
|
|
4
|
-
|
|
5
|
-
**核心理念**:你的的 Node 项目保持不变,CLI 负责搬运、编译、打包。所有定制集中在 `mobileAppConfig.js` 一个文件。
|
|
6
|
-
|
|
7
|
-
- GitHub:https://github.com/OpenFlun/node-mobile-app
|
|
8
|
-
- Gitee(国内镜像):https://gitee.com/OpenFlun/node-mobile-app
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## 特性
|
|
13
|
-
|
|
14
|
-
- **零侵入**:Node 项目源码、依赖、配置都不动,CLI 在独立目录里完成构建
|
|
15
|
-
- **自动识别服务地址**:拦截 `server.js` 里的 `listen()` 调用,动态获取真实协议和端口
|
|
16
|
-
- **失败可见**:5 秒内未启动、加载异常,App 显示错误页并支持展开详情(开发者可查)
|
|
17
|
-
- **增量构建**:文件指纹判断缓存,无变化时 10 秒级重跑
|
|
18
|
-
- **跨平台**:Android(Windows / macOS / Linux)+ iOS(仅 macOS)
|
|
19
|
-
- **离线可用**:`build` 打出的 APK / IPA 内置 JS,无需连电脑也能跑
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## 环境要求
|
|
24
|
-
|
|
25
|
-
| 项 | 要求 |
|
|
26
|
-
| ------------ | ------------------------------------------------------------------- |
|
|
27
|
-
| Node.js | >= 18.20.4 |
|
|
28
|
-
| Android 构建 | JDK **17**、Android SDK(minSdk 29 / targetSdk 36 / compileSdk 37) |
|
|
29
|
-
| iOS 构建 | macOS + Xcode + CocoaPods |
|
|
30
|
-
| 可选 | watchman(提升 Metro 文件监听性能) |
|
|
31
|
-
|
|
32
|
-
**JDK 必须是 17**,Android Gradle Plugin 目前不支持更高版本。
|
|
33
|
-
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
## 本包目录结构:
|
|
37
|
-
```txt
|
|
38
|
-
@flun/node-mobile-app/
|
|
39
|
-
│
|
|
40
|
-
├── bin/
|
|
41
|
-
│ └── cli.js # CLI 入口(命令分发)
|
|
42
|
-
│
|
|
43
|
-
├── cli-assets/
|
|
44
|
-
│ └── server.js # 默认 server 模板(你的项目无 server.js 时复制过去)
|
|
45
|
-
│
|
|
46
|
-
├── scripts/
|
|
47
|
-
│ └── copy-files.js # postinstall 钩子:在你的项目根生成 mobileAppConfig.js
|
|
48
|
-
│
|
|
49
|
-
├── src/
|
|
50
|
-
│ ├── config.js # 配置加载 + 校验(DEFAULT_CONFIG / loadConfig / validateConfig)
|
|
51
|
-
│ ├── copy.js # 模板复制 / 你的项目复制 / ABI patch / extraRnDependencies 注入
|
|
52
|
-
│ ├── fingerprint.js # 缓存指纹(判断是否需要清理构建缓存)
|
|
53
|
-
│ ├── generate.js # 生成 main.js(桥接)+ mobileApp.runtime.ts(运行时配置)
|
|
54
|
-
│ ├── install.js # 依赖安装 + 插件 abiFilters patch + WebView SSL patch
|
|
55
|
-
│ ├── patcher.js # 应用信息 / Android / iOS 配置 patch
|
|
56
|
-
│ ├── platform-ios.js # iOS 构建(pod install / xcodebuild archive / export)
|
|
57
|
-
│ ├── utils.js # 通用工具(文件操作 / 进程调用 / adb / hermesc 定位)
|
|
58
|
-
│ └── commands/
|
|
59
|
-
│ ├── test.js # `test` 命令
|
|
60
|
-
│ ├── build.js # `build` 命令
|
|
61
|
-
│ └── clean.js # `clean` 命令
|
|
62
|
-
│
|
|
63
|
-
├── template/ # RN 工程模板(运行时复制到你的项目的 node-mobile-app-build/)
|
|
64
|
-
│ ├── android/ # Android 原生工程
|
|
65
|
-
│ ├── ios/ # iOS 原生工程
|
|
66
|
-
│ ├── @types/
|
|
67
|
-
│ │ └── nodejs-mobile-react-native/
|
|
68
|
-
│ │ └── index.d.ts # nodejs-mobile 类型声明
|
|
69
|
-
│ ├── App.tsx # RN 主界面(WebView + Node 桥接 + 错误页)
|
|
70
|
-
│ ├── index.js # RN 入口(注册根组件)
|
|
71
|
-
│ ├── app.json # RN 应用名(CLI 会覆盖)
|
|
72
|
-
│ ├── babel.config.js
|
|
73
|
-
│ ├── eslint.config.js
|
|
74
|
-
│ ├── metro.config.js # Metro 配置(watchFolders / nodeModulesPaths)
|
|
75
|
-
│ ├── mobileApp.runtime.d.ts # App.tsx 里 import 的类型声明(运行时由 CLI 生成 .ts)
|
|
76
|
-
│ ├── package.json # RN 工程依赖清单
|
|
77
|
-
│ ├── .prettierrc.js
|
|
78
|
-
│ ├── Gemfile
|
|
79
|
-
│ └── .watchmanconfig # watchman 文件监控配置(详见下方说明)
|
|
80
|
-
│
|
|
81
|
-
├── mobileAppConfig.js # 你的配置模板(postinstall 时复制到你的项目根)
|
|
82
|
-
├── package.json
|
|
83
|
-
├── README.md # 本文件
|
|
84
|
-
├── Android构建指南.md # Android 环境配置与踩坑清单
|
|
85
|
-
├── 自定义libnode指南.md # 自编译 libnode.so 的完整流程
|
|
86
|
-
└── 其它略...
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
**关键约定**:
|
|
90
|
-
- `template/` 是**只读模板**。CLI 每次 `test`/`build` 会把它复制到你的项目的 `node-mobile-app-build/`,你的如手改模板内容会被覆盖
|
|
91
|
-
- 你的持久化的自定义项应写进 `mobileAppConfig.js`,或通过 `keepFiles` 保留特定模板文件
|
|
92
|
-
- `template/.watchmanconfig` 会在 `copyTemplate` 时复制到 `node-mobile-app-build/.watchmanconfig`,供 Metro 的 watchman 使用
|
|
93
|
-
|
|
94
|
-
### .watchmanconfig 说明
|
|
95
|
-
|
|
96
|
-
位于包根目录,配置 watchman 的文件监控行为:
|
|
97
|
-
|
|
98
|
-
```json
|
|
99
|
-
{
|
|
100
|
-
"ignore_dirs": [
|
|
101
|
-
".git", ".vs", ".vscode", ".idea",
|
|
102
|
-
"android/build", "android/app/build", "android/.gradle", "android/.cxx", "android/.kotlin",
|
|
103
|
-
"ios/build", "ios/Pods",
|
|
104
|
-
"node-mobile-app-build", "nodejs-assets",
|
|
105
|
-
"out", "dist", "dist-apk", "coverage"
|
|
106
|
-
],
|
|
107
|
-
"settle": 20
|
|
108
|
-
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
- **`ignore_dirs`**:排除的目录(构建产物、缓存、IDE 配置)。**不要排除 `node_modules`**,Metro 需要监控它来解析依赖
|
|
112
|
-
- **`settle`**:防抖延迟(毫秒),短时间内多次文件变更只触发一次重编
|
|
113
|
-
- 改完后需 `watchman watch-del-all && watchman shutdown-server` 才生效
|
|
114
|
-
|
|
115
|
-
---
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
---
|
|
136
|
-
|
|
137
|
-
##
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
|
167
|
-
|
|
|
168
|
-
|
|
|
169
|
-
|
|
|
170
|
-
|
|
|
171
|
-
|
|
172
|
-
###
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
|
211
|
-
|
|
|
212
|
-
| `
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
|
218
|
-
|
|
|
219
|
-
| `
|
|
220
|
-
| `
|
|
221
|
-
| `
|
|
222
|
-
| `
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
|
231
|
-
|
|
|
232
|
-
| `
|
|
233
|
-
| `
|
|
234
|
-
| `
|
|
235
|
-
| `
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
|
240
|
-
|
|
|
241
|
-
| `
|
|
242
|
-
| `
|
|
243
|
-
| `
|
|
244
|
-
| `
|
|
245
|
-
| `
|
|
246
|
-
| `
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
|
251
|
-
|
|
|
252
|
-
| `
|
|
253
|
-
| `
|
|
254
|
-
| `signing.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
|
262
|
-
|
|
|
263
|
-
| `
|
|
264
|
-
| `
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
|
270
|
-
|
|
|
271
|
-
| `
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
|
277
|
-
|
|
|
278
|
-
| `
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
`
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
├──
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
adb
|
|
386
|
-
adb shell am
|
|
387
|
-
adb
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
1
|
+
# @flun/node-mobile-app
|
|
2
|
+
|
|
3
|
+
将 Node.js 项目一键打包为 Android / iOS 移动应用。运行时由 @flun/nodejs-mobile-react-native 提供,无需修改你的 Node 代码;
|
|
4
|
+
|
|
5
|
+
**核心理念**:你的的 Node 项目保持不变,CLI 负责搬运、编译、打包。所有定制集中在 `mobileAppConfig.js` 一个文件。
|
|
6
|
+
|
|
7
|
+
- GitHub:https://github.com/OpenFlun/node-mobile-app
|
|
8
|
+
- Gitee(国内镜像):https://gitee.com/OpenFlun/node-mobile-app
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 特性
|
|
13
|
+
|
|
14
|
+
- **零侵入**:Node 项目源码、依赖、配置都不动,CLI 在独立目录里完成构建
|
|
15
|
+
- **自动识别服务地址**:拦截 `server.js` 里的 `listen()` 调用,动态获取真实协议和端口
|
|
16
|
+
- **失败可见**:5 秒内未启动、加载异常,App 显示错误页并支持展开详情(开发者可查)
|
|
17
|
+
- **增量构建**:文件指纹判断缓存,无变化时 10 秒级重跑
|
|
18
|
+
- **跨平台**:Android(Windows / macOS / Linux)+ iOS(仅 macOS)
|
|
19
|
+
- **离线可用**:`build` 打出的 APK / IPA 内置 JS,无需连电脑也能跑
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 环境要求
|
|
24
|
+
|
|
25
|
+
| 项 | 要求 |
|
|
26
|
+
| ------------ | ------------------------------------------------------------------- |
|
|
27
|
+
| Node.js | >= 18.20.4 |
|
|
28
|
+
| Android 构建 | JDK **17**、Android SDK(minSdk 29 / targetSdk 36 / compileSdk 37) |
|
|
29
|
+
| iOS 构建 | macOS + Xcode + CocoaPods |
|
|
30
|
+
| 可选 | watchman(提升 Metro 文件监听性能) |
|
|
31
|
+
|
|
32
|
+
**JDK 必须是 17**,Android Gradle Plugin 目前不支持更高版本。
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 本包目录结构:
|
|
37
|
+
```txt
|
|
38
|
+
@flun/node-mobile-app/
|
|
39
|
+
│
|
|
40
|
+
├── bin/
|
|
41
|
+
│ └── cli.js # CLI 入口(命令分发)
|
|
42
|
+
│
|
|
43
|
+
├── cli-assets/
|
|
44
|
+
│ └── server.js # 默认 server 模板(你的项目无 server.js 时复制过去)
|
|
45
|
+
│
|
|
46
|
+
├── scripts/
|
|
47
|
+
│ └── copy-files.js # postinstall 钩子:在你的项目根生成 mobileAppConfig.js
|
|
48
|
+
│
|
|
49
|
+
├── src/
|
|
50
|
+
│ ├── config.js # 配置加载 + 校验(DEFAULT_CONFIG / loadConfig / validateConfig)
|
|
51
|
+
│ ├── copy.js # 模板复制 / 你的项目复制 / ABI patch / extraRnDependencies 注入
|
|
52
|
+
│ ├── fingerprint.js # 缓存指纹(判断是否需要清理构建缓存)
|
|
53
|
+
│ ├── generate.js # 生成 main.js(桥接)+ mobileApp.runtime.ts(运行时配置)
|
|
54
|
+
│ ├── install.js # 依赖安装 + 插件 abiFilters patch + WebView SSL patch
|
|
55
|
+
│ ├── patcher.js # 应用信息 / Android / iOS 配置 patch
|
|
56
|
+
│ ├── platform-ios.js # iOS 构建(pod install / xcodebuild archive / export)
|
|
57
|
+
│ ├── utils.js # 通用工具(文件操作 / 进程调用 / adb / hermesc 定位)
|
|
58
|
+
│ └── commands/
|
|
59
|
+
│ ├── test.js # `test` 命令
|
|
60
|
+
│ ├── build.js # `build` 命令
|
|
61
|
+
│ └── clean.js # `clean` 命令
|
|
62
|
+
│
|
|
63
|
+
├── template/ # RN 工程模板(运行时复制到你的项目的 node-mobile-app-build/)
|
|
64
|
+
│ ├── android/ # Android 原生工程
|
|
65
|
+
│ ├── ios/ # iOS 原生工程
|
|
66
|
+
│ ├── @types/
|
|
67
|
+
│ │ └── nodejs-mobile-react-native/
|
|
68
|
+
│ │ └── index.d.ts # nodejs-mobile 类型声明
|
|
69
|
+
│ ├── App.tsx # RN 主界面(WebView + Node 桥接 + 错误页)
|
|
70
|
+
│ ├── index.js # RN 入口(注册根组件)
|
|
71
|
+
│ ├── app.json # RN 应用名(CLI 会覆盖)
|
|
72
|
+
│ ├── babel.config.js
|
|
73
|
+
│ ├── eslint.config.js
|
|
74
|
+
│ ├── metro.config.js # Metro 配置(watchFolders / nodeModulesPaths)
|
|
75
|
+
│ ├── mobileApp.runtime.d.ts # App.tsx 里 import 的类型声明(运行时由 CLI 生成 .ts)
|
|
76
|
+
│ ├── package.json # RN 工程依赖清单
|
|
77
|
+
│ ├── .prettierrc.js
|
|
78
|
+
│ ├── Gemfile
|
|
79
|
+
│ └── .watchmanconfig # watchman 文件监控配置(详见下方说明)
|
|
80
|
+
│
|
|
81
|
+
├── mobileAppConfig.js # 你的配置模板(postinstall 时复制到你的项目根)
|
|
82
|
+
├── package.json
|
|
83
|
+
├── README.md # 本文件
|
|
84
|
+
├── Android构建指南.md # Android 环境配置与踩坑清单
|
|
85
|
+
├── 自定义libnode指南.md # 自编译 libnode.so 的完整流程
|
|
86
|
+
└── 其它略...
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**关键约定**:
|
|
90
|
+
- `template/` 是**只读模板**。CLI 每次 `test`/`build` 会把它复制到你的项目的 `node-mobile-app-build/`,你的如手改模板内容会被覆盖
|
|
91
|
+
- 你的持久化的自定义项应写进 `mobileAppConfig.js`,或通过 `keepFiles` 保留特定模板文件
|
|
92
|
+
- `template/.watchmanconfig` 会在 `copyTemplate` 时复制到 `node-mobile-app-build/.watchmanconfig`,供 Metro 的 watchman 使用
|
|
93
|
+
|
|
94
|
+
### .watchmanconfig 说明
|
|
95
|
+
|
|
96
|
+
位于包根目录,配置 watchman 的文件监控行为:
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"ignore_dirs": [
|
|
101
|
+
".git", ".vs", ".vscode", ".idea",
|
|
102
|
+
"android/build", "android/app/build", "android/.gradle", "android/.cxx", "android/.kotlin",
|
|
103
|
+
"ios/build", "ios/Pods",
|
|
104
|
+
"node-mobile-app-build", "nodejs-assets",
|
|
105
|
+
"out", "dist", "dist-apk", "coverage"
|
|
106
|
+
],
|
|
107
|
+
"settle": 20
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
- **`ignore_dirs`**:排除的目录(构建产物、缓存、IDE 配置)。**不要排除 `node_modules`**,Metro 需要监控它来解析依赖
|
|
112
|
+
- **`settle`**:防抖延迟(毫秒),短时间内多次文件变更只触发一次重编
|
|
113
|
+
- 改完后需 `watchman watch-del-all && watchman shutdown-server` 才生效
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
## 基本配置
|
|
117
|
+
|
|
118
|
+
### 允许安装脚本执行
|
|
119
|
+
|
|
120
|
+
本包在安装时可能触发某些依赖包的自动脚本(如 `postinstall` 等);如果你的 npm 全局配置或项目配置禁止了脚本执行(例如设置了 `ignore-scripts=true`),可能会导致安装不完整或运行时异常;
|
|
121
|
+
|
|
122
|
+
推荐在项目根目录的 `package.json` 中添加 `allowScripts` 字段,显式放行本包及其依赖的脚本:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"allowScripts": {
|
|
127
|
+
"@flun/nodejs-mobile-react-native": true,
|
|
128
|
+
"@flun/node-mobile-app": true
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
> 如果你信任所有安装包,也可以直接在项目 `.npmrc` 中设置 `allow-scripts = false`(表示关闭脚本拦截,所有脚本均允许执行),或删除 `ignore-script`字段;
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 安装
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
npm i --save-dev @flun/node-mobile-app
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
安装完成后,会在你的项目根目录自动生成 `mobileAppConfig.js`(配置文件模板);
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 快速开始
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# 1. 编辑配置
|
|
150
|
+
# 打开 mobileAppConfig.js,改 appId / appName / serverPath 等
|
|
151
|
+
|
|
152
|
+
# 2. 开发调试(需连 USB,走 Metro 热更新,如需用模拟器请在 mobileAppConfig.js文件中显式配置)
|
|
153
|
+
npx node-mobile-app test
|
|
154
|
+
|
|
155
|
+
# 3. 打包发布
|
|
156
|
+
npx node-mobile-app build --release
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 命令说明
|
|
162
|
+
|
|
163
|
+
| 命令 | 用途 |
|
|
164
|
+
| ------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
165
|
+
| `npx node-mobile-app test` | 编译并安装到设备(**需连 USB**,走 Metro 热更新) |
|
|
166
|
+
| `npx node-mobile-app test --ios` | iOS 版(仅 macOS) |
|
|
167
|
+
| `npx node-mobile-app build` | 打 debug APK(**离线可用**) |
|
|
168
|
+
| `npx node-mobile-app build --release` | 打 release APK(默认用 debug keystore 签名,可安装;上架需配置 `android.signing`) |
|
|
169
|
+
| `npx node-mobile-app build --ios` | 打 IPA(仅 macOS) |
|
|
170
|
+
| `npx node-mobile-app clean` | 清理构建缓存 |
|
|
171
|
+
|
|
172
|
+
### 常用选项
|
|
173
|
+
|
|
174
|
+
| 选项 | 用途 |
|
|
175
|
+
| --------------- | ----------------------------------------- |
|
|
176
|
+
| `--ios` | 目标平台为 iOS(默认 Android) |
|
|
177
|
+
| `--release` | 打 release 包(仅 `build`) |
|
|
178
|
+
| `--device <id>` | 指定设备(`test`) |
|
|
179
|
+
| `--arch <abi>` | 指定 ABI,逗号分隔(`build`,仅 Android) |
|
|
180
|
+
|
|
181
|
+
### 安装 APK 到手机
|
|
182
|
+
|
|
183
|
+
`build` 打出的 APK 在 `outputDir`(默认 `./out/`)里。手动装到手机:
|
|
184
|
+
|
|
185
|
+
```powershell
|
|
186
|
+
# Windows PowerShell
|
|
187
|
+
$adb = "$env:LOCALAPPDATA\Android\Sdk\platform-tools\adb.exe"
|
|
188
|
+
& $adb install -r "D:\你的项目\out\<appName>-<versionName>-debug.apk"
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# macOS / Linux
|
|
193
|
+
adb install -r ./out/<appName>-<versionName>-debug.apk
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**说明**:
|
|
197
|
+
- `-r` = 覆盖安装(保留应用数据)
|
|
198
|
+
- 不知道 APK 的确切文件名?看 `build` 命令的末尾输出(会打印完整路径)
|
|
199
|
+
- `adb` 找不到?在 `mobileAppConfig.js` 里配 `android.adbPath`
|
|
200
|
+
- `test` 命令已自动安装,无需手动
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## 配置文件 `mobileAppConfig.js`
|
|
205
|
+
|
|
206
|
+
所有定制集中在这一个文件。**不配置也能跑**(用默认值)。
|
|
207
|
+
|
|
208
|
+
### 必填
|
|
209
|
+
|
|
210
|
+
| 字段 | 类型 | 说明 |
|
|
211
|
+
| ------------ | -------- | ----------------------------------------- |
|
|
212
|
+
| `serverPath` | `string` | Node 启动脚本路径(默认 `'./server.js'`) |
|
|
213
|
+
|
|
214
|
+
### 应用信息
|
|
215
|
+
|
|
216
|
+
| 字段 | 类型 | 说明 |
|
|
217
|
+
| ------------- | ---------------- | -------------------------------------------------------------------------- |
|
|
218
|
+
| `appName` | `string \| null` | 应用显示名称(默认从 `package.json` 的 `name` 读) |
|
|
219
|
+
| `outputDir` | `string \| null` | APK / IPA 输出目录(默认 `./out`) |
|
|
220
|
+
| `appId` | `string` | 应用唯一标识,反向域名格式(Android `applicationId` / iOS Bundle ID) |
|
|
221
|
+
| `versionCode` | `int` | 内部版本号(Android `versionCode` / iOS `CFBundleVersion`) |
|
|
222
|
+
| `versionName` | `string` | 你的可见版本名(Android `versionName` / iOS `CFBundleShortVersionString`) |
|
|
223
|
+
|
|
224
|
+
### WebView
|
|
225
|
+
|
|
226
|
+
| 字段 | 类型 | 默认 | 说明 |
|
|
227
|
+
| --------------------- | --------- | ------------------- | ------------------------------------------------------------------------------------------- |
|
|
228
|
+
| `showLoading` | `boolean` | `true` | 是否显示加载指示器 |
|
|
229
|
+
| `loadingText` | `string` | `'正在启动服务...'` | 加载提示文字 |
|
|
230
|
+
| `enableJavaScript` | `boolean` | `true` | 是否启用 JavaScript |
|
|
231
|
+
| `enableDomStorage` | `boolean` | `true` | 是否启用 DOM Storage |
|
|
232
|
+
| `allowFileAccess` | `boolean` | `true` | 是否允许访问本地文件 |
|
|
233
|
+
| `mixedContentMode` | `string` | `'always'` | 混合内容模式:`never` / `always` / `compatibility` |
|
|
234
|
+
| `backgroundColor` | 见下 | `'#ffffff'` | WebView 背景色。支持:固定色 `'#ffffff'` / 跟随系统 `'system'` / 深浅两值 `{ light, dark }` |
|
|
235
|
+
| `allowSelfSignedCert` | `boolean` | `false` | 见下文「HTTPS 自签证书」 |
|
|
236
|
+
|
|
237
|
+
### Android
|
|
238
|
+
|
|
239
|
+
| 字段 | 类型 | 默认 | 说明 |
|
|
240
|
+
| ----------------------- | ---------------- | -------------------- | ----------------------------------------------------------------------- |
|
|
241
|
+
| `sdkPath` | `string \| null` | `null` | Android SDK 路径(默认自动查找) |
|
|
242
|
+
| `adbPath` | `string \| null` | `null` | adb 路径(默认自动查找) |
|
|
243
|
+
| `minSdkVersion` | `int` | `29` | 最低 SDK(29=Android 10.0) |
|
|
244
|
+
| `targetSdkVersion` | `int` | `36` | 目标 SDK |
|
|
245
|
+
| `compileSdkVersion` | `int` | `37` | 编译 SDK |
|
|
246
|
+
| `buildToolsVersion` | `string` | `'37.0.0'` | 构建工具版本 |
|
|
247
|
+
| `abiFilters` | `string[]` | `['arm64-v8a']` | 打包架构(真机 `arm64-v8a`,模拟器加 `x86_64`) |
|
|
248
|
+
| `icon` | `string` | `'./build/icon.png'` | 应用图标(建议 512×512 PNG) |
|
|
249
|
+
| `usesCleartextTraffic` | `boolean` | `true` | 是否允许明文 HTTP |
|
|
250
|
+
| `permissions` | `string[]` | `[]` | 额外权限(如 `'android.permission.CAMERA'`) |
|
|
251
|
+
| `signing.keystore` | `string` | — | 签名 keystore 路径(相对你的项目根)。不填则用模板自带的 debug keystore |
|
|
252
|
+
| `signing.storePassword` | `string` | — | keystore 密码 |
|
|
253
|
+
| `signing.keyAlias` | `string` | — | key 别名 |
|
|
254
|
+
| `signing.keyPassword` | `string` | — | key 密码 |
|
|
255
|
+
|
|
256
|
+
### iOS
|
|
257
|
+
|
|
258
|
+
| 字段 | 类型 | 默认 | 说明 |
|
|
259
|
+
| ----------------------------- | -------- | -------------------- | ------------------------------------------------------ |
|
|
260
|
+
| `deploymentTarget` | `string` | `'15.1'` | 最低 iOS 版本 |
|
|
261
|
+
| `icon` | `string` | `'./build/icon.png'` | 应用图标(建议 1024×1024 PNG) |
|
|
262
|
+
| `signing.teamId` | `string` | — | Apple Developer Team ID |
|
|
263
|
+
| `signing.provisioningProfile` | `string` | — | 描述文件路径(写入 `exportOptions.plist`) |
|
|
264
|
+
| `signing.certificate` | `string` | — | P12 证书路径(导入临时 keychain 供 xcodebuild 签名用) |
|
|
265
|
+
| `signing.certificatePassword` | `string` | — | P12 密码 |
|
|
266
|
+
|
|
267
|
+
### 高级
|
|
268
|
+
|
|
269
|
+
| 字段 | 类型 | 默认 | 说明 |
|
|
270
|
+
| ---------------------------- | --------- | ------ | -------------------------- |
|
|
271
|
+
| `advanced.keepAlive` | `boolean` | `true` | 是否发送心跳保持 Node 进程 |
|
|
272
|
+
| `advanced.heartbeatInterval` | `int` | `5000` | 心跳间隔(毫秒) |
|
|
273
|
+
|
|
274
|
+
### 扩展点
|
|
275
|
+
|
|
276
|
+
| 字段 | 类型 | 默认 | 说明 |
|
|
277
|
+
| --------------------- | ---------- | ---- | ----------------------------------------------------- |
|
|
278
|
+
| `keepFiles` | `string[]` | `[]` | 不重置的模板文件(路径相对 `node-mobile-app-build/`) |
|
|
279
|
+
| `extraRnDependencies` | `string[]` | `[]` | 额外 RN 原生依赖包名(需先安装在你的开发字段中) |
|
|
280
|
+
|
|
281
|
+
### 排除 / 白名单
|
|
282
|
+
|
|
283
|
+
| 字段 | 说明 |
|
|
284
|
+
| -------------- | ---------------------------------------------------------------------------- |
|
|
285
|
+
| `excludeFiles` | 复制到 build 目录时跳过的文件/目录(支持 `*.log`、`build/` 等) |
|
|
286
|
+
| `allowScripts` | 移动端 Node 环境里允许跑安装脚本的包(会写入 `nodejs-project/package.json`) |
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## 服务地址说明
|
|
291
|
+
|
|
292
|
+
CLI **自动识别 `server.js` 实际监听的协议和端口**——拦截 `net.Server.prototype.listen`,从 `server.address()` 取真实端口,从 `Server` 类型判断 `http` / `https`。
|
|
293
|
+
|
|
294
|
+
因此 `mobileAppConfig.js` **不需要**配置端口/协议。动态端口(`listen(0)`)会拿到系统分配的真实端口。
|
|
295
|
+
|
|
296
|
+
**失败场景**:
|
|
297
|
+
- `server.js` 加载抛异常 → App 显示"应用启动失败"
|
|
298
|
+
- 5 秒内未调用 `listen()` → App 显示"应用启动失败"
|
|
299
|
+
|
|
300
|
+
你的看到简要提示,开发者点开"▶ 查看详细信息"能看到具体原因。
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## HTTPS 自签证书
|
|
305
|
+
|
|
306
|
+
`webview.allowSelfSignedCert` 控制是否放行**不受信任的 HTTPS 证书**:
|
|
307
|
+
|
|
308
|
+
| 场景 | 是否受开关影响 |
|
|
309
|
+
| --------------------------------------------- | ------------------- |
|
|
310
|
+
| HTTP | 无关 |
|
|
311
|
+
| HTTPS + 真证书(Let's Encrypt 等) | 无关 |
|
|
312
|
+
| HTTPS + 自签证书 + 已装进设备信任库 | 无关 |
|
|
313
|
+
| HTTPS + 自签证书 + 未装设备(本地测试最常见) | **必须设为 `true`** |
|
|
314
|
+
|
|
315
|
+
**实现方式**:
|
|
316
|
+
- Android:patch `RNCWebViewClient.java`,仅对 `127.0.0.1` / `localhost` 放行
|
|
317
|
+
- iOS:patch `RNCWebViewImpl.m`,同上
|
|
318
|
+
|
|
319
|
+
其他域名仍严格校验。生产环境建议关闭。
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## Android / iOS 差异
|
|
324
|
+
|
|
325
|
+
| 项 | Android | iOS |
|
|
326
|
+
| ------------ | --------------------------------- | ------------------------------------------------------ |
|
|
327
|
+
| 构建环境 | Windows / macOS / Linux | **仅 macOS** |
|
|
328
|
+
| Node.js 版本 | v18(官方)/ v22+(自编译) | **v18**(官方;v22 需自编译 `NodeMobile.xcframework`) |
|
|
329
|
+
| Express 版本 | v18 用 4.x,v22 + full-icu 用 5.x | **v18 必须用 4.x** |
|
|
330
|
+
| `test` 离线 | ✓(内置 bundle) | ✓(需 `FORCE_BUNDLING=1`) |
|
|
331
|
+
| 图标尺寸 | 5 个密度(48~192) | 9 个尺寸(40~1024) |
|
|
332
|
+
|
|
333
|
+
**iOS Node 版本限制**:`nodejs-mobile` 官方为 iOS 提供的二进制停留在 v18。v22 需自行编译 `NodeMobile.xcframework`,流程与 Android 自编译 `libnode.so` 类似(见 `自定义libnode指南.md`)。
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## 你的项目结构
|
|
338
|
+
|
|
339
|
+
运行 CLI 后,你的项目根目录的样子:
|
|
340
|
+
|
|
341
|
+
```
|
|
342
|
+
你的项目/
|
|
343
|
+
├── package.json # 你自己的
|
|
344
|
+
├── mobileAppConfig.js # CLI 生成的配置(可编辑)
|
|
345
|
+
├── server.js # Node 启动脚本(你写的,或 CLI 生成的示例)
|
|
346
|
+
├── node_modules/ # 你的依赖
|
|
347
|
+
├── build/ # 你的资源(图标、keystore 等)
|
|
348
|
+
│ ├── icon.png
|
|
349
|
+
│ └── release.keystore
|
|
350
|
+
│── 你的其它文件/目录...
|
|
351
|
+
└── node-mobile-app-build/ # CLI 生成的 RN 工程(可整体删除重建)
|
|
352
|
+
├── android/ ios/ App.tsx index.js ...
|
|
353
|
+
├── mobileApp.runtime.ts # CLI 生成,App.tsx 读
|
|
354
|
+
└── nodejs-assets/
|
|
355
|
+
└── nodejs-project/ # 你的 Node 项目副本
|
|
356
|
+
├── server.js # 你的源码
|
|
357
|
+
├── main.js # CLI 生成,桥接代码
|
|
358
|
+
├── package.json # 只保留 dependencies
|
|
359
|
+
└── node_modules/ # 你的生产依赖
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## 常见问题
|
|
365
|
+
|
|
366
|
+
### Q:`test` 拔掉 USB 后 App 加载慢?
|
|
367
|
+
|
|
368
|
+
`test` 打的是 debug 版,启动时**先尝试连 Metro**,失败后才 fallback 到内置 bundle。这个"等超时"是 RN debug 版的固有行为。
|
|
369
|
+
|
|
370
|
+
- 需要**秒开**:用 `npx node-mobile-app build`
|
|
371
|
+
- 需要**热更新**:`test` 保持 USB 连接
|
|
372
|
+
|
|
373
|
+
### Q:`test` 装到手机后拔 USB 就崩?
|
|
374
|
+
|
|
375
|
+
前提是 APK 里有内置 bundle。`test` 每次都会先 `react-native bundle` 打进 APK。**如果崩,检查 CLI 输出里 `[6/9] 生成 JS bundle` 是否成功**。
|
|
376
|
+
|
|
377
|
+
### Q:Node 进程启动失败怎么排查?
|
|
378
|
+
|
|
379
|
+
App 显示"应用启动失败"页 → 点"▶ 查看详细信息" → 看到具体原因(如 `加载 ./server.js 失败 -- ...`)。
|
|
380
|
+
|
|
381
|
+
进一步用 `adb logcat` 看 Node 日志:
|
|
382
|
+
|
|
383
|
+
```bash
|
|
384
|
+
adb logcat -c
|
|
385
|
+
adb shell am force-stop <你的 appId>
|
|
386
|
+
adb shell am start -n <你的 appId>/.MainActivity
|
|
387
|
+
adb logcat | grep -E "NODEJS-MOBILE|ReactNativeJS"
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Q:`npm install` 时提示 `install-scripts not yet covered by allowScripts`?
|
|
391
|
+
- 请检查 你的 'package.json' 中 "allowScripts" 字段
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
### Q:Express 版本怎么选?
|
|
395
|
+
|
|
396
|
+
- **`libnode.so` 不带 full-icu(官方 v18)** → **必须用 Express 4**(如 `4.22.2`)
|
|
397
|
+
- **`libnode.so` 带 full-icu(自编译 v22)** → 可以用 Express 5(如 `5.2.1`)
|
|
398
|
+
|
|
399
|
+
Express 5 的路由语法与 4 不同(如 `app.get('*')` 要改成 `app.get('/{*splat}')`),迁移时留意。
|
|
400
|
+
|
|
401
|
+
### Q:`libnode.so` 和 `NodeMobile.xcframework` 是怎么来的?
|
|
402
|
+
|
|
403
|
+
从 `@flun/nodejs-mobile-react-native` 1.0.1 起,两套预编译二进制**不在 npm 包里**,改为 postinstall 阶段自动从 Gitee / GitHub Release 下载:
|
|
404
|
+
|
|
405
|
+
| 资源 | 大小 | 目标位置 |
|
|
406
|
+
| -------------------------------- | -------- | --------------------------------------------------------------------------- |
|
|
407
|
+
| `android-libnode.zip` | 约 52 MB | `node_modules/@flun/nodejs-mobile-react-native/android/libnode/` |
|
|
408
|
+
| `ios-nodemobile.zip`(仅 macOS) | 约 47 MB | `node_modules/@flun/nodejs-mobile-react-native/ios/NodeMobile.xcframework/` |
|
|
409
|
+
|
|
410
|
+
- 默认下载 v18.20.4 官方二进制
|
|
411
|
+
- Gitee 优先,失败自动回退 GitHub
|
|
412
|
+
- 已装版本匹配则跳过,不重复下
|
|
413
|
+
- 全部源失败时打印下载链接,**不中断 npm 安装**
|
|
414
|
+
|
|
415
|
+
环境变量:
|
|
416
|
+
|
|
417
|
+
```bash
|
|
418
|
+
NODE_MOBILE_PREBUILT_VERSION=v22.23.2 # 覆盖默认版本
|
|
419
|
+
NODE_MOBILE_PREBUILT_SKIP=1 # 跳过全部下载
|
|
420
|
+
NODE_MOBILE_PREBUILT_IOS_SKIP=1 # 只跳过 iOS
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### Q:如何替换成自定义编译的 `libnode.so`?
|
|
424
|
+
|
|
425
|
+
如果你自编译了带 full-icu 的 v22(或其它版本)`libnode.so`,可手动覆盖自动下载的产物:
|
|
426
|
+
|
|
427
|
+
1. 把编译好的 `libnode.so` 覆盖到 `android/libnode/bin/<架构>/`(**只放你实际编译的架构**)
|
|
428
|
+
2. 如果 `mobileAppConfig.js` 的 `android.abiFilters` 与 libnode 支持的架构不一致,同步调整
|
|
429
|
+
3. 跑 `npx node-mobile-app build` 或 `npx node-mobile-app test`
|
|
430
|
+
|
|
431
|
+
**CLI 会自动处理缓存**:指纹机制检测到 `libnode.so` 或 `abiFilters` 变化,自动清理 `.cxx` / `android/build` / `app/build`,全量重编。**你的无需手动清任何缓存**。
|
|
432
|
+
|
|
433
|
+
详细流程(自编译 v22 + full-icu)见 `自定义libnode指南.md`。
|
|
434
|
+
|
|
435
|
+
### Q:iOS 提示 `fallbackSourceURL does not override`?
|
|
436
|
+
|
|
437
|
+
RN 0.87 的 API 若变动,`AppDelegate.swift` 里的 fallback 可能不生效——不影响"连 Mac + Metro"正常开发,只是拔 Mac 后无法 fallback 到内置 bundle。届时反馈,我们更新适配。
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## 相关文档
|
|
442
|
+
|
|
443
|
+
- [Android 构建指南.md](./Android%20构建指南.md) —— Android 环境配置、踩坑清单
|
|
444
|
+
- [自定义libnode指南.md](./自定义libnode指南.md) —— 自编译 v22 `libnode.so` 的完整流程
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## 许可
|
|
449
|
+
|
|
450
|
+
ISC
|