Electron for 鸿蒙PC - 番茄工作法计时器适配问题排查与解决方案

前言

在将 Pomotroid(一款 Electron 桌面番茄工作法计时器)适配到鸿蒙 PC 平台的过程中,我们遇到了多个技术挑战:OpenSSL 兼容性问题node-sass ARM64 架构不支持webpack-cli 版本不兼容模块找不到错误contextBridge API 错误等。

本文将详细记录我们如何通过问题排查和系统化解决方案逐一解决这些适配过程中的常见问题,帮助开发者快速定位和解决类似问题。

关键词:鸿蒙PC、Electron适配、Pomotroid、问题排查、WebSocket、模块依赖、IPC通信、Remote模块


文档说明

本文档系统化地记录了在将 Pomotroid 番茄工作法计时器应用适配到鸿蒙PC平台过程中遇到的 10 个典型问题及其详细解决方案。每个问题都包含问题描述、原因分析、解决方案和注意事项,帮助开发者快速定位和解决适配过程中的常见问题。


问题 1:OpenSSL 兼容性问题

问题描述

在构建渲染进程代码时,遇到以下错误:

复制代码
Error: error:0308010C:digital envelope routines::unsupported

原因分析

Node.js 17+ 版本使用了 OpenSSL 3.0,而旧版本的 webpack 使用了已弃用的 OpenSSL API,导致不兼容。

解决方案

package.jsondev 脚本中添加 NODE_OPTIONS=--openssl-legacy-provider 环境变量:

json 复制代码
{
  "scripts": {
    "dev": "NODE_OPTIONS=--openssl-legacy-provider node .electron-vue/dev-runner.js",
    "pack:renderer": "NODE_OPTIONS=--openssl-legacy-provider cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js"
  }
}

注意事项

  • 此方案适用于 Node.js 17+ 版本
  • 如果使用 Node.js 16 或更低版本,可能不需要此配置
  • 建议在构建脚本中统一添加,避免在不同环境中出现问题

问题 2:node-sass ARM64 架构不支持

问题描述

在 macOS ARM64 架构上安装依赖时,node-sass 模块编译失败:

复制代码
Error: Node Sass does not yet support your current environment: OS X Unsupported architecture (arm64)

原因分析

node-sass 是一个已弃用的包,不支持 ARM64 架构(Apple Silicon)。

解决方案

node-sass 替换为 sass(Dart Sass):

bash 复制代码
# 1. 卸载 node-sass
npm uninstall node-sass

# 2. 安装 sass
npm install sass --save-dev --legacy-peer-deps

# 3. 重新安装依赖
npm install --legacy-peer-deps

注意sassnode-sass 的替代品,API 兼容,但不需要编译原生模块。


问题 3:webpack-cli 版本不兼容

问题描述

使用 npm run pack:renderer 构建渲染进程时,遇到以下错误:

复制代码
[webpack-cli] TypeError: Cannot read properties of undefined (reading 'getArguments')

原因分析

webpack-cli 版本与 webpack 版本不兼容,或者 webpack-cli 的 API 发生了变化。

解决方案

创建自定义构建脚本,直接使用 webpack API:

javascript 复制代码
// build-renderer.js
const webpack = require('webpack');
const config = require('./.electron-vue/webpack.renderer.config.js');

webpack(config, (err, stats) => {
  if (err) {
    console.error(err);
    process.exit(1);
  }
  if (stats.hasErrors()) {
    console.error(stats.toString({ colors: true }));
    process.exit(1);
  }
  console.log(stats.toString({ colors: true }));
});

然后在 package.json 中更新脚本:

json 复制代码
{
  "scripts": {
    "pack:renderer": "node build-renderer.js"
  }
}

问题 4:模块找不到错误(ws、winston)

问题描述

应用运行时出现以下错误:

复制代码
Cannot find module 'ws'
Cannot find module 'winston'

原因分析

Electron for 鸿蒙PC 应用的模块解析路径与标准 Electron 应用不同,需要将依赖模块复制到应用目录中。

解决方案

  1. 手动复制模块

    bash 复制代码
    # 复制 ws 模块
    cp -r pomotroid/node_modules/ws \
      ElectronForHarmony_pomotroid/web_engine/src/main/resources/resfile/resources/app/node_modules/
    
    # 复制 winston 模块及其依赖
    cp -r pomotroid/node_modules/winston \
      ElectronForHarmony_pomotroid/web_engine/src/main/resources/resfile/resources/app/node_modules/
  2. 添加自定义模块解析逻辑

    javascript 复制代码
    // main.js
    const Module = require('module');
    const fs = require('fs');
    
    const nodeModulesPath = path.join(__dirname, 'node_modules');
    if (fs.existsSync(nodeModulesPath)) {
        const originalResolveFilename = Module._resolveFilename;
        Module._resolveFilename = function(request, parent, isMain) {
            // 优先从当前目录的 node_modules 查找
            if (request === 'ws') {
                const wsPath = path.join(nodeModulesPath, 'ws', 'index.js');
                if (fs.existsSync(wsPath)) {
                    return wsPath;
                }
            }
            // ... 其他模块处理
            return originalResolveFilename.apply(this, arguments);
        };
    }
  3. 创建自动化脚本

    bash 复制代码
    # copy-dependencies.sh
    #!/bin/bash
    SOURCE_DIR="../pomotroid/node_modules"
    TARGET_DIR="web_engine/src/main/resources/resfile/resources/app/node_modules"
    
    mkdir -p "$TARGET_DIR"
    
    # 复制必要的模块
    cp -r "$SOURCE_DIR/ws" "$TARGET_DIR/"
    cp -r "$SOURCE_DIR/winston" "$TARGET_DIR/"
    # ... 复制其他依赖

注意事项

  • 需要复制所有直接依赖和间接依赖
  • 某些模块可能有平台特定的二进制文件,需要确保兼容性
  • 建议使用自动化脚本,避免遗漏依赖

问题 5:contextBridge API 错误

问题描述

preload.js 中使用 contextBridge 时出现错误:

复制代码
contextBridge API can only be used when contextIsolation is enabled

原因分析

contextBridge API 只能在 contextIsolation: true 时使用,但某些 Electron 应用需要 contextIsolation: false 来保持兼容性。

解决方案

如果 contextIsolation 设置为 false,直接暴露到 window 对象:

javascript 复制代码
// preload.js
// ❌ 错误写法(contextIsolation: false 时)
// contextBridge.exposeInMainWorld('electron', { ... });

// ✅ 正确写法
const electron = require('electron');
const { ipcRenderer } = electron;

// 直接暴露到 window
window.ipcRenderer = ipcRenderer;
window.remote = {
    app: {
        getPath: (name) => ipcRenderer.sendSync('electron-app-getPath-sync', name),
        getVersion: () => ipcRenderer.sendSync('electron-app-getVersion-sync'),
        getName: () => ipcRenderer.sendSync('electron-app-getName-sync')
    }
};

问题 6:renderer.js 中无法访问 electron.remote

问题描述

renderer.js 中访问 electron.remote.app 时返回 undefined

原因分析

preload.js 中只设置了 window.remote,但代码中可能使用 electron.remote

解决方案

preload.js 中同时设置 window.remoteelectron.remote

javascript 复制代码
// preload.js
const electron = require('electron');

// 创建 remote 代理对象
const remote = {
    app: {
        getPath: (name) => ipcRenderer.sendSync('electron-app-getPath-sync', name),
        // ...
    }
};

// 同时设置 window.remote 和 electron.remote
window.remote = remote;
electron.remote = remote;

// 同时设置 electron.app
if (!electron.app) {
    electron.app = remote.app;
}

问题 7:Ability 不存在错误

问题描述

安装应用时出现错误:

复制代码
Error Code:10104001 Error Message:The specified ability does not exist

原因分析

module.json5EntryAbilitylaunchType 配置错误,或 JSON 格式有问题。

解决方案

检查并修正 electron/src/main/module.json5

json5 复制代码
{
  "module": {
    "abilities": [
      {
        "name": "EntryAbility",
        "launchType": "singleton",  // ✅ 必须是 "singleton"
        // ...
      }
    ]
  }
}

注意

  • launchType 必须是 "singleton",不能是 "specified"
  • 确保 JSON 格式正确,没有多余的逗号

问题 8:页面内容未正常展示

问题描述

应用启动后窗口显示,但页面内容为空白或未正常渲染。

原因分析

可能的原因:

  1. renderer.js 未正确构建或路径错误
  2. __static 路径设置不正确
  3. HTML 文件中的脚本路径错误
  4. 资源文件路径问题

解决方案

  1. 检查 renderer.js 构建

    bash 复制代码
    cd pomotroid
    npm run pack:renderer
    # 确保生成的文件存在
    ls dist/electron/renderer.js
  2. 检查 index.html 中的脚本路径

    html 复制代码
    <!-- ✅ 正确 -->
    <script type="text/javascript" src="renderer.js"></script>
    
    <!-- ❌ 错误 -->
    <script type="text/javascript" src="./renderer.js"></script>
  3. 检查 __static 路径设置

    javascript 复制代码
    // index.html
    <script>
      window.__static = require('path')
        .join(__dirname, '/static')
        .replace(/\\/g, '\\\\');
    </script>
  4. 添加调试日志

    javascript 复制代码
    // main.js
    mainWindowRef.webContents.on('did-finish-load', () => {
        console.log('Window finished loading');
        // 自动打开 DevTools 以便调试
        if (process.env.NODE_ENV !== 'production') {
            mainWindowRef.webContents.openDevTools();
        }
    });

问题 9:WebSocket 连接失败

问题描述

应用启动后,WebSocket 服务器无法正常启动或连接失败。

原因分析

  1. ws 模块未正确加载
  2. 端口被占用
  3. 模块路径解析问题

解决方案

  1. 确保 ws 模块已复制

    bash 复制代码
    ls web_engine/src/main/resources/resfile/resources/app/node_modules/ws
  2. 添加模块解析逻辑(见问题 4)

  3. 检查端口占用

    javascript 复制代码
    // main.js
    function initWebSocket(port) {
        try {
            wss = new WebSocket.Server({ port });
            console.log(`WebSocket server started on port ${port}`);
        } catch (e) {
            console.error('Failed to start WebSocket server:', e);
        }
    }

问题 10:主题文件无法加载

问题描述

切换主题时,主题文件无法加载或主题不生效。

原因分析

  1. 主题文件路径错误
  2. 主题文件格式不正确
  3. 主题名称不匹配

解决方案

  1. 检查主题文件路径

    javascript 复制代码
    // Themer.js 中
    const localDir = join(__static, 'themes');
    console.log('Theme directory:', localDir);
  2. 验证主题文件格式

    json 复制代码
    {
      "name": "主题名称",
      "colors": {
        "--color-background": "#2f384b",
        // ... 其他颜色
      }
    }
  3. 确保主题名称一致

    • 主题文件中的 name 字段
    • 主题选择器中的名称
    • 文件名(可选,不影响功能)

总结

在适配过程中遇到的主要问题类型:

  1. 构建工具兼容性:Node.js 版本、webpack 版本、sass 编译器
  2. 模块依赖管理:Node.js 模块路径解析、依赖复制
  3. Electron API 兼容性:contextBridge、remote 模块、IPC 通信
  4. HarmonyOS 平台特性:硬件加速、Ability 配置、资源路径

最佳实践

  1. 统一环境:使用相同的 Node.js 版本和构建工具版本
  2. 自动化脚本:创建脚本自动复制依赖和资源文件
  3. 调试工具:充分利用 DevTools 和日志输出
  4. 参考文档:参考其他已适配项目的实现方式
  5. 逐步测试:每完成一个功能就进行测试,避免问题累积

参考资源

相关推荐
xiaocao_10231 小时前
记录在鸿蒙手机的备忘录内容被误删怎么找回?
华为·harmonyos
Sahadev_1 小时前
做APP开发有哪些基建可以做?完整调试工具集实践指南(以ReactNative为例)
javascript·react native·react.js
阿民不加班1 小时前
【React】使用browser-image-compression在上传前压缩图片、react上传图片压缩
前端·javascript·react.js
草字1 小时前
css 父节点设置display: flex; align-items: center;,子节点如何跟随其他子节点撑高的高度
前端·javascript·css
我命由我123451 小时前
微信小程序 - 页面跳转并传递参数(使用路由参数、使用全局变量、使用本地存储、使用路由参数结合本地存储)
开发语言·前端·javascript·微信小程序·小程序·前端框架·js
Gomiko1 小时前
JavaScript基础(九):内部对象
开发语言·javascript·udp
克喵的水银蛇1 小时前
Flutter 状态管理:Provider 入门到实战(替代 setState)
前端·javascript·flutter
刻刻帝的海角2 小时前
响应式数据可视化 Dashboard
开发语言·前端·javascript
小飞侠在吗2 小时前
vue3 中的 ref 和 reactive
前端·javascript·vue.js