electron-ohos-hotreload 1.0.0 → 1.0.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/README.md ADDED
@@ -0,0 +1,63 @@
1
+ # electron-ohos-hotreload
2
+
3
+ Hot-reload CLI for Electron on HarmonyOS — push JS/TS changes to device without rebuilding HAP.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g electron-ohos-hotreload
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```bash
14
+ # 1. 进入你的 ohos_hap 工程目录
15
+ cd <你的路径>/ohos_hap
16
+
17
+ # 2. 初始化(一次性)
18
+ eohr init
19
+
20
+ # 3. 重建 HAP 并安装到设备(仅此一次)
21
+ hvigorw assembleHap --mode module -p product=default -p buildMode=debug --no-daemon
22
+ hdc install <hap文件>
23
+
24
+ # 4. 启动热加载
25
+ eohr watch
26
+ ```
27
+
28
+ 然后正常写代码,改完保存,切到终端按 `Ctrl+Shift+X`,十几秒设备上就生效了。
29
+
30
+ ## What eohr init does
31
+
32
+ - **新增** `hot-reload-agent.js`(工具自己的文件)
33
+ - **改一行** `package.json`(`main` 字段指向 agent)
34
+ - **不碰** `main.js`,你的代码原封不动
35
+
36
+ 用完了执行 `eohr clean` 自动还原,不留痕迹。
37
+
38
+ ## Commands
39
+
40
+ | 命令 | 说明 |
41
+ |------|------|
42
+ | `eohr init` | 一次性初始化 |
43
+ | `eohr watch` | 启动热加载(按 Ctrl+Shift+X 推送) |
44
+ | `eohr watch --auto` | 保存即自动推送 |
45
+ | `eohr push` | 单次推送 |
46
+ | `eohr status` | 查询设备状态 |
47
+ | `eohr strategy` | 查看/切换策略 |
48
+ | `eohr log` | 查看设备日志 |
49
+ | `eohr clean` | 恢复工程 + 清空设备 |
50
+
51
+ ## Reload Strategy
52
+
53
+ 默认 `hard`(杀进程重启),完全干净无副作用。业界标准做法。
54
+
55
+ ## Docs
56
+
57
+ - [快速上手](docs/quick-start.md)
58
+ - [用户使用手册](docs/user-manual.md)
59
+ - [设计手册](docs/design-manual.md)
60
+
61
+ ## License
62
+
63
+ BSD-2-Clause
package/bin/eohr.js CHANGED
@@ -17,7 +17,7 @@
17
17
  */
18
18
  var path = require("path");
19
19
 
20
- var VERSION = "1.0.0";
20
+ var VERSION = "1.0.2";
21
21
 
22
22
  function parseArgs(argv) {
23
23
  var args = argv.slice(2);
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "electron-ohos-hotreload",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Hot-reload CLI for Electron on HarmonyOS — push JS/TS changes to device without rebuilding HAP",
5
5
  "bin": {
6
- "eohr": "./bin/eohr.js"
6
+ "eohr": "bin/eohr.js"
7
7
  },
8
8
  "main": "bin/eohr.js",
9
9
  "scripts": {
@@ -35,6 +35,8 @@
35
35
  "bin/",
36
36
  "src/",
37
37
  "templates/",
38
- "docs/"
38
+ "docs/quick-start.md",
39
+ "docs/user-manual.md",
40
+ "README.md"
39
41
  ]
40
42
  }
@@ -1,445 +0,0 @@
1
- # Electron OHOS Hot-Reload 设计手册
2
-
3
- > **版本**: 1.4.0
4
- > **日期**: 2026-09-09
5
- > **工具名称**: `eohr` (Electron OHOS Hot-Reload)
6
-
7
- ---
8
-
9
- ## 1. 背景与目�?
10
- ### 1.1 问题
11
-
12
- 在鸿蒙版 Electron 工程中,开发者的 JS/TS 代码打包�?HAP 内的 `resfile/resources/app/` 目录中。每次修改代码都需要重�?HAP、卸载重装、重启应用,单次迭代 3~4 分钟�?
13
- ### 1.2 目标
14
-
15
- 让开发者修改自己的 Electron 应用代码后,**无需重建 HAP**�?~15 秒内完成推�?�?重载�?
16
- ### 1.3 设计原则
17
-
18
- - **不碰开发者文�?* �?`eohr init` 不修改开发者的 `main.js` 或任何业务文件,只新增一个文�?+ �?`package.json` 一�?- **零侵�?* �?不修�?ETS / 原生�?- **可恢�?* �?`eohr clean` 一条命令恢复工程到 init 之前的状态,不留痕迹
19
- - **生产安全** �?�?override �?agent 直接加载开发者的 `main.js`,行为与未安�?eohr 完全一�?
20
- ### 1.4 约束
21
-
22
- | 约束 | 影响 |
23
- |------|------|
24
- | resfile 只读 | HAP 内的文件不能运行时修改,但可从可写目�?override |
25
- | 沙箱可写 `/data/storage/el2/base/files/` | override 目录放这�?|
26
- | 物理路径 `hdc shell cat` | 状�?日志读取走物理路�?|
27
- | ETS 编译�?HAP | ETS 改动必须全量构建 |
28
- | Electron 启动�?`package.json` �?`main` 字段 | 通过�?`main` 字段注入 agent |
29
- | BOM 问题 | 推送前自动�?BOM |
30
- | node_modules 符号链接 | esbuild 打包为单文件规避 |
31
-
32
- ---
33
-
34
- ## 2. 架构
35
-
36
- ### 2.1 系统拓扑
37
-
38
- ```
39
- ┌───────────────────────────────────────────────────────────────────�?�? 开发机 (Windows) �?�? �?�? ┌──────────�? ┌───────────�? ┌──────────�? ┌──────────�? �?�? │FileWatcher│─▶│ Bundler │─▶│stripBOM │─▶│HdcBridge �? �?�? │fs.watch �? │esbuild �? �? hash �? │file send �? �?�? �? 轮询兜底 �? │开发者代�? �? �? diff �? �? touch �? �?�? └──────────�? └───────────�? └──────────�? └────┬─────�? �?�? �? �?�? ┌────────────────────────────────────────────�? �? �?�? �? eohr CLI �? �? �?�? �? init / watch / push / status / strategy �? �? �?�? �? clean / log �? �? �?�? └────────────────────────────────────────────�? �? �?�? �? �?�? ┌────────────────────────────────────────────�? �? �?�? �? Dashboard (终端彩色输出) �? �? �?�? �? 文件变更 / 打包 / 推�?/ 重载状�? �? �? �?�? └────────────────────────────────────────────�? �? �?�? �? �?�? ┌────────────────────────────────────────────�? �? �?�? �? 键盘交互 (手动模式) �? �? �?�? �? Ctrl+Shift+X 触发推�?(可配�? �? �? �?�? �? q / Ctrl+C 退�? �? �? �?�? └────────────────────────────────────────────�? �? �?└────────────────────────────────────────────────────┼───────────────�? �?hdc �?┌───────────────────────▼────────────────────────────▼───────────────�?�? 设备 (HarmonyOS) �?�? �?�? ┌──────────────────────────────────────────────────────────�? �?�? �? Electron 进程 (libelectron.so @ UIAbility) �? �?�? �? �? �?�? �? resfile/resources/app/ (只读, �?HAP 发布): �? �?�? �? ├── package.json �?main: "hot-reload-agent.js" �? �?�? �? ├── main.js �?开发者原始代�?(未改�? �? �?�? �? └── hot-reload-agent.js �?设备�?agent (eohr init 新增) �? �?�? �? �? �?�? �? /data/storage/el2/base/files/hot/ (可写 override): �? �?�? �? ├── entry.js �?esbuild 打包产物 (开发者代�? �? �?�? �? ├── hot-config.json �?运行时配�? �? �?�? �? └── .reload-trigger �?touch 触发重载 �? �?�? �? �? �?�? �? ┌──────────────────────────────────────────────────�? �? �?�? �? �?hot-reload-agent.js 运行�? �? �? �?�? �? �? ├─ app.whenReady() �?加载 entry.js (有则�? �? �? �?�? �? �? �? �?否则 require('./main.js') �? �? �?�? �? �? ├─ fs.watch override 目录 �? �? �?�? �? �? ├─ setInterval 轮询兜底 (2s) �? �? �?�? �? �? ├─ soft: require.cache 失效 + 重新 require �? �? �?�? �? �? └─ hard: app.quit() �?系统重启 Ability �? �? �?�? �? └──────────────────────────────────────────────────�? �? �?�? └──────────────────────────────────────────────────────────�? �?�? �?�? /data/storage/el2/base/files/ (状�? 可写): �?�? ├── hot-status.json �?agent 状�? �?�? └── hot-harness.log �?运行日志 �?└────────────────────────────────────────────────────────────────────�?```
40
-
41
- ### 2.2 模块划分
42
-
43
- ```
44
- electron-ohos-hotreload/
45
- ├── bin/
46
- �? └── eohr.js CLI 入口,参数解�?+ 命令分发
47
- ├── src/
48
- �? ├── utils.js 共享工具 (BOM/JSON5/hash/ANSI)
49
- �? ├── core/
50
- �? �? ├── Config.js 配置管理 (自动探测 + .eohr.config.json)
51
- �? �? ├── HdcBridge.js hdc 命令封装 (查找/执行/文件传输)
52
- �? �? ├── Bundler.js esbuild 打包�?�? �? ├── FileWatcher.js 文件监听 (fs.watch + 轮询兜底)
53
- �? �? ├── StatusPoller.js 设备状态轮�?�? �? └── Dashboard.js 终端输出面板
54
- �? └── commands/
55
- �? ├── setup.js eohr setup �?自动配置快捷命令
56
- �? ├── init.js eohr init �?新增 agent + �?package.json
57
- �? ├── watch.js eohr watch �?热加载循�?+ 键盘交互
58
- �? ├── push.js eohr push �?单次打包推�?�? ├── status.js eohr status �?查询设备状�?�? ├── strategy.js eohr strategy �?切换重载策略
59
- �? ├── clean.js eohr clean �?恢复工程 + 清空设备
60
- �? └── log.js eohr log �?查看设备日志
61
- ├── templates/
62
- �? └── hot-reload-agent.js 设备�?agent 模板
63
- ├── docs/
64
- �? ├── design-manual.md 设计手册
65
- �? └── user-manual.md 用户使用手册
66
- └── package.json
67
- ```
68
-
69
- ---
70
-
71
- ## 3. 核心设计
72
-
73
- ### 3.1 注入方式(不碰开发者文件)
74
-
75
- Electron 启动时读 `package.json` �?`main` 字段决定加载哪个 JS 文件。`eohr init` 只做两件事:
76
-
77
- ```
78
- eohr init 做的�?
79
- 1. 新增 hot-reload-agent.js �?app 目录(不修改任何已有文件�? 2. 修改 package.json �?main 字段: "main.js" �?"hot-reload-agent.js"
80
- ```
81
-
82
- 改动清单:
83
-
84
- | 文件 | 操作 | 说明 |
85
- |------|------|------|
86
- | `hot-reload-agent.js` | **新增** | 设备�?agent |
87
- | `package.json` | **改一�?* | `main` 字段指向 agent |
88
- | `main.js` | **不碰** | 开发者的原始代码,原封不�?|
89
-
90
- Electron 启动时加�?`hot-reload-agent.js`,agent 接管后决定加载谁�?
91
- ### 3.2 设备�?Agent
92
-
93
- **文件**: `templates/hot-reload-agent.js`
94
-
95
- #### 加载优先�?
96
- ```
97
- Electron 启动 �?package.json main �?hot-reload-agent.js
98
- �? ├─ 1) /data/storage/el2/base/files/hot/entry.js (override, hdc 推送的开发者代�?
99
- �? └─ 开发模�? 加载 esbuild 打包的最新代�? �? └─ 2) ./main.js (开发者的原始入口)
100
- └─ 生产模式 / 首次运行: 加载开发者的原始代码
101
- ```
102
-
103
- - �?`entry.js` �?加载推送的代码(热加载模式�?- 没有 `entry.js` �?加载开发者的 `main.js`(生产模式,与未安装 eohr 时行为完全一致)
104
-
105
- #### 生命周期
106
-
107
- ```
108
- app.whenReady()
109
- ├─ loadConfig() 读取 hot-config.json
110
- ├─ writeStatus("agent-ready")
111
- ├─ loadEntry() 首次加载开发者代�? �? ├─ entry.js 存在 �?require(entry.js)
112
- �? └─ 不存�?�?require('./main.js')
113
- ├─ 成功 �?writeStatus("loaded")
114
- �? 失败 �?writeStatus("init-fail")
115
- └─ startWatch()
116
- ├─ fs.watch(OVERRIDE_DIR) 通道 1
117
- └─ setInterval(2000) 通道 2: 轮询兜底
118
- ```
119
-
120
- #### 重载策略
121
-
122
- | 策略 | 机制 | 耗时 | 适用 |
123
- |------|------|------|------|
124
- | **hard** | `app.quit()` �?系统重启 Ability | ~15s | 默认,推�?|
125
- | **soft** | `require.cache` 失效 + 重新 `require` | 1~3s | 无副作用的纯逻辑模块 |
126
- | **hard-first** | �?soft,失�?500ms 后回退 hard | 1~3s / 15s | 按需 |
127
-
128
- hard �?Electron 主进程热加载的业界标准做法。`electron-reload`、`electronmon` 等工具均采用杀进程重启方式,因为主进程的窗口、IPC、定时器等副作用无法通过清缓存完全回收�?
129
- **soft 重载**:
130
- ```
131
- softReload()
132
- ├─ currentModule.cleanup() (如有)
133
- ├─ 失效 require.cache (OVERRIDE_DIR 下的条目 + DEV_MAIN)
134
- ├─ loadEntry() 重新加载开发者代�? ├─ 成功 �?writeStatus("soft-ok")
135
- └─ 失败 �?writeStatus("soft-fail") �?返回 false
136
- ```
137
-
138
- **hard-first 调度**:
139
- ```
140
- reload()
141
- ├─ reloadInProgress = true 防重�? ├─ loadConfig()
142
- ├─ soft �?softReload()
143
- ├─ hard �?hardReload()
144
- ├─ hard-first:
145
- �? ├─ ok = softReload()
146
- �? ├─ ok �?完成
147
- �? └─ !ok �?setTimeout(hardReload, 500)
148
- └─ reloadInProgress = false
149
- ```
150
-
151
- #### 双通道文件监听
152
-
153
- - **通道 1**: `fs.watch(OVERRIDE_DIR)` �?监听 `.reload-trigger` �?`entry.js` 变更
154
- - **通道 2**: `setInterval(2000)` 轮询 `.reload-trigger` �?mtime �?兜底(某�?OHOS 路径 fs.watch 不可靠)
155
- - 两个通道都有 `reloadInProgress` 防重�?
156
- #### 状态上�?
157
- `hot-status.json`:
158
-
159
- | status | 含义 |
160
- |--------|------|
161
- | `agent-ready` | Agent 启动完成 |
162
- | `waiting` | 等待首次 entry.js 推�?|
163
- | `loaded` | 首次加载成功 |
164
- | `soft-reloading` | 软重载进行中 |
165
- | `soft-ok` | 软重载成�?|
166
- | `soft-fail` | 软重载失�?|
167
- | `hard-reloading` | 硬重载进行中 |
168
- | `init-fail` | 首次加载失败 |
169
-
170
- ### 3.3 主机�?Bundler
171
-
172
- **文件**: `src/core/Bundler.js`
173
-
174
- �?esbuild 将开发者的入口文件打包成自包含�?`entry.js`�?
175
- ```
176
- bundle()
177
- ├─ 解析入口文件 (config.entry, �?"web_engine/.../app/main.js")
178
- ├─ esbuild.build()
179
- �? ├─ entryPoints: [入口文件]
180
- �? ├─ bundle: true 内联解析所有依�? �? ├─ platform: "node"
181
- �? ├─ format: "cjs"
182
- �? ├─ external: ["electron", ...nodeBuiltins] 运行时提�? �? ├─ sourcemap: "inline"
183
- �? └─ write: false
184
- ├─ stripBOM(output)
185
- └─ simpleHash(code) �?{ code, hash, changed }
186
- ```
187
-
188
- **关键设计**:
189
- - `electron` 标记 external �?运行时由 Electron 提供
190
- - Node.js 内置模块 (fs/path/...) 标记 external �?运行时提�?- 项目 `node_modules` 中的依赖打进 bundle �?设备端无需 node_modules
191
- - `sourcemap: "inline"` �?便于调试
192
- - `hash` diff �?内容未变时跳过推�?
193
- ### 3.4 主机�?FileWatcher
194
-
195
- **文件**: `src/core/FileWatcher.js`
196
-
197
- | 平台 | 主通道 | 兜底 |
198
- |------|--------|------|
199
- | Windows | `fs.watch({ recursive: true })` | 轮询 (2s) |
200
- | Linux/macOS | 递归 `fs.watch` | 轮询 (2s) |
201
-
202
- - 500ms 防抖合并多文件变�?- 只监�?`.ts` / `.js` 文件
203
- - 排除 `node_modules` / `.git` / `dist` / `entry.js`
204
-
205
- **手动模式 vs auto 模式**:
206
-
207
- FileWatcher 始终监听文件变化,区别在收到变化后的行为�?
208
- | 模式 | FileWatcher 回调行为 |
209
- |------|---------------------|
210
- | 手动 (默认) | 文件名加�?`pendingChanges` 数组,终端显�?`[pending]`,等用户按触发键才推�?|
211
- | auto (`--auto`) | 直接调用 `doReloadCycle()` 打包推�?|
212
-
213
- ### 3.5 主机侧触发键
214
-
215
- **文件**: `src/commands/watch.js` 中的 `parseTriggerKey()` + `startKeyboardInput()`
216
-
217
- 手动模式下,开发者在终端按配置的组合键触发推�?重载�?
218
- **默认**: `Ctrl+Shift+X`,可�?`.eohr.config.json` �?`triggerKey` 字段配置�?
219
- **实现**:
220
- - `process.stdin.setRawMode(true)` 进入 raw 模式捕获原始按键
221
- - `parseTriggerKey()` 把配置字符串(如 `"ctrl+shift+x"`)解析为匹配函数
222
- - raw 模式�?Ctrl+字母 的编码是 `\x01`~`\x1a`,终端不区分 Shift 所�?Ctrl+Shift+X 匹配 `\x18`
223
- - �?`q` �?`Ctrl+C` 退�?
224
- **支持的格�?*:
225
-
226
- | 配置�?| 按键 |
227
- |--------|------|
228
- | `"ctrl+shift+x"` | Ctrl+Shift+X(默认) |
229
- | `"ctrl+r"` | Ctrl+R |
230
- | `"ctrl+alt+t"` | Ctrl+Alt+T |
231
- | `"f5"` | F5 功能�?|
232
- | `"space"` | 空格�?|
233
- | `"enter"` | 回车�?|
234
-
235
- ### 3.6 主机�?HdcBridge
236
-
237
- **文件**: `src/core/HdcBridge.js`
238
-
239
- **hdc 查找**: `DEVECO_SDK_HOME` �?常见路径 �?PATH
240
-
241
- **沙箱路径 vs 物理路径**:
242
-
243
- | 类型 | 格式 | hdc 可读 |
244
- |------|------|---------|
245
- | 沙箱 | `/data/storage/el2/base/files/` | �?(进程退出后) |
246
- | 物理 | `/data/app/el2/100/base/<bundle>/files/` | �?|
247
-
248
- - `hdc file send` �?物理路径
249
- - `hdc shell cat` �?物理路径
250
- - Agent 运行时写 �?沙箱路径(同一物理位置�?
251
- ### 3.7 主机�?StatusPoller
252
-
253
- **文件**: `src/core/StatusPoller.js`
254
-
255
- 每秒通过 `hdc cat` 读取 `hot-status.json`,状态变化时触发回调�?
256
- ### 3.8 主机�?Config
257
-
258
- **文件**: `src/core/Config.js`
259
-
260
- **合并优先�?*: CLI 参数 > `.eohr.config.json` > 自动探测 > 默认�?
261
- **自动探测**:
262
-
263
- | 配置 | 来源 |
264
- |------|------|
265
- | `hapRoot` | 向上�?`build-profile.json5` |
266
- | `bundleName` | `AppScope/app.json5` �?`app.bundleName` |
267
- | `appDir` | `web_engine/.../resfile/resources/app/` |
268
- | `entry` | `appDir/main.ts` �?`src/main.ts` �?默认 |
269
-
270
- ---
271
-
272
- ## 4. 数据�?
273
- ### 4.1 热加载迭代循环(手动模式�?
274
- ```
275
- 开发者保存代码文�?(�?main.js)
276
- �? �?FileWatcher 检测变�?(fs.watch 或轮�?
277
- �? �? (手动模式: 不立即推�?
278
- pendingChanges.push(file)
279
- 终端显示 [pending] main.js (�?Ctrl+Shift+X 推�?
280
- �? �? 开发者按 Ctrl+Shift+X
281
- 清空 pendingChanges
282
- �? �?Bundler.bundle()
283
- ├─ esbuild 打包开发者入口文�?�?entry.js
284
- ├─ stripBOM
285
- └─ simpleHash �?changed?
286
- ├─ unchanged �?跳过
287
- └─ changed �?继续
288
- �?HdcBridge.pushOverride(entry.js)
289
- �? hdc file send �?物理路径
290
- �?HdcBridge.touch(.reload-trigger)
291
- �? hdc shell touch
292
- �?设备�?Agent 检测到触发 (fs.watch 或轮�?
293
- �? �?Agent.reload()
294
- ├─ soft: require.cache 失效 �?loadEntry() �?require(entry.js)
295
- ├─ hard: app.quit() �?系统重启
296
- └─ hard-first: soft �?失败回退 hard
297
- �? �?开发者代码在设备上重新执�? �? �?Agent.writeStatus("soft-ok" / "soft-fail")
298
- �? �?主机�?StatusPoller 轮询 (1s)
299
- └─ Dashboard.statusUpdate() �?终端显示
300
- ```
301
-
302
- ### 4.2 auto 模式
303
-
304
- 与手动模式唯一区别:FileWatcher 回调中跳�?`pendingChanges`,直接调�?`doReloadCycle()`。保存即推送,无需按键�?
305
- ---
306
-
307
- ## 5. 容错设计
308
-
309
- ### 5.1 生产安全
310
-
311
- - �?`entry.js` �?agent 加载开发者的 `main.js`,行为与未安�?eohr 完全一�?- `hot-config.json` 不存�?�?使用默认配置
312
- - `eohr init` 不修改开发者的 `main.js`
313
-
314
- ### 5.2 可恢�?
315
- `eohr clean` 一条命令恢复工程:
316
- 1. 删除 `hot-reload-agent.js`
317
- 2. `package.json` �?`main` 改回原始�?3. 删除 `.eohr.config.json`
318
- 4. 清空设备 override 目录和状态文�?
319
- ### 5.3 BOM 处理
320
-
321
- `utils.stripBOM()` 在打�?推送时自动去除 UTF-8 BOM�?
322
- ### 5.4 防重�?
323
- Agent �?`reloadInProgress` 标志防止 fs.watch + 轮询同时触发�?
324
- ### 5.5 hash diff
325
-
326
- 内容未变时跳过推送,避免无意义重载�?
327
- ### 5.6 soft 失败兜底
328
-
329
- `hard-first` 策略�?soft 重载失败�?500ms 自动回退 hard�?
330
- ---
331
-
332
- ## 6. 配置
333
-
334
- ### 6.1 .eohr.config.json
335
-
336
- ```json
337
- {
338
- "bundleName": "com.huawei.ohos_electron",
339
- "hapRoot": "<工作区路�?/ohos_hap",
340
- "appDir": "<工作区路�?/ohos_hap/web_engine/src/main/resources/resfile/resources/app",
341
- "entry": "web_engine/src/main/resources/resfile/resources/app/main.js",
342
- "strategy": "hard",
343
- "triggerKey": "ctrl+shift+x",
344
- "watch": [
345
- "web_engine/src/main/resources/resfile/resources/app/**/*.ts",
346
- "web_engine/src/main/resources/resfile/resources/app/**/*.js",
347
- "src/**/*.ts",
348
- "src/**/*.js"
349
- ],
350
- "ignore": ["node_modules/**", "dist/**", ".git/**"],
351
- "userId": 100,
352
- "softTimeout": 5000,
353
- "pollInterval": 2000
354
- }
355
- ```
356
-
357
- | 字段 | 说明 | 默认�?|
358
- |------|------|--------|
359
- | `entry` | 开发者入口文�?| 自动探测 |
360
- | `strategy` | 重载策略 | `hard` |
361
- | `triggerKey` | 触发键(手动模式�?| `ctrl+shift+x` |
362
- | `watch` | 监听的文�?glob | 自动探测(含 app 目录 + src 目录�?|
363
- | `ignore` | 忽略的文�?glob | `["node_modules/**", "dist/**", ".git/**"]` |
364
- | `userId` | OHOS 用户 ID | `100` |
365
- | `softTimeout` | soft 重载超时 (ms) | `5000` |
366
- | `pollInterval` | 文件轮询间隔 (ms) | `2000` |
367
-
368
- ### 6.2 hot-config.json (设备�?
369
-
370
- ```json
371
- {
372
- "strategy": "hard",
373
- "softTimeout": 5000
374
- }
375
- ```
376
-
377
- 通过 `eohr strategy` / `eohr push` / `eohr watch` 时自动推送到设备�?
378
- ---
379
-
380
- ## 7. 关键路径
381
-
382
- | 路径 | 说明 | 可写�?|
383
- |------|------|--------|
384
- | `resfile/resources/app/package.json` | main 指向 agent | 只读 |
385
- | `resfile/resources/app/main.js` | 开发者原始代�?| 只读 |
386
- | `resfile/resources/app/hot-reload-agent.js` | 设备�?agent | 只读 |
387
- | `/data/storage/el2/base/files/hot/` | override 目录 (沙箱) | 可写 |
388
- | `/data/app/el2/100/base/<bundle>/files/hot/` | override 目录 (物理) | 可写 |
389
- | `/data/storage/el2/base/files/hot-status.json` | Agent 状�?| 可写 |
390
- | `/data/storage/el2/base/files/hot-harness.log` | 运行日志 | 可写 |
391
-
392
- ---
393
-
394
- ## 8. 性能模型
395
-
396
- | 阶段 | soft | hard |
397
- |------|------|------|
398
- | 文件检�?| <100ms / �?s | 同左 |
399
- | 防抖 (auto 模式) | 500ms | 500ms |
400
- | esbuild 打包 | 20~700ms | 同左 |
401
- | hdc file send | 1~2s | 1~2s |
402
- | touch trigger | <500ms | <500ms |
403
- | 设备检测触�?| <100ms / �?s | 同左 |
404
- | require.cache 失效 | <10ms | �?|
405
- | require(entry.js) | 500ms~2s | �?|
406
- | app.quit + 重启 | �?| 5~10s |
407
- | **总计** | **~3s** | **~15s** |
408
-
409
- 手动模式下额外等待开发者按触发键的时间,不计入迭代耗时�?
410
- ---
411
-
412
- ## 9. 恢复方式
413
-
414
- `eohr clean` 自动完成�?
415
- ```
416
- eohr clean
417
- ├─ 删除 hot-reload-agent.js
418
- ├─ package.json main �?"main.js" (�?.eohr.config.json �?entry 推导)
419
- ├─ 删除 .eohr.config.json
420
- └─ 清空设备 override 目录 + 状态文�?```
421
-
422
- 跑完后重�?HAP 即可。工程恢复到 `eohr init` 之前的状态,开发者的 `main.js` 从头到尾没被动过�?
423
- ---
424
-
425
- ## 10. 文件清单
426
-
427
- | 文件 | 行数 | 职责 |
428
- |------|------|------|
429
- | `bin/eohr.js` | 116 | CLI 入口,参数解�?+ 命令分发 |
430
- | `src/utils.js` | 93 | 共享工具 (BOM/JSON5/hash/ANSI) |
431
- | `src/core/Config.js` | 159 | 配置管理,自动探�?|
432
- | `src/core/HdcBridge.js` | 133 | hdc 封装,三级查�?|
433
- | `src/core/Bundler.js` | 72 | esbuild 打包,external 策略 |
434
- | `src/core/FileWatcher.js` | 170 | fs.watch + 轮询兜底,防�?|
435
- | `src/core/StatusPoller.js` | 59 | 状态轮询,事件回调 |
436
- | `src/core/Dashboard.js` | 108 | 终端彩色输出 |
437
- | `src/commands/setup.js` | 155 | 自动配置快捷命令 (跨平�? |
438
- | `src/commands/init.js` | 76 | 新增 agent + �?package.json |
439
- | `src/commands/watch.js` | 248 | 热加载循�?+ 键盘交互 + 触发�?|
440
- | `src/commands/push.js` | 78 | 单次打包推�?|
441
- | `src/commands/status.js` | 50 | 设备状态查�?|
442
- | `src/commands/strategy.js` | 55 | 策略切换 |
443
- | `src/commands/clean.js` | 80 | 恢复工程 + 清空设备 |
444
- | `src/commands/log.js` | 30 | 查看设备日志 |
445
- | `templates/hot-reload-agent.js` | 157 | 设备�?agent |