轻画廊桌面版:Electron 跨平台图片查看器实践与鸿蒙适配
今天我们一起来适配一个GitHub上有1kstar的开源项目到GitCode,一起来看一下适配的过程,以及这个应用升级的时候遇到的一些问题。
-
项目定位:一个基于 Electron 与 Node.js 的现代图片查看器,借助 LightGallery 实现丰富的动效与缩略图体验。
-
跨平台目标:统一代码在 macOS、Windows、Linux 运行;并给出 HarmonyOS NEXT 的集成思路。
-
技术焦点:Electron 主进程与渲染进程协作、LightGallery 插件集成、菜单与国际化、打包脚本与签名发布。
效果预览

实现过程
-
主进程启动
-
在
app/background.js创建BrowserWindow,并启用@electron/remote/main,以兼容新版 Electron 移除默认remote的变更。 -
通过菜单配置与
webContents.send实现渲染进程通信(如打开目录、更新配置项)。
-
-
渲染层与 LightGallery 集成
-
app/app.html引入 LightGallery 的 CSS/JS 与各插件(如 Autoplay、Thumbnail),并在页面中渲染图片容器。 -
app/app.js负责将defaults(主进程中的配置)透传到 LightGallery 初始化,绑定事件与控件逻辑。
-
-
配置与菜单
-
background.js维护defaults,其中包含mode/speed/zoom/thumbnail/autoplay等所有参数;菜单项通过updateConfig(key, value)动态更新并通知渲染进程。
-
-
国际化(i18n)
-
在
app/i18n.js提供简易字典,默认语言zh-CN,可用setLocale('en-US')切换。 -
所有菜单标签使用
t('key')获取翻译,避免硬编码英文。
-
示例代码(附注释)
-
app/i18n.js核心方法与字典结构
export function setLocale(code) {
// 切换当前语言,默认字典包含 zh-CN 与 en-US
}
export function t(key) {
// 读取当前字典;如果未找到键,降级返回 key 本身,避免崩溃
}
-
缩略图菜单国际化(摘自
background.js,已替换为t())
{
label: t('thumbnail'), // 缩略图主开关
type: 'checkbox',
checked: defaults.thumbnail,
click: (menuItem) => updateConfig('thumbnail', menuItem.checked)
},
{
label: t('animateThumb'), // 缩略图动效
type: 'checkbox',
checked: defaults.animateThumb,
click: (menuItem) => updateConfig('animateThumb', menuItem.checked)
},
{
label: t('toogleThumb'), // 切换缩略图显示
type: 'checkbox',
checked: defaults.toogleThumb,
click: (menuItem) => updateConfig('toogleThumb', menuItem.checked)
},
{
label: t('enableThumbDrag'), // 启用缩略图拖拽
type: 'checkbox',
checked: defaults.enableThumbDrag,
click: (menuItem) => updateConfig('enableThumbDrag', menuItem.checked)
}
-
字典补充(摘自
app/i18n.js)
'zh-CN': {
thumbnail: '缩略图',
animateThumb: '缩略图动画',
toogleThumb: '切换缩略图',
enableThumbDrag: '启用缩略图拖拽',
// ...
},
'en-US': {
thumbnail: 'Thumbnail',
animateThumb: 'animateThumb',
toogleThumb: 'toogleThumb',
enableThumbDrag: 'enableThumbDrag',
// ...
}
目录结构
-
app:应用主代码与资源-
app.html:页面骨架与资源引入 -
app.js:渲染逻辑与 LightGallery 初始化 -
background.js:Electron 主进程、菜单、配置与事件转发 -
i18n.js:字典与翻译方法 -
lightgallery/:第三方库 CSS/JS/Sass 与字体、图片等 -
stylesheets/main.less:样式入口 -
config.json:默认配置与参数
-
-
tasks:构建与打包脚本-
start.js:开发时独立构建并启动 Electron -
build_standalone.js:独立构建,规避旧版 gulp 问题 -
release_standalone.js:按当前 OS 打包(推荐入口) -
release_osx*.js:macOS 打包,支持 zip/DMG 与签名 -
release_windows.js:Windows 打包(NSIS 安装包) -
release_linux.js:Linux 打包(DEB) -
utils.js:通用工具(OS 检测、变量替换、签名参数等)
-
-
resources:平台打包素材-
osx/:Info.plist、DMG 配置与图标 -
windows/:图标与 NSIS 安装脚本 -
linux/:DEBIAN/ 控制文件与 Desktop 文件模板
-
-
config:环境配置(development/test/production) -
README.md:文档(含打包与升级说明)
启动与开发
-
安装依赖(包含 Electron 与
app内依赖)
npm install
-
启动开发
npm start
-
国内镜像加速下载 Electron(可选)
ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ npm install
打包流程
-
基础打包(推荐)
npm run release
-
macOS(签名/DMG)
node ./tasks/release_osx.js --env=production --sign="Developer ID Application: 你的证书名称 (TEAMID)"
-
macOS(简化脚本,zip/DMG,不强制签名)
node ./tasks/release_osx_simple.js --env=production
-
Windows(NSIS)
node ./tasks/release_windows.js --env=production
-
Linux(DEB)
node ./tasks/release_linux.js --env=production
-
发布前建议:
-
更新
app/package.json的version/productName/identifier -
在应用中切换语言自查菜单文案(i18n)与主流程
-
升级过程中遇到的问题
-
electron-prebuilt → electron@^31
-
新版 Electron 移除默认
remote,需在主进程启用@electron/remote/main,渲染进程使用@electron/remote。 -
BrowserWindow需设置webPreferences: { nodeIntegration: true, contextIsolation: false }以兼容旧代码。
-
-
gulp 3 与 Node 18 的兼容性
-
典型报错:
primordials is not defined -
处理方案:开发与构建走
build_standalone.js;发布脚本按平台拆分(可逐步迁移到 gulp v4) -
兜底方案:如暂时保留旧版脚本,打包时使用 Node 14 LTS
-
-
macOS 打包与签名
-
release_osx.js支持签名与 DMG;需设置--sign指定 Developer ID -
简化版脚本
release_osx_simple.js默认生成 zip 与 DMG,增强兼容性(优先hdiutil,回退appdmg)
-
-
Windows 安装包
-
需本地安装 NSIS,确保
makensis在PATH -
使用
rcedit替换图标与版本描述
-
-
Linux DEB
-
依赖
fakeroot与dpkg-deb;脚本中处理了路径转义,避免空间字符导致命令失败
-
-
国际化缺口修复
-
Autoplay 菜单与缩略图菜单存在英文硬编码:已补齐
Autoplay/autoplay/progressBar/fourceAutoplay/autoplayControls/ms等键,并替换菜单标签为t() -
缩略图菜单新增键:
animateThumb、toogleThumb、enableThumbDrag,对应中文翻译与英文占位
-
HarmonyOS 适配
-
复用前端资源
-
将构建后的
build/作为资源目录,在 ArkUI 的 Web 组件中加载
-
-
ArkTS 壳工程
-
通过
Web组件承载页面,映射键盘与鼠标事件(如缩放、全屏、拖拽) -
以 JSBridge 封装平台差异,统一文件选择与目录访问
-
-
文案与单位
-
继续沿用英文键名作字典键(
t('thumbnail')),保持跨平台一致性;单位类(如ms)按键值组合翻译,避免硬编码
-
-
打包建议
-
HarmonyOS 侧生成
.hap;桌面端仍按上述流程输出安装包,形成多端共用前端代码的混合架构
-
开源项目地址
-
项目仓库:
gitcode.com:nutpi/lightgallery-desktop.git -
相关项目:
-
LightGallery for web:
https://github.com/sachinchoolur/lightGallery -
jQuery lightslider:
https://github.com/sachinchoolur/lightslider
-
结语
-
本项目以 Electron + LightGallery 打造跨平台图片查看器,并通过简易 i18n 与脚本化打包流程实现快速发布。
-
在升级 Electron 与适配 HarmonyOS 的过程中,建议保持英文键名统一、用脚本替代手工流程,并在每次发布前用
npm start做一次端到端自查。
架构与流程详解(更深入的技术细节)
-
主进程与渲染进程边界
-
主进程:负责窗口管理、菜单、系统能力(文件/目录选择)与配置下发;文件
app/background.js。 -
渲染进程:承载 UI 与 LightGallery 交互;文件
app/app.html与app/app.js。 -
事件通道:通过
webContents.send(channel, payload)下发事件;渲染进程监听并应用配置。
-
-
关键主进程代码(带注释)
// background.js 中的配置更新桥
var updateConfig = function(key, val) {
// 1) 更新内存中的 defaults
defaults[key] = val;
// 2) 广播给渲染进程(LightGallery 的实例在渲染层)
if (ready) {
mainWindow.webContents.send('updateConfig', { key: key, val: val });
}
};
// 菜单项示例(缩略图开关)
{
label: t('thumbnail'),
type: 'checkbox',
checked: defaults.thumbnail,
click: (menuItem) => updateConfig('thumbnail', menuItem.checked)
}
-
渲染层初始化(要点)
-
将主进程下发的
defaults映射为 LightGallery 的初始化参数与插件选项。 -
图片列表支持
dynamicEl,也可从目录读取并填充数组。
-
构建流水线详解(替代旧版 gulp 的方案)
-
入口:
tasks/start.js-
调用
build_standalone.js完成打包,然后拉起 Electron:
-
var app = childProcess.spawn(electron, ['./build'], { stdio: 'inherit' });
-
省略旧的 gulp watch;如需热更,可后续用
chokidar恢复监听。 -
独立构建:
tasks/build_standalone.js-
目标:在现代 Node 环境下替代 gulp 3 的打包功能。
-
核心步骤:
-
清理
build/;复制app的静态资源与第三方库。 -
使用
rollup打包background.js与app.js为cjs:
-
-
rollup.rollup({ entry: src }).then((bundle) => {
const result = bundle.generate({ format: 'cjs', sourceMap: true });
const isolatedCode = '(function () {' + result.code + '}());';
// 写入 bundle 及 source map
});
- 编译 Less:`stylesheets/main.less` → `build/stylesheets/main.css`。 - 写入 `build/package.json` 并注入环境配置:
manifest.env = projectDir.read('config/env_' + utils.getEnvName() + '.json', 'json');
destDir.write('package.json', manifest);
打包实现细节(按平台)
-
通用入口:
npm run release→tasks/release_standalone.js-
先执行独立构建,再根据当前 OS 路由到对应打包脚本:
-
const releaseForOs = { osx: require('./release_osx_simple'), linux: require('./release_linux'), windows: require('./release_windows') };
-
macOS:
release_osx_simple.js与release_osx.js-
复制
Electron.app到临时目录,打包app.asar,替换Info.plist与图标。 -
产物:
.zip与.dmg;优先使用系统hdiutil,失败时回退到appdmg。 -
可选签名:
release_osx.js支持--sign="Developer ID Application: ... (TEAMID)"。
-
-
Windows:
release_windows.js-
复制
electron/dist,打包app.asar,用rcedit替换图标与版本说明。 -
生成 NSIS 安装包,需本地
makensis可用。
-
-
Linux:
release_linux.js-
复制
electron/dist,打包app.asar,生成.desktop文件与图标。 -
使用
fakeroot dpkg-deb生成amd64.deb。
-
IPC 与安全策略(升级注意点)
-
remote 替换
-
新版 Electron 移除默认
remote;主进程需@electron/remote/main初始化并在创建窗口后启用。 -
渲染进程使用
@electron/remote获取app等 API。
-
-
BrowserWindow安全配置(现状与建议)-
当前为兼容旧代码,设置
nodeIntegration: true, contextIsolation: false。 -
建议后续迁移:开启
contextIsolation: true与preload,通过contextBridge暴露受控 API,降低 XSS 风险。
-
i18n 设计与扩展
-
字典结构:
dictionaries[locale][key];默认zh-CN,支持en-US。 -
回退策略:
t(key)未命中返回key本身,保证菜单不因缺失键而崩溃。 -
单位翻译:诸如
ms等单位作为独立键处理,避免字符串拼接硬编码。 -
示例:补齐缩略图相关键并替换菜单标签为
t()(见上文代码片段)。
性能与体验细节(实践建议)
-
图片目录加载
-
大量图片时建议按批次分页加载到 LightGallery,避免一次性渲染导致卡顿。
-
-
缩略图与动效
-
在低端机或远程网络资源下,建议关闭
animateThumb并降低speed,以提升交互流畅性。
-
-
资源体积
-
构建时仅复制必要的
lightgallery子目录与字体/图片,减少包体。
-
HarmonyOS 集成更细节(ArkTS/ETS)
-
Web 组件加载
-
ArkUI 提供
Web组件承载build/页面;通过postMessage或 JSBridge 与宿主交互。
-
-
能力映射
-
文件选择与目录访问在桌面与移动端差异较大,建议封装统一接口,内部桥接到平台实现。
-
-
文案一致性
-
继续沿用英文键名作为 i18n 字典键,与桌面端共享字典,减少维护成本。
-
问题清单与解决策略(升级踩坑)
-
primordials is not defined-
原因:gulp 3 与 Node 18 不兼容。
-
方案:开发/构建改为独立脚本;若保留旧版任务,打包阶段用 Node 14 LTS 兜底。
-
-
Electron 下载缓慢/失败(国内网络)
-
方案:
ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ npm install。
-
-
macOS Gatekeeper 限制
-
现象:未签名 DMG 运行受限。
-
方案:使用
--sign进行签名,必要时按 Apple 流程进行公证(notarytool)。
-
-
Windows NSIS 缺失
-
现象:
spawn makensis ENOENT。 -
方案:安装 NSIS 并把
makensis加入PATH。
-
更多推荐



所有评论(0)