Hippy 调试原理
Hippy 是直接运行于手机的 JS 引擎中的,在 Android 上使用 WebSocket 通过 Chrome DevTools Protocol 与电脑上的 Chrome 进行通讯调试,而 iOS 上使用内置 的 JavaScriptCore 与 Safari 连接进行调试,在较新的 Hippy 版本 iOS 也可以使用 Chrome DevTools 进行调试。
Hippy 中运行的 JS 代码可以来源于本地文件(local file),或者远程服务地址(server)。
@hippy/debug-server-next 就是为了解决调试模式下终端模式获取调试用 JS 文件,以及将 Chrome DevTools Protocol 传输回调试器而诞生。
项目初始化
-
运行
git clone https://github.com/Tencent/Hippy.git!> Hippy 仓库使用 git-lfs 来管理 so, gz, otf, png, jpg 文件, 请确保你已经安装 git-lfs。
-
项目根目录运行命令
npm install安装前端依赖。 -
项目根目录运行命令
npx lerna bootstrap安装前端每一个 package 依赖。(Hippy 采用 Lerna 管理多JS仓库) -
项目根目录运行命令
npm run build编译前端 SDK 包。 -
选择一个前端范例项目来进行编译,项目根目录运行
npm run buildexample [hippy-react-demo|hippy-vue-demo]。
终端环境准备
我们推荐在终端代码中留一个后门,通过一定条件触发后进入调试模式,具体代码可以参考 iOS 和 Android,这里实现了一个 TestModule,当前端调用它的 debug 或 remoteDebug 方法时就会进入调试模式,而终端可以通过其它方式进入。终端打开 Hippy Debug 页面代码如下:
-
Android:
// 初始化 hippy 引擎 HippyEngine.EngineInitParams initParams = new HippyEngine.EngineInitParams(); // 可选:是否设置为 debug 模式,默认为 false。设置 true 为调试模式,所有 jsbundle 都将从 debug server 上下载 initParams.debugMode = true; initParams.debugServerHost = "localhost:38989"; // 可选参数 Hippy Server 的 jsbundle 名字,默认为 "index.bundle"。debugMode = true 时有效 initParams.debugBundleName = "index.bundle"; -
iOS:
- (void)viewDidLoad { // 开启调试 NSDictionary *launchOptions = @{@"DebugMode": @(YES)}; // 使用默认 http://localhost:38989/index.bundle NSString *bundleStr = [HippyBundleURLProvider sharedInstance].bundleURLString; NSURL *bundleUrl = [NSURL URLWithString:bundleStr]; HippyBridge *bridge = [[HippyBridge alloc] initWithDelegate:self bundleURL:bundleUrl moduleProvider:nil launchOptions:launchOptions executorKey:@"Demo"]; } - (BOOL)shouldStartInspector:(HippyBridge *)bridge { return bridge.debugMode; } - (NSURL *)inspectorSourceURLForBridge:(HippyBridge *)bridge { return bridge.bundleURL; } -
Ohos:
let initParams = new EngineInitParams(this.libHippy!, this.abilityContext!, this.getUIContext()) // 是否设置为 debug 模式,默认为 false。设置 true 为调试模式,所有 jsbundle 都将从 debug server 上下载 initParams.debugMode = true; initParams.debugServerHost = "localhost:38989"; // usb线调试时,这里设置localhost即可 // initParams.debugServerHost = "192.168.76.25:38989"; // 网络调试时,这里请设置正确 JS Server 的 IP
Hippy鸿蒙版本支持 JSVM 和 V8 两个JS引擎,JSVM 性能更好所以默认使用JSVM,不过可以自由切换。
- 鸿蒙调试JS引擎使用JSVM和V8都可以
- 鸿蒙调试请使用Debug包
Debug包默认打开了ENABLE_INSPECTOR宏,使得调试功能生效。即:Hippy/framework/ohos/build-profile.json5 里配置了:"arguments": "-DENABLE_INSPECTOR=true"
鸿蒙上JSVM调试限制说明
默认会使用JSVM进行调试,由于JSVM提供的调试接口限制,特别说明:
- 所有需要主动执行JS调试命令的地方,都需要页面上JS执行来触发,比如:点击某个按钮处理响应事件触发,滚动后处理响应事件触发,等等。这些场景如下:

如需切换到V8进行调试,请修改:
- Hippy/driver/js/CMakeLists.txt 里:打开 set(JS_ENGINE "V8") 注释 set(JS_ENGINE "JSH")
鸿蒙上usb线调试限制说明
由于鸿蒙上没有提供hdc实时监听手机拔插的接口,usb调试时需要先插着手机再启动调试server(启动调试server时会做手机端口到PC端口的映射)。 如果先启动了调试server,再插上手机,可以手动如下命令进行端口映射。
hdc rport tcp:端口 tcp:端口
端口限制说明
有些公司网络会有限制,公司网络限制可能端口限制需要改端口,可能手机和电脑不同网,具体咨询IT部门。个人热点一般无限制。
修改端口需要改2个地方:
- 前端包scripts/hippy-webpack.dev.js里 devServer - remote - port 端口修改;(影响电脑端Http server的服务端口)
- 客户端连接端口修改;(影响手机端连接)
前端环境准备
-
安装新一代调试工具:
npm i -D @hippy/debug-server-next@latest -
修改 Webpack 配置,添加调试服务地址,默认为
http://localhost:38989module.exports = { devServer: { // 调试服务地址 remote: { protocol: 'http', // iOS 真机调试时配置为本地局域网 IP // iOS 模拟器和安卓真机调试时配置为 localhost // 远程调试时配置为远程服务器 IP 或域名 host: '192.168.1.100', // 调试服务端口 port: 38989, }, // 默认为 false,设为 true 调试服务支持多个工程同时调试,彼此之间不会干扰 multiple: false, // 默认为 false,hippy vue 项目可以手动开启 vueDevtools: false, // 默认 hot, liveReload 都为 true,如果只想使用 live-reload 功能,请将 hot 设为 false,liveReload 设为 true hot: true, liveReload: true, client: { overlay: false, }, }, // ... other config } -
修改
package.json中的启动编译命令。如果业务通过自定义 cli 启动,参考 打包编译 API 进行配置{ "scripts": { // -c 或 --config 提供 webpack config 配置路径 "hippy:dev": "node ./scripts/env-polyfill.js hippy-dev -c ./scripts/hippy-webpack.dev.js" } }!> Node 17+ 不再支持
md4hash,此处为了兼容 Webpack 的 hash 算法,暂时通过env-polyfill.js脚本判断环境来解决,若出现错误将node ./scripts/env-polyfill.js移除即可 -
运行
npm run hippy:dev启动编译并按需开启用于HMR和Live-Reload的 Dev Server,编译结束后打印出 bundleUrl 和调试首页地址
-
粘贴 bundleUrl 并点击开始按钮
-
使用调试器开始调试
-
Safari DevTools:在 Mac 上打开 Safari 的开发菜单(
预置->高级->显示开发菜单),然后按下图指引开始调试。Safari 调试器支持 iOS 设备,支持HMR & Live-Reload, Log, Sources, Memory等能力。
-
Chrome DevTools:访问第 4 步打印的调试首页地址开始调试。Chrome 调试器支持 Android & iOS & Ohos 设备,支持
HMR & Live-Reload, Elements, Log, Sources, Memory等能力。
如果不使用我们的调试主页,也可以主动在
chrome://inspect打开 DevTools,首先确保Discover USB devices的复选框呈未选中状态,然后确保Discover network targets选中,并在右侧Configure按钮的弹窗中包含了localhost:38989调试服务地址,下方的Remote Target中应该会出现Hippy debug tools for V8字样,点击下方的inspect链接即可打开 Chrome 调试器。

-
调试 Javascript
尽管 Hippy 是前端框架,但依然运行在终端中,如果终端提供了后门可以直接链接调试服务,那可以直接用终端后门连接终端进行调试。
这里仅以官方范例为准,讲述如何进行调试。
!> 需要注意的是:官方范例为应用最新功能,将 @hippy/react 和 @hippy/vue 做了 alias 到 packages 目录,如果调试官方范例,需要先在 Hippy 项目根目录下运行 npm run build 编译前端 SDK;或者删除范例的 scripts 目录中对 packages 的 alias。
iOS
iOS 调试支持模拟器和真机两种方式,由于 JSBundle 和调试协议依赖网络传输,真机调试时需要确保手机与开发机在同一个局域网内,因此我们推荐使用模拟器调试。
模拟器调试
- 点击 Xcode on Mac AppStore 下载安装 Xcode。
- 使用 Xcode 打开Hippy iOS 范例工程 中的
HippyDemo.xcodeproj工程文件,并点击运行,正常情况下应该可以启动模拟器,并运行之前内置的 Hippy 前端代码。 - 打开
examples下的前端范例工程 hippy-react-demo 或者 hippy-vue-demo,通过npm i安装完依赖之后,使用npm run hippy:dev启动编译和调试服务。 - 回到模拟器,粘贴 bundleUrl 并启动调试
- 当 JS 源码文件发生改动时,如已开启 HMR 或 Live-Reload,编译结束后会自动刷新;否则需要按
Command + R或Command + D键调起 Reload 面板刷新
如果
Command + D无法调起面板,可以点击Device->Shake强制调起 Reload 面板
真机调试
-
iOS 真机调试只支持 XCode 编译的 App,并且 iOS 设备上需要开启 JavaScript 调试和 Web 检查器选项
-
确保 iOS 设备和调试服务处于同一局域网内
-
编译 App,粘贴 bundleUrl 并启动调试
!> 注意:真机调试时必须保证开发机和手机处于同一局域网内,否则会加载 JSBundle 失败。以下两种情况都不是同一局域网:
(a) 开发机和手机分别连接不同的网络环境;
(b) 开发机连接网线,手机连接 WiFi。
Android
Android 使用了 adb 的端口映射功能,解决了真机到开发机的通讯问题。由于 ARM 模拟器运行效率问题,更加推荐使用真机进行调试。
具体流程:
- 下载安装 Android Studio。
- 通过 Android Studio 直接打开 Hippy 项目根目录,即可加载 Hippy Android 范例工程
- 通过数据线插上 Android 手机,并在 Android Studio 中点击运行,正常情况下手机应该已经运行起
Hippy Demoapp。 - 回到手机上,首先确保手机的
USB 调试模式已经打开 -- 一般在关于手机页面里连续点击Build可以进入开发者模式,再进入开发者模式界面后打开USB 调试模式。 - 执行
adb reverse --remove-all && adb reverse tcp:38989 tcp:38989确保 38389 端口不被占用。 - 打开前端范例工程 hippy-react-demo 或者 hippy-vue-demo,通过
npm i安装完依赖之后,使用npm run hippy:dev启动编译和调试服务。 - 回到手机上,粘贴 bundleUrl 并启动调试
- 当 JS 源码文件发生改动时,如已开启 HMR 或 Live-Reload,编译结束后会自动刷新;否则需要按
Command + R或Command + D键调起 Reload 面板刷新
Ohos
鸿蒙调试目前只支持网络调试(手机和JS Server在一个网络内,通过网络下载JS Bundle调试),数据线调试还在开发中。
Elements 可视化审查
Android SDK 最低支持版本 2.9.0
iOS SDK 最低支持版本 2.11.5
Hippy 实现了节点和属性从前端到终端的映射,可以在 Chrome DevTools 上进行 Elements 的可视化检查。
HMR & Live-Reload 能力
最低支持版本 2.12.0

!> 请勿在生产环境引入 HMR 相关的配置
当开发者修改了前端代码后,我们可以通过 Hot Module Replacement (HMR) 保留状态刷新组件视图,或通过 live-reload 重载业务实例,步骤如下:
Hippy-Vue
-
安装热更新依赖
npm i @hippy/vue@^2.12.0 npm i -D @hippy/debug-server-next@latest @hippy/vue-loader @hippy/vue-css-loader -
webpack 配置示例
const VueLoaderPlugin = require('@hippy/vue-loader/lib/plugin'); const vueLoader = '@hippy/vue-loader'; module.exports = { devServer: { // 默认 hot, liveReload 都为 true,如果只想使用 live-reload 功能,请将 hot 设为 false,liveReload 设为 true hot: true, liveReload: true, client: { // 暂不支持错误提示蒙层 overlay: false, }, }, plugins: [ new VueLoaderPlugin(), // add other plugin ... ], module: { rules: [ { test: /\.vue$/, use: [ vueLoader, ], }, ], // add other loaders ... } } -
package.json 配置:
{ "scripts": { // -c 或 --config 提供 webpack config 配置路径 "hippy:dev": "node ./scripts/env-polyfill.js hippy-dev -c ./scripts/hippy-webpack.dev.js" } } -
启动开发:
npm run hippy:dev -
如果安卓设备断连,需要手动用 adb 转发端口:
adb reverse tcp:38989 tcp:38989。 -
iOS 的热更新:iOS 设备需要代理到开发机上,或处于同一网段,才能使用 HMR 能力。Webpack 配置修改如下所示,对于模拟器,本就和开发机处于同一网段,IP 写
localhost就能访问到。module.exports = { devServer: { host: '<your_ip_or_localhost_with_proxy>', }, }
Hippy-React
-
安装热更新依赖
npm i @hippy/react@^2.12.0 npm i -D @hippy/debug-server-next@latest @hippy/hippy-react-refresh-webpack-plugin react-refresh -
webpack 配置示例
const ReactRefreshWebpackPlugin = require('@hippy/hippy-react-refresh-webpack-plugin'); module.exports = { devServer: { // 默认 hot, liveReload 都为 true,如果只想使用 live-reload 功能,请将 hot 设为 false,liveReload 设为 true hot: true, liveReload: true, client: { // 暂不支持错误提示蒙层 overlay: false, }, }, plugins: [ new ReactRefreshWebpackPlugin({ // 暂不支持错误提示蒙层 overlay: false, }), ], module: { rules: [ { test: /\.(jsx?)$/, use: [ { loader: 'babel-loader', options: { sourceType: 'unambiguous', presets: [ '@babel/preset-react', [ '@babel/preset-env', { targets: { chrome: 57, ios: 9, }, }, ], ], plugins: [ ['@babel/plugin-proposal-class-properties'], ['@babel/plugin-proposal-decorators', { legacy: true }], ['@babel/plugin-transform-runtime', { regenerator: true }], // add react-refresh babel plugin require.resolve('react-refresh/babel'), ], }, }, ], }, // other loader ... ], }, }; -
package.json 配置:
{ "scripts": { // -c 或 --config 提供 webpack config 配置路径 "hippy:dev": "node ./scripts/env-polyfill.js hippy-dev -c ./scripts/hippy-webpack.dev.js" } } -
执行
npm run hippy:dev命令。 -
如果安卓设备断连,需要手动用adb转发端口:
adb reverse tcp:38989 tcp:38989。 -
iOS的热更新:iOS 设备需要代理到开发机上,或处于同一网段,才能使用 HMR 能力。Webpack 配置修改如下所示,对于模拟器,本就和开发机处于同一网段,IP 写
localhost就能访问到。module.exports = { devServer: { host: '<your_ip_or_localhost_with_proxy>', }, }
Vue Devtools
最低支持版本 2.13.7
支持调试 Vue 组件树、组件状态、路由、store、以及事件性能等
使用配置:
-
安装 vue devtools 依赖:
npm i @hippy/vue@^2.13.7 @hippy/vue-router@^2.13.7 npm i @hippy/debug-server-next@latest -D -
开启 vue devtools
module.exports = { devServer: { remote: { protocol: 'https', host: 'devtools.qq.com', port: 443, }, // 默认为 false,开启后将通过 remote 字段指定的远程调试服务分发 vue 调试指令 vueDevtools: true }, }
!> Vue Devtools 的配置会在业务运行时中注入调试代码,可能会有一定的性能影响,请勿在生产环境引入。
React Devtools
客户端最低支持版本 2.13.7
前端最低支持版本 2.14.0
支持调试 React 组件树、组件状态、路由以及性能等
使用配置:
-
安装 react devtools 依赖:
npm i @hippy/react@^2.14.0 npm i @hippy/debug-server-next@latest -D -
开启 react devtools
module.exports = { devServer: { remote: { protocol: 'https', host: 'devtools.qq.com', port: 443, }, // 默认为 false,开启后将通过 remote 字段指定的远程调试服务分发 react 调试指令 reactDevtools: true }, module: { rules: [ { test: /\.(jsx?)$/, // 必须添加下面这一行,让 babel 忽略 react-devtools 插件 exclude: /@hippy\/hippy-react-devtools-plugin/, use: [ { loader: 'babel-loader', options: { sourceType: 'unambiguous', presets: [ '@babel/preset-react', [ '@babel/preset-env', { targets: { chrome: 57, ios: 9, }, }, ], ], plugins: [ ['@babel/plugin-proposal-class-properties'], ['@babel/plugin-proposal-decorators', { legacy: true }], ['@babel/plugin-transform-runtime', { regenerator: true }], require.resolve('react-refresh/babel'), ], }, }, ], }, ], }, }
!> React Devtools 的配置会在业务运行时中注入调试代码,可能会有一定的性能影响,请勿在生产环境引入。
打包编译 API
@hippy/debug-server-next 除了提供 bin 命令 hippy-debug 和 hippy-dev 进行调试构建,还提供了接口供自定义的 CLI 工具封装时调用,使用方法如下:
const { webpack } = require('@hippy/debug-server-next');
// 开始 webpack 编译,支持 HMR 等能力
webpack(webpackConfig, (err, stats) => {
// 处理 webpack 打包回调信息
});
远程调试
本地调试存在两个痛点:
- 无法覆盖所有机型,测试反馈的问题难以定位;
- 无法摆脱数据线的束缚。
那么这些场景我们可以考虑使用远程调试,效果预览:
前端接入配置
-
安装新一代调试工具:
npm i -D @hippy/debug-server-next@latest -
修改 Webpack 配置,添加
remote字段来配置编译产物上传地址和调试服务地址(默认为 http://127.0.0.1:38989 )。考虑到安全因素,官方不提供公网的远程调试服务,你需要自己私有化部署。module.exports = { devServer: { // 远程调试地址,需要配置为你的私有化调试服务地址 remote: { protocol: 'https', host: 'devtools.qq.com', port: 443, // 配置宿主 App 扫码加载的 scheme,如无需扫码,可不配置 qrcode: (bundleUrl) => { // 必须指定业务 bundleName const bundleName = 'QQGroupGameRank'; return `mqqapi://hippy/remoteDebug?bundleName=${bundleName}&bundleUrl=${encodeURIComponent(bundleUrl)}`; } }, client: { overlay: false, }, }, // other config ... }!> 配置远程调试时编译产物将上传远端,并在调试结束后删除。为以防万一,请确保代码中不含敏感信息(如密钥等)。
!> 远程调试时,
publicPath将被设为${protocol}://${host}:${port}/<hash>/,以区分不同的业务。!> 业务加载远程 js bundle 分包时,如未配置
customChunkPath,将默认使用publicPath的地址,请确保远程分包也同时上传到调试服务器。 -
启动编译:
npm run hippy:dev,编译结束后将打印调试信息:
其中打印三个字段表示:
- bundleUrl:远程调试的 JSBundle 地址,填入宿主 App 接入的
remoteServerUrl字段中 - debug page:PC 端调试首页
- bundleUrl scheme:宿主 App 扫码的 scheme
- bundleUrl:远程调试的 JSBundle 地址,填入宿主 App 接入的
宿主 App 接入配置
宿主 App 设置 debugMode 为 true,并把前端 webpack 生成远程无线调试的 bundleUrl 传入,推荐宿主使用输入框或扫描二维码的方式传入。
-
Android:
// 初始化 hippy 引擎 HippyEngine.EngineInitParams initParams = new HippyEngine.EngineInitParams(); initParams.debugMode = true; initParams.remoteServerUrl = ""; // 远程调试 bundleUrl -
iOS:
- (void)viewDidLoad { // 开启调试 NSDictionary *launchOptions = @{@"DebugMode": @(YES)}; NSString *bundleStr = ""; // 远程调试 bundleUrl NSURL *bundleUrl = [NSURL URLWithString:bundleStr]; HippyBridge *bridge = [[HippyBridge alloc] initWithDelegate:self bundleURL:bundleUrl moduleProvider:nil launchOptions:launchOptions executorKey:@"Demo"]; } - (BOOL)shouldStartInspector:(HippyBridge *)bridge { return bridge.debugMode; } - (NSURL *)inspectorSourceURLForBridge:(HippyBridge *)bridge { return bridge.bundleURL; }
远程调试支持能力列表
最低支持版本 2.13.1
| 平台 | HMR & Live-Reload | React Devtools | Vue Devtools | Elements | Log | Sources | Memory |
|---|---|---|---|---|---|---|---|
| Android | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| iOS | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
框架日志输出
无论是 hippy-react 还是 hippy-vue 都将和终端通讯的信息进行输出,包含了前终端的节点操作、事件收发。这些日志对于业务调试其实很有帮助,可以让开发了解到前端框架是如何将代码转译成终端可以理解的语法。当遇到问题时应先检查框架通信日志,基本可以定位到大部分问题。
如果需要关闭日志,可以在 hippy-react 的 new Hippy 启动参数中增加 silent: true,或者 hippy-vue 项目的入口文件中,开启 Vue.config.silent = true;。
