前言
项目中使用一大一小两张图片
但是打包结果中并未发现小图
这是由于 Vite 默认的优化手段,当图片小于 4KB 时,会处理为 base64,在打包后的 JS 中可以查看
执行 npm run preview
查看线上环境发现,打印的图片路径也为base64,大部分情况下,这种差异不会有影响,但如果强制要求图片必须完全一致,就需要阻止 Vite 这个默认优化手段。
方法一:取消默认优化
通过 assetsInlineLimit
将默认的 4096 变为 0,这个选项只会影响生产环境
export default defineConfig({
plugins: [react()],
build: {
assetsInlineLimit: 0,
},
})
分别执行 npm run build
和 npm run preview
,可以发现小图也正常处理了
但是丢失了 Vite 本身的优化行为,所以并不推荐这种方法。
方法二:自己写一个Vite插件(推荐)
为了确保图片在开发和生产环境下的完全一致,但又要保证 Vite 默认优化行为,只能修改开发环境,保证与开发环境下的优化机制一致。
Vite 配置选项里并没有针对开发环境的配置,需要自己写一个
const myPlugin = (limit = 4096) => {
return {
name: "my-plugin",
transform(code, id) {
console.log(id)
if (process.env.NODE_ENV !== "development") {
return
}
},
}
}
export default defineConfig({
plugins: [react(), myPlugin()],
})
Vite 基于 Rollup 的插件系统,transform
是 rollup 钩子,用于在代码模块被加载和打包之前,对模块内容进行修改或转换。code 是模块的内容,id 是模块的路径。
使用 node 环境下的 fs 读取文件状态并查看
import fs from "node:fs"
const myPlugin = (limit = 4096) => {
return {
name: "my-plugin",
async transform(code, id) {
if (process.env.NODE_ENV !== "development") {
return
}
// 根据需求筛选要处理的文件
if (!id.endsWith(".png") || !id.endsWith(".jpg")) {
return
}
const stat = await fs.promises.stat(id)
console.log(stat)
},
}
}
只需要对 size 进行判断,并在恰当时机(小于4kb)转为 base64 即可
import fs from "node:fs"
const myPlugin = (limit = 4096) => {
return {
name: "my-plugin",
async transform(code, id) {
if (process.env.NODE_ENV !== "development") {
return
}
if (!id.endsWith(".png") && !id.endsWith(".jpg")) {
return
}
const stat = await fs.promises.stat(id)
if (stat.size > limit) {
return
}
const buffer = await fs.promises.readFile(id)
const base64 = buffer.toString("base64")
const dataurl = `data:image/png;base64,${base64}`
console.log(dataurl)
},
}
}
最后将处理好的 base64 返回即可
const myPlugin = (limit = 4096) => {
return {
name: "my-plugin",
async transform(code, id) {
if (process.env.NODE_ENV !== "development") {
return
}
if (!id.endsWith(".png") && !id.endsWith(".jpg")) {
return
}
const stat = await fs.promises.stat(id)
if (stat.size > limit) {
return
}
const buffer = await fs.promises.readFile(id)
const base64 = buffer.toString("base64")
const dataurl = `data:image/png;base64,${base64}`
return {
code: `export default ${JSON.stringify(dataurl)}`,
}
},
}
}
查看开发环境
如果想要将插件发布到npm,请看本人另一篇文章:如何将开发的vite插件发布到npm