1、如何将图片资源变成base64?
vite中要将图片资源转成base64而不是提取成网络资源,需要配置build.assetsInlineLimit参数,表示小于该值的图片资源都会被内敛,减少网络请求数。
2、问题:vite4之前的版本包括vite4,该配置对svg无效,导致有很多细小的svg会发起网络请求,得不尝失。
3、如何解决?
-
对这个问题的讨论,可以追溯到2020年,有兴趣的朋友可以看看以下issues.
-
直到最近,终于给出了解决方案。大家可以看看以下PR。
-
采用何种方式来编码svg?
-
mini-svg-data-uri的作者提到了为什么不使用base64编码svg,并给出了自己的方案codepen.io/tigt/post/o…。 -
这篇文章也提到了不使用base64编码svg的原因。css-tricks.com/probably-do…
-
而vite中不采用base64编码也不采用
mini-svg-data-uri。为什么?PR中给出了以下两个理由- colors minification should be done ahead of time or with a plugin with other optimizations (using svgo for example)
- using multiple
replaceAll(node 15) which is faster than encodeURI or regexes or one regex with match function
意思是:
- 颜色压缩应该提前完成,或者使用其他优化的插件来完成(例如使用 svgo)。
- 使用多个
replaceAll方法(Node 15 版本)比使用 encodeURI 或正则表达式,或者使用带有匹配函数的一个正则表达式更快。
-
-
Vite5解决了这个问题,那么对于vite4及以前版本该如何解决?
我编写了一个插件来转换svg,转换代码取至上述PR。
以下是转换svg的代码。
// Inspired by https://github.com/iconify/iconify/blob/main/packages/utils/src/svg/url.ts function svgToDataURL(content: Buffer): string { const stringContent = content.toString() // If the SVG contains some text, any transformation is unsafe, and given that double quotes would then // need to be escaped, the gain to use a data URI would be ridiculous if not negative if (stringContent.includes('<text')) { return `data:image/svg+xml;base64,${content.toString('base64')}` } else { return ( 'data:image/svg+xml,' + stringContent .trim() .replaceAll('"', "'") .replaceAll('%', '%25') .replaceAll('#', '%23') .replaceAll('<', '%3c') .replaceAll('>', '%3e') // Spaces are not valid in srcset it has some use cases // it can make the uncompressed URI slightly higher than base64, but will compress way better // https://github.com/vitejs/vite/pull/14643#issuecomment-1766288673 .replaceAll(/\s+/g, '%20') ) } }如何使用?
import { resolve } from "path"; import { defineConfig } from "vite"; import vue from "@vitejs/plugin-vue"; import { inlineSvgPlugin } from "./plugins/inlineSvg"; export default defineConfig(({ command, mode }) => { const isProduction = mode == "production"; return { plugins: [ vue({ isProduction, }), inlineSvgPlugin({ assetsInlineLimit: 10 * 1024, }), ], resolve: { alias: { "@/": `${resolve(__dirname, "src")}/`, }, }, build: { chunkSizeWarningLimit: 500, cssCodeSplit: true, //css 拆分 sourcemap: false, assetsInlineLimit: 5 * 1024, //小于该值 图片将打包成Base64 minify: "terser", //是否压缩 }, }; }); 导入
inlineSvgPlugin并传入assetsInlineLimit即可,含义与build.assetsInlineLimit一致。若没有传,则取build.assetsInlineLimit的值。优化结果:svg资源文件个数60个->4个
-
插件的代码放在了github上,有兴趣的朋友自行领取。
github地址:github.com/fishermanxz…
插件目前只支持
import导入的图片和img标签src引用的图片。即以下两种情况。<template> <img src="@/assets/1.svg"/> </template>或者
import svg from "@/assets/1.svg"暂不支持css导入的svg。
以上就是vite中关于svg内敛的探讨,如果对您有帮助,请您高抬贵手帮忙点个赞~