场景:
- 按产品需要,应用需要打多种马甲包(换个图标名字)及渠道包(同种包有不同的渠道),多达上百个,包名还需要根据渠道、版本、名称经过加密来命名。
- 打包过程:需要更换图片、渠道id、名字、版本号,然后运行打包命令,等待三四分钟编译打完包,然后更改加密后的包名
想象一下,几百个包,守在那里,一个一个打...
批量打包原理:
这里先是将需要打包的资源图片用统一的命名规范放在一个文件夹里面,然后用nodejs读取该文件就可以知道要打哪些马甲包,然后在遍历打包过程中用nodejs读取替换图片,计算加密包名,读取并更改配置文件,最后运行打包命令。说的可能不明不白,下面贴上代码:
创建channelMRD.js文件,代码如下:
- 引入fs模块,并读取目录确定所要打的包。所有要打包的图片资源都放在了文件夹resourcesImage里面。并过滤掉垃圾文件,防止后面遍历过程报错
const fs = require('fs');
const { mkdirpSync } = require('fs-extra');
const execSync = require('child_process').execSync;
const images = fs.readdirSync('./resourcesImage').filter(item => item != '.DS_Sto
- 对images进行遍历操作
images.forEach(async (f, i) => {
...
});
- 在遍历过程中替换图片,使用fs模块将resourcesImage下的图片资源替换到对应项目图片所在位置。
fs.copyFileSync(`./resourcesImage/${f}/${f}.ico`, `./resources/${f}/favicon.ico`);
fs.copyFileSync(
`./resourcesImage/${f}/${f}.ico`,
`./resources/${f}/favicon-256.ico`
);
fs.copyFileSync(`./resourcesImage/${f}/${f}.png`, `./resources/${f}/logo.png`);
// 替换应用程序、程序坞、mac右上角图标
fs.copyFileSync(`./resourcesImage/${f}/icon_512.png`, `./icon.png`);
fs.copyFileSync(`./resourcesImage/${f}/favicon_16.png`, `./script/favicon.png`);
fs.copyFileSync(`./resourcesImage/${f}/favicon2_64.png`, `./script/favicon2.png`);
fs.copyFileSync(`./resourcesImage/${f}/favicon2_64.png`, `./src/assets/icons/logo1024.png`);
fs.copyFileSync(`./resourcesImage/${f}/favicon2_64.png`, `./src/assets/icons/logo.png`);
fs.copyFileSync(`./resourcesImage/${f}/favicon2_64.png`, `./script/logo/favicon.png`);
- 设置配置文件。首先需要知道要设置成多少:resourcesImage图片命名按要求拼接好后,这里直接读取就可以了
const [
channel,
folderName,
shortcutName,
version = '4.0.1',
] = f.split('-');
- 拿到配置,接下来设置配置文件即可,这里将设置配置文件的代码放到了新建的channelProcess.js文件里了,通过child_process模块运行该脚本即可
execSync(
`node ./channelProcess.js ${folderName} ${shortcutName} ${channel} ${f} ${version} ${channel_type}`
);
- 进入channelProcess.js,首先是获取传进来的配置信息:
const fs = require('fs');
const argv = process.argv;
const name = argv[2];
const shortcutName = argv[3];
const channel = argv[4];
const fileName = argv[5];
const version = argv[6] || '1.0.0';
const channel_type = argv[7];
- 先是修改package.json配置,内容较多,可能有点麻烦
读取package.json并修改配置信息:名字、版本号、包名、id等
const readWriteFile = path => {
fs.readFile(path, function (err, data) {
if (err) {
console.log(`read [${path}] error`);
} else {
const jsonData = JSON.parse(data.toString()); // 读取的package.json内容
const stringData = JSON.stringify(changeData(jsonData)); // 修改后的package.json内容
writeFile(path, stringData); // 写入package.json
}
});
};
readWriteFile('./package.json');
changeData:修改名称、版本、id等配置
const changeData = data => {
data.name = name + `-mac` + `-c${channel}`;
data.version = version;
data.description = name + `-mac` + `-c${channel}`;
data.build.appId = name + `-c${channel}` + `-mac`;
data.build.productName = shortcutName; //应用程序桌面名字(mac)
data.build.artifactName = artifactName + '.${ext}';
// '${productName}-${version}' + `-c${channel}` + '.${ext}';
data.build.nsis.shortcutName = shortcutName;
data.build.directories = {
output: `dist/c${channel}-${channel_type}`
}
return data;
};
artifactName是经过md5加密的最终名称
const md5 = require('md5')
//16进制转为10进制
function hex2int(hex) {
var len = hex.length, a = new Array(len), code;
for (var i = 0; i < len; i++) {
code = hex.charCodeAt(i);
if (48 <= code && code < 58) {
code -= 48;
} else {
code = (code & 0xdf) - 65 + 10;
}
a[i] = code;
}
return a.reduce(function (acc, c) {
acc = 16 * acc + c;
return acc;
}, 0);
}
//执行方法
function clickmd5(version, channel, channel_type){
const value = `v${version}_c${channel}_${channel_type}_mac_ltz`
return "app_" + value.substring(0,value.length-3) + hex2int(md5(value).substring(4,8));
}
// 得到最终名称
const artifactName = clickmd5(version, channel, channel_type)
writeFile:写入文件包一层
const writeFile = (path, data) => {
try {
fs.writeFile(
path,
data,
{
encoding: 'utf8',
},
err => {
if (err) throw err;
console.log(`-- write [${path}] set success`);
}
);
} catch (error) {
console.log(`write [${path}] error: `, error);
}
};
- 修改其他配置同理,甚至更简单,直接覆盖写入即可
// 更改配置文件./public/preload.js
const publicPreloadText = `window.channelName='${shortcutName}';window.EXTEND_SOURCE='c${channel}';`;
writeFile('./public/preload.js', publicPreloadText);
// 更改配置文件./script/preset.js
const scriptPresetText = `const channelName='${shortcutName}'; module.exports={channelName};`;
writeFile('./script/preset.js', scriptPresetText);
// 更改配置文件./src/utils/config.js
const configText = `const PLATFORM = '4'; const CHANNEL_TYPE = '${channel_type}'; const VERSION = '${version}'; const PACKAGE = '${name}';const EXTEND_SOURCE = '${channel}';export{PLATFORM, CHANNEL_TYPE, VERSION,PACKAGE,EXTEND_SOURCE}`;
writeFile('./src/utils/config.js', configText);
- 至此,配置文件更改完毕。回到channelMRD.js文件下的遍历操作那里,改完配置后就是开始打包了。这里需要注意的是直接运行execSync('yarn edist')打包后会有文件丢失,我当时为了查看控制台输出,加入配置{stdio: 'inherit'}后就正常了
execSync('yarn edist', {stdio: 'inherit'});
- 还有同一种马甲包下有不同渠道包,这里渠道比较简单,就1、2、3,遍历123执行步骤5跟步骤9即可
// channel_type 1-正常包 2-分享包 3-下载包
let channel_type = 1
while (channel_type <= 3) {
execSync(
`node ./channelProcess.js ${folderName} ${shortcutName} ${channel} ${f} ${version} ${channel_type}`
);
execSync('yarn edist', {stdio: 'inherit'});
channel_type++
}
- 批量打包命令:在package.json的script下加入
"dist:all": "node ./channelMRD.js"
运行 yarn dist:all 坐等打包即可
总结:虽然过程看起来繁琐,其实就是用nodejs的fs模块读写文件,以及child_process模块execSync运行命令而已
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!