背景交代
最近在做的一个基于Electron开发的Mac端项目,要进行产品更名。
但是如果直接修改编译打包后的应用名称,问题会比较大。
首先,类似上图里所有缓存资源、以及涉及鉴权的各种Cookie&Storage ,都是存放在类似/Users/huzunjie/Library/Application Support/旧名称
目录下的。
其次,通过旧名称.dmg
安装到启动台中的应用,对应物理目录为/Applications/旧名称.app
。
如果直接对应用打包时更名,缓存必然全部失效,也会导致/Applications/
目录下同时存在新旧2个不同名称的APP。
这显然不是想看到的结果。
解决方案
通过查询资料,我们发现实际MacOS是允许在不影响原/Applications/旧名称.app
物理路径的基础上,给应用设置一系列语言包,用于告知MacOS的文件系统及启动台等地方,按本地化语言环境展示对应名字。
这么以来也就找到了一个“为编译打包旧名称.app
中增加语言包来配置别名”的解决方案。
我是基于 electron-build
进行编译打包的,所以按上面这个思路,给package.json
增加语言配置,并另外基于electron-build
的afterPack Hook
实现了个补充语言包的脚本。
具体代码
首先 package.json
中要添加 electronLanguagesInfoPlistStrings
配置,及钩子脚本afterPack
、并在extendInfo
中添加LSHasLocalizedDisplayName
字段:
{
"name": "my-app-name",
"productName": "旧名称",
....
"electronLanguagesInfoPlistStrings": {
"en": {
"CFBundleDisplayName": "En新名称",
"CFBundleName": "En新名称"
},
"zh_CN": {
"CFBundleDisplayName": "新名称",
"CFBundleName": "新名称"
},
},
"build": {
"afterPack": "./buildAfterPack.js",
"mac": {
"extendInfo": {
"LSHasLocalizedDisplayName": true
}
}
....
}
....
}
编译时的钩子脚本./buildAfterPack.js
用于读取package.json
中的语言配置,并生成语言包物理文件,实现如下 :
/* 基于 APP 打包后的钩子功能补充语言包配置,以满足类似“旧名字”在Mac文件系统中显示为“新名字”的需求 */
const fs = require('fs');
exports.default = async (context) => {
const { electronPlatformName, appOutDir } = context;
if (electronPlatformName !== 'darwin') {
return;
}
const {
productFilename,
info: {
_metadata: { electronLanguagesInfoPlistStrings },
},
} = context.packager.appInfo;
const resPath = `${appOutDir}/${productFilename}.app/Contents/Resources/`;
console.log(
'\n> 基于 package.json 配置项 “electronLanguagesInfoPlistStrings” 创建语言包 Sta \n',
'\n> electronLanguagesInfoPlistStrings:\n',
electronLanguagesInfoPlistStrings,
'\n\n',
'> ResourcesPath:',
resPath
);
// 创建APP语言包文件
const createLangFilesPromise = await Promise.all(
Object.keys(electronLanguagesInfoPlistStrings).map((langKey) => {
const infoPlistStrPath = `${langKey}.lproj/InfoPlist.strings`;
let infos = '';
const langItem = electronLanguagesInfoPlistStrings[langKey];
Object.keys(langItem).forEach((infoKey) => {
infos += `"${infoKey}" = "${langItem[infoKey]}";\n`;
});
return new Promise((resolve) => {
fs.writeFile(`${resPath}${infoPlistStrPath}`, infos, (err) => {
resolve();
if (err) throw err;
console.log(`> “{ResourcesPath}/${infoPlistStrPath}” 创建完毕。`);
});
});
})
);
console.log(
'\n> 基于 package.json 配置项 “electronLanguagesInfoPlistStrings” 创建语言包 End \n'
);
return createLangFilesPromise;
};
补充配置
以上解决了安装后的应用更名需求。
但编译打包后的文件还是“旧名称 1.2.3.dmg”、“旧名称 1.2.3.zip”。
用户安装过程中操作界面上大部分显示的也是“旧名称.app”。
如果要保证编译产生文件及上图中“旧名称”显示为新名称,还需要继续修改 package.json
,按下面位置添加 artifactName
和 dmg.title
:
{
....
"build": {
"artifactName": "新名称-${version}.${ext}",
"dmg": {
"title": "新名称 ${version}",
...
}
....
}
....
}
后记
这确实解决了我遇到的需求,但未必是最好的解决方案,如果发现有疏忽的地方或有更好的方案,欢迎回复。
Comments
可以发邮件 huzunjie@pyzy.net 或移步到 https://github.com/huzunjie/blog.pyzy.net/issues 评论交流。