前言
众所周知,Vite.js 在打包过程中会自动优化图片。具体来说,如果图片小于 4KB,它会被转换成 dataurl
,嵌入到 CSS 或 JS 文件中;如果大于 4KB,则使用图片的路径。这种优化能减少 HTTP 请求数量,提升加载速度。
但有时我们可能会遇到一个奇怪的需求:小于 4KB 的图片不要转成 dataurl
。我们该怎么实现呢?
最简单的解决方案
export default defineConfig({
build: {
// 单位是字节(b)
// 默认值是 4096(即 4KB)
assetsInlineLimit: 0,
},
});
通过这个配置,所有图片不论大小都会被当作文件引用,而不会嵌入到代码中。
虽然这个方法简单粗暴,但它完全禁用了 Vite.js 自带的优化功能。有没有更好的办法,只在某些特定情况下避免 dataurl
呢?
使用插件实现
export const MyPlugin = (limit = 4096) => {
return {};
};
我们可以使用 Vite.js 的插件机制来实现更加灵活的图片处理。Vite.js 底层用了 Rollup,所以我们可以创建一个自定义插件,利用 Rollup 提供的生命周期钩子函数(如 transform
),来实现图片转换的控制。
创建插件
回调函数提供两个参数:code 和 id,当 rollup 加载一个模块的时候,它就会运行 transform 函数,并将模块的路径 id 和内容 code 提供给开发者,让开发者对某个模块进行自定义转换。
export const MyPlugin = (limit = 4096) => {
return {
name: "my-plugin",
transform(code, id) {
// 仅在开发环境中应用
if (process.env.NODE_ENV !== "development") return;
// 只处理 .png 文件
if (!id.endsWith(".png")) return;
// 插件逻辑在这里实现
},
};
};
实现图片处理逻辑
接下来,我们可以使用 Node.js 提供的 fs
模块来读取和处理图片文件:
import fs from "fs";
export const MyPlugin = (limit = 4096) => {
return {
name: "my-plugin",
async transform(code, id) {
if (process.env.NODE_ENV !== "development") return;
if (!id.endsWith(".png")) return;
// 获取文件信息
const stat = await fs.promises.stat(id);
// 如果文件大小大于限制,则不处理
if (stat.size > limit) return;
// 读取文件并转换为 base64 格式
const buffer = await fs.promises.readFile(id);
const base64 = buffer.toString("base64");
const dataurl = `data:image/png;base64,${base64}`;
// 返回 dataurl
return `export default "${dataurl}"`;
},
};
};
在这个代码片段中,我们首先获取图片文件的大小信息。如果文件小于设定的 limit
(默认是 4KB),我们会读取文件内容,将其转换为 Base64 编码,并生成 dataurl
。
这样,我们既保留了 Vite.js 的优化功能,又能根据需求做出灵活调整。这种方式可以确保开发环境和生产环境的规则一致,避免了不必要的屎山和维护成本。