提升效率,一行命令更新项目中的 iconfont 图标库

493 阅读2分钟

需求背景

图标库频繁新增图标,每次下载替换到项目中比较麻烦。尤其是刚下载好,设计师优化了下,还得手动重来,费时费力。 所以可以写个简单的脚本,执行命令时,将文件读取到本地进行替换。

项目中使用iconfont的方式

  1. 如下图,symbol Tab下点击生成代码
image.png
  1. 点击操作会发起一个cdn的请求,然后生成如下具体地址(注意:当图标库有变化时,重新获取cdn地址会变化)
image.png
  1. 点击生成的地址,就会在新页面生成字体库的内容,此时我们复制下来,替换到项目中就可以了

image.png

  1. 最后在前端项目的入口文件里,引用iconfont.js就可以了

分析上述步骤

用脚本实现上述步骤,其实就是先获取最新的文件内容,并且下载到本地。

由于点击生成代码时,只是获取的那一刻的文件内容。所以想要得到最新的图标文件内容,就需要获取最新的下载地址。

打开控制台,可以看到这是一个post请求,接口是https://www.iconfont.cn/api/project/cdn.json,参数有3个

{
    pid: '', // 仓库id
    t: Date.now(), // 时间戳
    ctoken: '', // ctoken
}

接口返回成功后,其中的js_file就是展现的地址:

image.png

得到了文件地址,拼接一下,然后就可以通过nodejs下载文件了

update-icon.js 代码实现

  1. 获取最新cdn地址
  2. 下载文件,写入到本地的一个临时文件上
  3. 将临时文件内容覆盖iconfont.js文件
  4. 删除临时文件
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",   
}