需求背景
图标库频繁新增图标,每次下载替换到项目中比较麻烦。尤其是刚下载好,设计师优化了下,还得手动重来,费时费力。 所以可以写个简单的脚本,执行命令时,将文件读取到本地进行替换。
项目中使用iconfont的方式
- 如下图,symbol Tab下点击生成代码
- 点击操作会发起一个cdn的请求,然后生成如下具体地址(注意:当图标库有变化时,重新获取cdn地址会变化)
- 点击生成的地址,就会在新页面生成字体库的内容,此时我们复制下来,替换到项目中就可以了
- 最后在前端项目的入口文件里,引用
iconfont.js就可以了
分析上述步骤
用脚本实现上述步骤,其实就是先获取最新的文件内容,并且下载到本地。
由于点击生成代码时,只是获取的那一刻的文件内容。所以想要得到最新的图标文件内容,就需要获取最新的下载地址。
打开控制台,可以看到这是一个post请求,接口是
https://www.iconfont.cn/api/project/cdn.json,参数有3个
{
pid: '', // 仓库id
t: Date.now(), // 时间戳
ctoken: '', // ctoken
}
接口返回成功后,其中的js_file就是展现的地址:
得到了文件地址,拼接一下,然后就可以通过nodejs下载文件了
update-icon.js 代码实现
- 获取最新cdn地址
- 下载文件,写入到本地的一个临时文件上
- 将临时文件内容覆盖
iconfont.js文件 - 删除临时文件
const fs = require('fs');
const https = require('https');
const path = require('path');
const querystring = require('querystring')
const iconfontConfig = {
// iconfont域名,固定的
host: 'at.alicdn.com',
// icon动态路径
path: '',
// 本地iconfont.js文件相对脚本文件的路径
targetFilePath: path.join(__dirname, '../../assets/iconfont.js'),
// 存放临时文件的路径
tempFilePath: path.join(__dirname, './iconfont_tmp.js')
};
// 请求最新的cdn地址
const getIconUrl = () => {
const postData = querystring.stringify({
pid: '你的图标库id',
t: Date.now(),
ctoken: '你的ctoken'
})
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Cookie': '自己的cookie,找个接口copy一个就行'
}
}
const req = https.request('https://www.iconfont.cn/api/project/cdn.json', options, res => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
const result= JSON.parse(data)
if (result.code === 200) {
// 拼接下载文件的url
iconfontConfig.path = '/t/' + result.data?.js_file + '.js';
downloadIconfont()
}
});
})
req.on('error', (error) => {
console.error('请求发生错误:', error);
});
// 将请求体数据放入请求中
req.write(postData);
req.end();
}
// 下载文件
const downloadIconfont = () => {
cleanupDownloadedFile()
const fileStream = fs.createWriteStream(iconfontConfig.tempFilePath);
const options = {
host: iconfontConfig.host,
path: iconfontConfig.path
};
https.get(options, (response) => {
response.pipe(fileStream);
fileStream.on('finish', () => {
fileStream.close();
console.log('Iconfont.js 下载完成');
replaceIconfont();
});
}).on('error', (err) => {
console.error('Iconfont.js 下载失败:', err);
});
};
// 清除临时文件
const cleanupDownloadedFile = () => {
if (!fs.existsSync(iconfontConfig.tempFilePath)) return
fs.unlink(iconfontConfig.tempFilePath, (err) => {
if (err) {
console.error('删除临时文件失败:', err);
} else {
console.log('删除临时文件成功');
}
});
};
// 替换图标
const replaceIconfont = () => {
fs.copyFile(iconfontConfig.tempFilePath, iconfontConfig.targetFilePath, (err) => {
if (err) {
console.error('替换图标库失败:', err);
} else {
console.log('替换图标库成功');
}
cleanupDownloadedFile();
});
};
getIconUrl()
使用
package.json中新增一个命令,执行 yarn update-icon,当终端打印出 替换图标库成功 时,就大功告成了!
"scripts": {
"update-icon": "node ./common/scripts/update-icon.js",
}