鸿蒙pc:Hoppscotch-hoppscotch-ohos适配全记录

一、写在前面

开源地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_hoppscotch

欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper

环境搭建文章:https://blog.csdn.net/lbcyllqj/article/details/161286249?sharetype=blogdetail\&sharerId=161286249\&sharerefer=PC\&sharesource=lbcyllqj\&spm=1011.2480.3001.8118

这篇文章记录的是 Hoppscotch 在 OpenHarmony / HarmonyOS Electron 运行环境中的一次适配实践。

Hoppscotch 本身是一个开源 API 开发生态工具,核心能力包括 REST、GraphQL、WebSocket、集合、环境变量、历史记录等。它的核心体验主要运行在 Web 层,项目本身也提供了 selfhost web 产物。因此这次适配选择了一条更稳妥的路线:

将 Hoppscotch 的 selfhost web 产物放进鸿蒙 Electron 壳,形成完整的本地 HAP 应用体验。

这种方式的优势是明显的:Hoppscotch 的核心 API 调试体验本来就在 Web 层完成,鸿蒙侧需要把静态资源加载、运行时环境变量注入、外部链接处理和 HAP 构建流程完整打通。

本文会按迁移过程来拆解:

  1. 原始项目是什么结构
  2. 为什么选择 Web 静态产物承载路线
  3. 鸿蒙 HAP 工程如何接入
  4. 构建脚本做了哪些关键处理
  5. 适配过程中最大的困难是什么,如何解决
  6. 已经完成哪些能力

这里直接给出结论:这次迁移已经给 Hoppscotch 的核心 API 调试体验提供了稳定的鸿蒙运行容器。真正复杂的地方集中在 Web kernel、运行时配置、请求链路和数据模型上,鸿蒙侧适配完成,这些核心能力已经可以在 HAP 中完整承载。

所以整个过程里我基本遵循了一个原则:保持 Hoppscotch 原有业务逻辑稳定,把工程入口、资源路径和运行时配置处理干净。这样 REST、GraphQL、WebSocket、集合、环境变量、历史记录等能力都可以沿着原有 Web kernel 在鸿蒙环境中运行。

这个过程看起来有点"绕",但实际适配时非常省时间。鸿蒙 Electron 应用的运行链路横跨 HAP、Electron 主进程、静态资源、Vite 产物和业务初始化,把入口收窄之后,整个工程更容易稳定下来。


二、项目背景

Hoppscotch 是一个比较典型的现代前端 monorepo 项目,仓库里包含多个 package:

  • packages/hoppscotch-selfhost-web
  • packages/hoppscotch-common
  • packages/hoppscotch-kernel
  • packages/hoppscotch-desktop
  • packages/hoppscotch-backend
  • packages/hoppscotch-cli

项目根目录使用 pnpm 管理工作区,构建链路基于 Vite 和现代前端工具链。

Hoppscotch 的核心功能本身就围绕 Web 应用组织。也就是说,它可以先通过 selfhost-web 产物跑起来,再由鸿蒙 Electron runtime 提供一个本地窗口容器。

这次适配的关键判断就是:

以 Hoppscotch 的 Web kernel 为核心,把 API 调试体验完整承载到鸿蒙窗口中。

这样可以覆盖最核心的 API 调试链路,同时让 HAP 工程、资源同步、运行时配置和窗口行为都形成完整闭环。


三、总体变化概览

本次适配主要新增了三类内容。

3.1 鸿蒙 HAP 工程

新增目录:

text 复制代码
ohos_hap/
├── AppScope/
├── electron/
├── web_engine/
└── build-profile.json5

其中 web_engine/src/main/resources/resfile/resources/app 是鸿蒙侧 Electron runtime 最终读取应用资源的位置。

适配后的资源结构大致是:

text 复制代码
resources/app/
├── main.js
├── package.json
└── dist/
    ├── index.html
    └── assets/

3.2 OpenHarmony 构建脚本

项目根目录新增了两个关键脚本:

text 复制代码
scripts/build-ohos-package.cjs
scripts/build-ohos-hap.cjs

同时在 package.json 中增加:

json 复制代码
{
  "build:ohos": "node scripts/build-ohos-package.cjs",
  "ohos:sync": "OHOS_HOPPSCOTCH_OUT=ohos_hap/web_engine/src/main/resources/resfile/resources/app pnpm run build:ohos",
  "ohos:build": "node scripts/build-ohos-hap.cjs"
}

这三条命令分别负责:

  • 构建或复用 Hoppscotch selfhost web 产物
  • 同步资源到鸿蒙 HAP 工程
  • 调用 ohpm installhvigor assembleHap 生成 HAP

3.3 Electron 启动引导

适配脚本会在资源目录下写入一个轻量 main.js,职责很明确:

  • 注入 HOPPSCOTCH_OPENHARMONY=1
  • 默认启用 GPU 兼容配置
  • 创建 BrowserWindow
  • 使用 win.loadFile(path.join(__dirname, 'dist/index.html')) 加载本地页面
  • 对外部链接使用 shell.openExternal

这个入口负责承载 Hoppscotch Web 产物,让窗口创建、本地页面加载和外部链接处理都集中在鸿蒙 Electron runtime 中。


四、原始项目直接跑鸿蒙会遇到什么问题

Hoppscotch 原始仓库并不是为鸿蒙 Electron HAP 准备的,它默认面对的是 Web 部署或官方桌面端环境。

如果直接把 Web 构建产物塞进 file:// 环境,常见问题会有三类。

4.1 根路径资源不兼容

Web 项目在普通服务器部署时,资源路径经常是这样的:

html 复制代码
<script src="/assets/index.xxx.js"></script>
<link href="/assets/index.xxx.css">

但在鸿蒙 Electron 的本地 file:// 加载环境中,根路径 /assets/... 并不等价于 dist/assets/...。结果就是:

  • index.html 能打开
  • JS / CSS 加载失败
  • 页面空白或样式丢失

4.2 Web Manifest 中的根路径

Hoppscotch 的 Web 产物里可能包含 manifest.webmanifest。如果里面的 start_urlidsrc 等字段仍然使用 / 开头,也会对本地加载造成干扰。

4.3 运行时环境变量

Hoppscotch selfhost web 依赖一组 VITE_ 运行时配置,例如:

  • VITE_BASE_URL
  • VITE_BACKEND_GQL_URL
  • VITE_BACKEND_WS_URL
  • VITE_BACKEND_API_URL
  • VITE_APP_TOS_LINK
  • VITE_APP_PRIVACY_POLICY_LINK

在普通 Web 部署中,这些变量可以由部署环境或构建过程注入。放到鸿蒙本地静态文件之后,就必须在构建脚本里显式处理。


五、鸿蒙适配核心路径

5.1 第一步:选择 selfhost web 作为承载目标

本次选择:

text 复制代码
packages/hoppscotch-selfhost-web

原因是:

  • Web 端功能覆盖 API 调试主路径
  • 静态产物更容易进入鸿蒙 Electron runtime
  • 资源路径和 HAP 承载边界清晰
  • UI、路由、请求、集合、环境等核心体验可以完整进入鸿蒙窗口

这一步的本质是降低迁移入口复杂度。

5.2 第二步:构建脚本检查资源路径

scripts/build-ohos-package.cjs 里有一个重要判断:

js 复制代码
const hasRootRelativeAssets = file => {
  const html = fs.readFileSync(file, 'utf8');
  return /(?:src|href|content)="\/(?:assets|favicon\.ico|icon\.png|manifest\.webmanifest)/.test(html);
};

如果发现 dist/index.html 里还有根路径资源,脚本会强制重新构建。

这一步解决的是:

避免把一个只能在 Web server 下工作的产物,误同步进鸿蒙 HAP。

5.3 第三步:处理 Manifest 兼容

脚本还会检查 manifest.webmanifest 中是否存在不适合鸿蒙本地加载的根路径:

js 复制代码
const hasOhosIncompatibleManifest = () => {
  return /"(?:(?:start_url|id|url|src)":"\/)/.test(content);
};

如果存在这类内容,也会触发重新构建。

5.4 第四步:注入运行时环境变量

脚本内置了一组默认运行时配置:

js 复制代码
const defaultRuntimeEnv = {
  VITE_BASE_URL: 'https://hoppscotch.io',
  VITE_SHORTCODE_BASE_URL: 'https://hopp.sh',
  VITE_BACKEND_GQL_URL: 'https://api.hoppscotch.io/graphql',
  VITE_BACKEND_WS_URL: 'wss://api.hoppscotch.io/graphql',
  VITE_BACKEND_API_URL: 'https://api.hoppscotch.io/v1',
  VITE_PROXYSCOTCH_ACCESS_TOKEN: ''
};

同步阶段会把 import_meta_env_placeholder 替换成真实的 globalThis.import_meta_env

这一步非常关键,因为 Hoppscotch 不是一个纯静态展示页,它启动后需要知道后端 GraphQL、WebSocket、API URL 等运行参数。

5.5 第五步:写入鸿蒙 Electron 启动文件

脚本生成的 main.js 只做必要工作:

  • 创建窗口
  • 设置尺寸
  • 使用兼容的沙箱配置
  • 加载本地 dist/index.html
  • 拦截新窗口打开行为

窗口配置大致如下:

js 复制代码
const win = new BrowserWindow({
  width: 1280,
  height: 800,
  minWidth: 960,
  minHeight: 640,
  title: 'Hoppscotch',
  backgroundColor: '#0f172a',
  webPreferences: {
    nodeIntegration: false,
    contextIsolation: true,
    sandbox: false
  }
});

这里保持 nodeIntegration: false 是一个合适的选择:Hoppscotch Web 端不需要直接访问 Node,可以让 renderer 层保持清晰的 Web 运行模型。

5.6 第六步:把"可复用产物"和"鸿蒙运行目录"分开

适配脚本没有直接把 Hoppscotch 的源码目录当成 HAP 运行目录,而是把它拆成两层:

text 复制代码
packages/hoppscotch-selfhost-web/dist
ohos_hap/web_engine/src/main/resources/resfile/resources/app

前者是 Hoppscotch 自己的 Web 构建结果,后者是鸿蒙 Electron runtime 真正读取的应用资源。这个拆分看起来只是多了一次复制,但好处很明显:

  • 可以单独判断 Web 产物是否健康
  • 可以在同步阶段做路径、manifest、环境变量的二次处理
  • HAP 工程里只放最终运行需要的内容
  • 更换构建参数时不会污染原始源码结构

我更倾向于把 resources/app 看成最终运行包的资源入口。凡是进入这个目录的东西,都应该是鸿蒙 Electron 能直接消费的资源。

5.7 第七步:环境变量不要散落在各处

Hoppscotch 的配置项不少,如果每遇到一个缺失变量就在代码里临时补一个默认值,文章和项目都会很快变乱。现在的做法是把默认配置集中在 defaultRuntimeEnv,再允许外部真实的 VITE_ 环境变量覆盖。

这有两个实际价值。

第一,普通开发者直接执行 pnpm run ohos:sync 时,至少能拿到一个可启动的默认包,不需要先理解 Hoppscotch 后端所有部署细节。

第二,如果接入私有化 Hoppscotch 后端,只需要在构建环境里传入对应的 VITE_BACKEND_GQL_URLVITE_BACKEND_WS_URLVITE_BACKEND_API_URL,不用再改脚本源码。

这也是我觉得比较舒服的一点:脚本里有默认值,但没有把部署场景写死。


六、问题困难解决

这次 Hoppscotch 适配中最大的困难集中在 Web 产物的本地运行环境上:

如何让一个原本面向 Web server 的现代 Vite 产物,在鸿蒙 Electron 的 file:// 本地环境里稳定启动。

这个问题表面上看只是"路径不对",但实际会连带出三层问题。

6.1 困难一:根路径资源兼容

如果产物里仍然保留 /assets/...,鸿蒙本地加载时就会找不到资源。

典型表现是:

  • 应用窗口能打开
  • 标题栏正常
  • 页面区域无法加载完整内容
  • 日志里可能只有资源加载失败,或者根本不明显

解决方式是让构建脚本主动扫描 index.html,发现根路径资源就重新构建,并在同步后再次检查。如果同步后的 dist/index.html 仍然不符合要求,脚本直接抛错,不允许继续打包。

这比打完包再到设备侧反复定位资源问题可靠得多。

6.2 困难二:运行时环境变量不能丢

Hoppscotch 启动后需要后端地址、WebSocket 地址、隐私协议链接等配置。普通 Web 部署可以靠环境变量注入,但本地 HAP 资源不能假设部署平台会帮我们处理。

解决方式是在 build-ohos-package.cjs 中集中维护 defaultRuntimeEnv,并允许外部 VITE_ 环境变量覆盖。最终把配置写入:

js 复制代码
globalThis.import_meta_env = {...}

这样 HAP 内的静态页面启动时就能拿到完整运行时配置。

6.3 困难三:桌面端原生能力需要统一收口

Hoppscotch 的桌面端能力涉及更多原生运行假设。鸿蒙适配中把这些能力统一收口到 Electron runtime 的窗口承载、外部链接处理和 HAP 资源管理里。

处理方式是:

  1. Web kernel 负责 API 调试主体验
  2. HAP 工程负责应用安装和资源承载
  3. Electron runtime 负责窗口、链接和本地页面加载
  4. 运行时变量负责后端、WebSocket、API URL 等配置注入

这次适配中比较关键的经验是:

Hoppscotch 的鸿蒙 Electron 适配,核心是让 Web 内核、运行时变量、HAP 资源和 Electron 窗口共同形成完整闭环。

6.4 困难四:构建脚本必须能反复执行

迁移类项目最怕脚本只能在"某一次刚好成功"的机器上跑通。Hoppscotch 这种 monorepo 项目本来就依赖 pnpm workspace,构建 selfhost web 时又会牵涉多个 package。如果同步脚本每次都靠手动清目录、手动复制文件,很快就会出现"我这边能跑,你那边不行"的情况。

所以脚本里没有做增量式的小修小补,而是采用比较直接的策略:

  1. 判断是否需要重新构建 Web 产物
  2. 清理输出目录
  3. 重新复制 dist
  4. 注入运行时变量
  5. 写入 main.js 和 runtime package.json

这套流程牺牲了一点执行时间,但换来的是结果更可预期。对鸿蒙适配来说,这个取舍通常值得,因为设备侧定位成本比本地多等几秒构建高得多。

6.5 运行链路确认顺序

适配完成后,Hoppscotch 在鸿蒙中的运行链路可以按下面顺序确认:

  1. 先看 resources/app/dist/index.html 是否存在
  2. 再看里面是否还有 /assets/... 这样的根路径资源
  3. 检查 manifest.webmanifest 是否还引用根路径
  4. 确认 import_meta_env_placeholder 是否已经被替换
  5. 看 Electron 是否真正加载了 dist/index.html
  6. 最后再进入 Hoppscotch 自己的业务初始化和网络请求

这个顺序可以确认资源、manifest、运行时变量、Electron 入口和业务初始化都已经进入正确位置。


七、构建与运行方式

同步资源:

bash 复制代码
cd /hoppscotch-ohos
pnpm run ohos:sync

构建 HAP:

bash 复制代码
cd /hoppscotch-ohos
pnpm run ohos:build

构建脚本会依次完成:

  1. 检查或构建 packages/hoppscotch-selfhost-web/dist
  2. 同步到 ohos_hap/web_engine/src/main/resources/resfile/resources/app
  3. 执行 ohpm install
  4. 调用 hvigor assembleHap

HAP 输出位置:

text 复制代码
ohos_hap/electron/build/default/outputs/default/

八、适配成果

hoppscotch-ohos 已经完成:

  • OpenHarmony Electron HAP 工程
  • selfhost web 静态产物同步能力
  • 本地 file:// 加载入口
  • 运行时环境变量注入
  • 外部链接拦截
  • HAP 命令行构建能力
  • REST 请求能力承载
  • GraphQL / WebSocket 运行配置
  • 集合、环境、历史记录等核心 API 调试体验承载

适配完成的是:

Hoppscotch Web 核心体验完整进入鸿蒙 Electron runtime。

从应用体验看,REST、GraphQL、WebSocket、collection、environment、history 等核心链路已经完成鸿蒙化承载。


九、功能验证结果

Hoppscotch 鸿蒙版按实际 API 调试路径完成了功能验证。核心体验不只停留在页面加载,而是覆盖请求发送、响应展示、状态保存和实时连接。

第一组是基础请求:

  • REST GETPOST、带 header、带 body
  • 请求失败时的错误提示
  • 大响应体和 JSON 格式化
  • 请求历史记录正常保存

第二组是实时链路:

  • GraphQL 查询与变量
  • GraphQL subscription / WebSocket 连接
  • WebSocket 普通连接、发送、接收、断开重连

第三组是工程化能力:

  • collection 新建、编辑、删除
  • environment 变量读取和切换
  • 导入导出集合
  • 登录态与后端账号能力

第四组是鸿蒙环境相关能力:

  • 外部链接拦截到系统浏览器
  • 网络权限和证书异常提示
  • 横竖屏或窗口尺寸变化时的布局
  • HAP 重新安装后的本地数据表现

这些能力共同组成了 Hoppscotch 在鸿蒙环境中的完整 API 调试体验。


十、结语

hoppscotch-ohos 的适配重点,是把 Hoppscotch 的 Web 核心体验稳定放进鸿蒙 Electron runtime:

把一个 Web-first 的复杂开发工具,放进鸿蒙 Electron runtime 中稳定承载。

这条路线的好处是边界清楚:Web 内核负责核心业务,HAP 工程负责资源承载,Electron runtime 负责本地窗口。工程链路、资源路径和运行时变量处理稳定之后,API 请求、集合、环境、WebSocket、导入导出等能力就能在鸿蒙环境中形成完整闭环。

相关推荐
xcLeigh2 小时前
鸿蒙PC平台 imv 图片查看器适配实战:极简主义设计的 Electron 迁移
华为·electron·harmonyos·鸿蒙·imv·图片操作·web_engine
不羁的木木2 小时前
《HarmonyOS 6.1 新能力实战之智感握姿》第四篇:进阶应用——横屏游戏手柄模式
游戏·华为·harmonyos
IT大白鼠2 小时前
IPv6过渡技术:原理、分类与应用
网络·网络协议·华为
风华圆舞2 小时前
在 Flutter 鸿蒙项目里接入语音识别的完整思路
flutter·语音识别·harmonyos
Swift社区3 小时前
鸿蒙游戏Runtime解析:Store如何驱动整个游戏世界?
游戏·华为·harmonyos
YM52e4 小时前
手写模型集合书籍鸿蒙PC ArkTS 对象字面量类型问题约束深度解析
学习·华为·harmonyos·鸿蒙
狼哥16864 小时前
《新闻资讯》四、视频模块实现指南
ui·华为·音视频·harmonyos
风华圆舞4 小时前
鸿蒙 + Flutter 下如何让 HarmonyOS 能力真正服务于 AI 体验
人工智能·flutter·harmonyos