在项目中使用字体包,它的体积一般都是很大的,在一些网站去压缩其体积,大多数都能减少50%左右这样,其实也不错了。但是对于一些对包体积大小有要求的项目而言,减少的这50%还是远远不够,体积占比还是很大。如果还想要继续压缩,该怎么办呢?
我们可以使用 fontmin,如下
1、安装 fontmin
npm install fontmin -g //全局
npm install fontmin --save-dev //在项目中安装为依赖
2、使用 动态统计文字
网上大多数例子都是写死自己统计文字,这种既繁琐又不友好。
咱们程序员比较懒,所以介绍一种动态的:
创建一个文件夹 如 fontmin-compress.cjs,与src同级
const Fontmin = require("fontmin");
const fs = require("fs");
const path = require("path");
// 源字体文件目录
const inputDir = path.join(__dirname, "src/assets/fontsFile");
// 输出目录
const outputDir = path.join(__dirname, "src/assets/font");
// 项目文件目录
const projectDir = path.join(__dirname, "src");
// 正则表达式:匹配文字内容
const textRegex = /[\u4e00-\u9fa5a-zA-Z0-9]/g;
// 正则表达式:匹配注释
const commentRegex = {
js: /\/\/.*|\/\*[\s\S]*?\*\//g,
html: /<!--([\s\S]*?)-->/g,
css: /\/\*[\s\S]*?\*\//g,
};
// 移除文件中的注释
function removeComments(content, fileType) {
if (fileType === "js" || fileType === "vue") {
return content.replace(commentRegex.js, "");
} else if (fileType === "html") {
return content.replace(commentRegex.html, "");
} else if (fileType === "css") {
return content.replace(commentRegex.css, "");
}
return content;
}
// 动态提取项目中的所有文字
function extractTextFromProject(dir) {
let allText = "";
const traverseDir = (directory) => {
const files = fs.readdirSync(directory);
files.forEach((file) => {
const filePath = path.join(directory, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
traverseDir(filePath); // 递归子目录
} else if (/\.(html|js|vue|css)$/.test(file)) {
// 仅处理 HTML、JS、Vue 和 CSS 文件
const fileType = path.extname(file).slice(1); // 获取文件扩展名
let content = fs.readFileSync(filePath, "utf-8");
content = removeComments(content, fileType); // 移除注释
const matches = content.match(textRegex); // 匹配中文、英文、数字
if (matches) {
allText += matches.join(""); // 收集匹配到的文字
}
}
});
};
traverseDir(dir);
return Array.from(new Set(allText)).join(""); // 去重
}
// 获取项目中的文字
const text = extractTextFromProject(projectDir);
console.log("提取到的文字:", text);
// 获取所有字体文件
const fontFiles = fs.readdirSync(inputDir).filter((file) => {
return /\.(ttf|otf|woff|woff2)$/.test(file); // 仅处理字体文件
});
// 批量处理字体文件
fontFiles.forEach((fontFile) => {
const fontmin = new Fontmin()
.src(path.join(inputDir, fontFile)) // 输入字体文件路径
.use(Fontmin.glyph({ text })) // 使用动态提取的文字
.dest(outputDir); // 输出压缩后的字体文件路径
fontmin.run((err, files) => {
if (err) {
console.error(`压缩字体文件 ${fontFile} 时出错:`, err);
} else {
console.log(`成功压缩字体文件: ${fontFile}`);
}
});
});
该方法是只提取项目中用到的字的字体包,类似按需引入;
有一个缺点就是如果有些文案是接口返回来显示的,刚好页面没有用到这个字,没有统计下来;显示的时候就会出现一些有字体效果,一些是默认字体效果;
怎么解决呢?
自己跟后端协商好有哪些字,然后自己手动加上去!
3、项目打包
在项目打包时,我是先提取字体包出来,再打包项目。
所以在package.json中添加配置
"build": "node fontmin-compress.cjs && vite build",
这样就完成了项目打包时,对字体包体积的优化啦!
压缩效果举例:优化前后对比