Iconfont 图标更新指南
背景
项目使用阿里巴巴图标库 (iconfont.cn) 管理图标,采用本地文件引入方式(非 CDN)。图标文件位于:
meeting-client/src/renderer/assets/iconfont/
├── iconfont.css # 字体图标样式
├── iconfont.js # Symbol 模式脚本
├── iconfont.json # 图标元数据
├── iconfont.woff2 # 字体文件
├── iconfont.woff
├── iconfont.ttf
├── iconfont.svg
├── demo.css # 预览页样式
└── demo_index.html # 图标预览页每次在 iconfont.cn 上新增或删除图标后,需要将最新文件同步到本地。为避免手动下载解压替换的繁琐操作,项目提供了一键更新脚本。
快速使用
1. 在 iconfont.cn 上更新图标
登录 iconfont.cn,进入项目),添加或删除图标后点击「更新链接」。
2. 复制在线链接
在项目页顶部,选择「Font class」标签页,点击「查看在线链接」或「更新代码」,复制生成的链接,格式类似:
//at.alicdn.com/t/c/font_5161721_abc123def.css3. 复制脚本文件
将 meeting-client/scripts/update-iconfont.mjs 复制到目标项目的 scripts/ 目录下。
4. 修改目标目录
打开脚本文件,找到 DEST_DIR 常量,将路径改为该项目实际的 iconfont 存放目录:
// 修改前(meeting-client 的路径)const DEST_DIR = resolve(__dirname, '../src/renderer/assets/iconfont');
// 修改后(按实际项目调整,例如)const DEST_DIR = resolve(__dirname, '../src/assets/iconfont'); // Vue 项目const DEST_DIR = resolve(__dirname, '../public/iconfont'); // 放在 public 目录const DEST_DIR = resolve(__dirname, '../src/styles/iconfont'); // 放在 styles 目录路径规则:相对于脚本文件(scripts/update-iconfont.mjs)所在目录。
5. 添加 npm script
在目标项目的 package.json 中添加:
{"scripts": {"update-iconfont": "node scripts/update-iconfont.mjs"}}配置完成后,使用方式与本项目一致:
npm run update-iconfont -- --url "//at.alicdn.com/t/c/font_xxxxxxx_xxxxxxx.css"环境要求
Node.js >= 18(脚本使用了原生
fetchAPI,18 以下版本不支持)网络能访问
at.alicdn.com
脚本源码
脚本位于 meeting-client/scripts/update-iconfont.mjs,完整代码如下:
#!/usr/bin/env node/**
* iconfont 自动更新脚本
*
* 使用方式:
* node scripts/update-iconfont.mjs --url "//at.alicdn.com/t/c/font_5161721_xxxxxxx.css"
*
* 也可以只传 hash 部分(省略 .css 后缀和前缀):
* node scripts/update-iconfont.mjs --url "font_5161721_xxxxxxx"
*
* 脚本会自动下载以下文件到 src/renderer/assets/iconfont/ 目录:
* iconfont.css / iconfont.js / iconfont.json
* iconfont.woff2 / iconfont.woff / iconfont.ttf / iconfont.svg
* demo.css / demo_index.html
*
* ─── 在其他项目中使用 ───
* 1. 将本文件复制到目标项目的 scripts/ 目录下
* 2. 修改下方 DEST_DIR 为该项目的 iconfont 存放路径(相对于本脚本所在目录)
* 3. 在 package.json 的 scripts 中添加:
* "update-iconfont": "node scripts/update-iconfont.mjs"
* 4. 运行:npm run update-iconfont -- --url "<iconfont在线链接>"
*
* 环境要求:Node.js >= 18(使用了原生 fetch API)
*/import { writeFile, mkdir } from 'node:fs/promises';
import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
// ⬇️ 其他项目使用时,修改此路径为实际的 iconfont 存放目录(相对于本脚本所在目录)const DEST_DIR = resolve(__dirname, '../src/renderer/assets/iconfont');
// 需要下载的文件后缀列表const FONT_EXTS = ['css', 'js', 'json', 'woff2', 'woff', 'ttf', 'svg'];
const DEMO_FILES = ['demo.css', 'demo_index.html'];
/**
* 从命令行参数中解析出 iconfont 的基础 URL
* 支持多种输入格式:
* //at.alicdn.com/t/c/font_5161721_abc123.css
* https://at.alicdn.com/t/c/font_5161721_abc123.css
* font_5161721_abc123
*/function parseBaseUrl(raw) {let url = raw.trim();
// 去掉可能的文件后缀
url = url.replace(/\.(css|js|json)$/, '');
// 如果是完整链接,提取路径中的 font_xxx_xxx 部分const match = url.match(/(font_\d+_\w+)/);if (!match) {console.error('错误:无法从输入中解析 iconfont 项目标识');console.error('期望格式://at.alicdn.com/t/c/font_5161721_xxxxxxx.css');
process.exit(1);
}
return `https://at.alicdn.com/t/c/${match[1]}`;
}
/**
* 下载单个文件
*/async function download(url) {const res = await fetch(url);if (!res.ok) {throw new Error(`下载失败: ${url} (${res.status})`);
}return res;
}
/**
* 下载并保存二进制文件
*/async function downloadToFile(url, destPath) {const res = await download(url);const buf = Buffer.from(await res.arrayBuffer());await writeFile(destPath, buf);return buf.length;
}
/**
* 下载并保存文本文件
*/async function downloadTextToFile(url, destPath) {const res = await download(url);const text = await res.text();await writeFile(destPath, text, 'utf-8');return text;
}
/**
* 修正 CSS 中的字体路径:
* 将远程 URL 替换为本地相对路径,保留时间戳参数
*/function fixCssPaths(cssContent, baseUrl) {// 匹配 url('...font_xxx_xxx.woff2?t=xxx') 等格式return cssContent.replace(/url\(['"]?([^'")\s]+)['"]?\)/g,(match, rawUrl) => {// 只处理包含 font_ 的远程字体链接if (!rawUrl.includes('font_')) return match;
// 提取文件名部分(如 iconfont.woff2?t=xxx)const fileName = rawUrl.split('/').pop();if (!fileName) return match;
// 将 font_xxx_xxx.ext 重命名为 iconfont.extconst localName = fileName.replace(/font_\d+_\w+/, 'iconfont');return `url('${localName}')`;
}
);
}
async function main() {// 解析命令行参数const args = process.argv.slice(2);const urlIndex = args.indexOf('--url');if (urlIndex === -1 || !args[urlIndex + 1]) {console.log('用法: node scripts/update-iconfont.mjs --url "<iconfont在线链接>"');console.log('');console.log('示例:');console.log(' node scripts/update-iconfont.mjs --url "//at.alicdn.com/t/c/font_5161721_abc123.css"');console.log(' node scripts/update-iconfont.mjs --url "font_5161721_abc123"');
process.exit(1);
}
const baseUrl = parseBaseUrl(args[urlIndex + 1]);console.log(`基础 URL: ${baseUrl}`);console.log(`目标目录: ${DEST_DIR}`);console.log('');
// 确保目标目录存在await mkdir(DEST_DIR, { recursive: true });
let hasError = false;
// 1. 下载字体相关文件for (const ext of FONT_EXTS) {const url = `${baseUrl}.${ext}`;const destPath = resolve(DEST_DIR, `iconfont.${ext}`);const isBinary = ['woff2', 'woff', 'ttf'].includes(ext);
try {if (ext === 'css') {// CSS 需要修正字体路径为本地相对路径const res = await download(url);const cssContent = await res.text();const fixed = fixCssPaths(cssContent, baseUrl);await writeFile(destPath, fixed, 'utf-8');console.log(` ✓ iconfont.${ext} (已修正路径)`);
} else if (isBinary) {const size = await downloadToFile(url, destPath);console.log(` ✓ iconfont.${ext} (${(size / 1024).toFixed(1)} KB)`);
} else {await downloadTextToFile(url, destPath);console.log(` ✓ iconfont.${ext}`);
}
} catch (e) {console.log(` ✗ iconfont.${ext} - ${e.message}`);
hasError = true;
}
}
// 2. 下载 demo 文件(可选,失败不影响)for (const file of DEMO_FILES) {const url = `${baseUrl}/${file}`;const destPath = resolve(DEST_DIR, file);try {await downloadTextToFile(url, destPath);console.log(` ✓ ${file}`);
} catch {console.log(` - ${file} (跳过)`);
}
}
console.log('');if (hasError) {console.log('部分文件下载失败,请检查链接是否正确。');
process.exit(1);
} else {console.log('iconfont 更新完成!');
}
}
main();支持的链接格式
脚本支持多种输入格式,以下写法等效:
# 完整 CSS 链接(推荐)
npm run update-iconfont -- --url "//at.alicdn.com/t/c/font_5161721_abc123def.css"# 带 https 前缀
npm run update-iconfont -- --url "https://at.alicdn.com/t/c/font_5161721_abc123def.css"# JS 链接也可以
npm run update-iconfont -- --url "//at.alicdn.com/t/c/font_5161721_abc123def.js"# 只传项目标识(省略域名和后缀)
npm run update-iconfont -- --url "font_5161721_abc123def"脚本做了什么
解析链接:从输入中提取
font_{项目ID}_{hash}标识下载文件:从阿里 CDN 下载
.css、.js、.json、.woff2、.woff、.ttf、.svg共 7 个核心文件,以及demo.css、demo_index.html2 个预览文件修正 CSS 路径:将 CSS 中的远程字体 URL(如
url('//at.alicdn.com/t/c/font_5161721_abc.woff2'))替换为本地相对路径(如url('iconfont.woff2?t=...'))覆盖写入:所有文件直接写入
src/renderer/assets/iconfont/目录,覆盖旧文件
Tips
如果加载了图标但设置颜色不生效,需要去除底色
评论区