侧边栏壁纸
博主头像
前端学习

行动起来,活在当下

  • 累计撰写 313 篇文章
  • 累计创建 18 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Iconfont 图标更新

Administrator
2026-04-20 / 0 评论 / 0 点赞 / 3 阅读 / 0 字

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.css

3. 复制脚本文件

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(脚本使用了原生 fetch API,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"

脚本做了什么

  1. 解析链接:从输入中提取 font_{项目ID}_{hash} 标识

  2. 下载文件:从阿里 CDN 下载 .css.js.json.woff2.woff.ttf.svg 共 7 个核心文件,以及 demo.cssdemo_index.html 2 个预览文件

  3. 修正 CSS 路径:将 CSS 中的远程字体 URL(如 url('//at.alicdn.com/t/c/font_5161721_abc.woff2'))替换为本地相对路径(如 url('iconfont.woff2?t=...')

  4. 覆盖写入:所有文件直接写入 src/renderer/assets/iconfont/ 目录,覆盖旧文件


Tips

如果加载了图标但设置颜色不生效,需要去除底色

0

评论区