在 Vite 中如何处理静态资源
静态资源处理是前端工程经常遇到的问题,在真实的工程中不仅仅包含了动态执行的代码,也不可避免地要引入各种静态资源,如图片
、JSON
、Worker 文件
、Web Assembly 文件
等等。
在 Vite 中处理静态资源(如图片、字体、CSS/JS 文件等)主要通过自动路径解析、内联优化、显式后缀控制等机制实现,同时支持生产环境下的哈希命名和压缩优化。接下来我会通过例子,配合官方文档介绍详细的处理方法。《官方文档地址》,本文章篇幅较长,但我希望大家能耐心看完,,对 vite 的学习有很大帮助!!!!
🧩 一、基础导入方式(自动 URL 处理)
接下来让我们在目前的脚手架项目来进行实际的编码,你可以在 Vite 的配置文件中配置一下别名,方便后续的图片引入:
// vite.config.ts
import path from 'path';{resolve: {// 别名配置alias: {'@assets': path.join(__dirname, 'src/assets')}}
}
通过常规 import
导入资源时,Vite 会返回解析后的 公共 URL,并根据文件大小决定是否内联为 Base64:
import imgUrl from './assets/image.png';
document.getElementById('img').src = imgUrl;
- 开发环境:路径为
/src/assets/image.png
- 生产环境:自动哈希化路径,如
/assets/image.2d8efhg.png
- 内联规则:文件体积 <
assetsInlineLimit
(默认 4KB)时转为 Base64,减少 HTTP 请求 。
⚙️ 二、使用组件加载
SVG 组件加载在不同的前端框架中的实现不太相同,社区中也已经了有了对应的插件支持:(其他框架项目可以去查找相关的资料)
-
Vue3 项目中可以引入 vite-svg-loader。
-
React 项目使用 vite-plugin-svgr插件。
现在让我们在 vue3 脚手架项目中安装对应的依赖:
npm install vue-svg-loader --save-dev
或:
yarn add vue-svg-loader --dev
在项目的 vite.config.js
文件中配置插件:
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import svgLoader from 'vite-svg-loader';export default defineConfig({plugins: [vue(),svgLoader({// 默认情况下,它会将 SVG 文件转换为 Vue 组件defaultImport: 'url', // 或者 'component'}),],
});
假设将你的 SVG 文件放在 src/assets/icons
文件夹中。例如:
src/
└── assets/└── icons/└── my-icon.svg
配置完成后,你可以直接导入 SVG 文件作为 Vue 组件:
<template><div><MyIcon class="custom-icon" /></div>
</template><script setup lang="ts">
import MyIcon from './assets/icons/my-icon.svg';
</script><style scoped>
/* 这里可以添加针对 SVG 的样式 */
.custom-icon {width: 100px;height: 100px;fill: blue;
}
</style>
💡 三、显式处理方式(后缀控制)
通过后缀指定资源处理行为:
-
?url
:强制作为 URL 引入(适用于非标准资源)import workletUrl from './paint-worklet.js?url'; CSS.paintWorklet.addModule(workletUrl);
-
?raw
:作为原始字符串引入import shaderCode from './shader.glsl?raw';
-
?worker
/?sharedworker
:脚本转为 Web Worker(之后我会在后面的文章单独介绍)import Worker from './data-processor.js?worker'; const worker = new Worker(); // 生产环境自动分离为独立 chunk
-
?inline
:强制内联为 Base64import inlineIcon from './icon.png?inline';
-
?asset
(Electron 场景):获取文件物理路径import iconPath from '../../build/icon.ico?asset'; // 输出:path.join(__dirname, "./chunks/icon-xxx.ico") ``` [1](@ref)
📂 四、其他静态资源
除了上述的一些资源格式,Vite 也对下面几类格式提供了内置的支持:
-
媒体类文件,包括
mp4
、webm
、ogg
、mp3
、wav
、flac
和aac
。 -
字体类文件。包括
woff
、woff2
、eot
、ttf
和otf
。 -
文本类。包括
webmanifest
、pdf
和txt
。
也就是说,你可以在 Vite 将这些类型的文件当做一个 ES 模块来导入使用。如果你的项目中还存在其它格式的静态资源,你可以通过assetsInclude
配置让 Vite 来支持加载:
// vite.config.tsexport default defineConfig({// ... 已有配置 ...assetsInclude: ['**/*.jpg','**/*.png','**/*.gif','**/*.webp','**/*.woff','**/*.woff2','**/*.ttf','**/*.eot'],build: {// ... 已有配置 ...assetsInlineLimit: 4096 // 小于4KB的资源转为base64}
});
1.图片资源 (存放在 src/assets/images/)
<script setup lang="ts">
// 直接引用
import logo from '@/assets/images/logo.png';// 或通过路径拼接
const dynamicImage = new URL(`./assets/images/${name}.png`, import.meta.url).href;
</script><template><img :src="logo" alt="logo"><img :src="dynamicImage" alt="dynamic">
</template>
2.字体文件 (存放在 src/assets/fonts/)
/* 在CSS中引用 */
@font-face {font-family: 'MyFont';src: url('@/assets/fonts/my-font.woff2') format('woff2');
}
3.JSON文件 (存放在 src/assets/data/)
// 直接导入JSON
import config from '@/assets/data/config.json';// 动态导入JSON
const dynamicData = await import(`@/assets/data/${pageName}.json`);
4.公共资源 (存放在 public/ 目录)
<!-- 直接使用相对路径 -->
<img src="/public-image.jpg" alt="public image">
public
目录的使用时需要注意:
存放无需处理的静态资源(如 robots.txt
、保留原名的文件):
- 路径规则:直接放在
<root>/public
下,通过根路径引用(如/icon.png
) - 构建行为:原样复制到输出目录(
dist
),不经过哈希或压缩处理 。
⚠️ 注意:
- 避免在 JS 中引用
public
资源,否则路径可能错误- 内容图片建议放
public
,小图标或需 Base64 内联的资源放src/assets
🏗️ 五、生产环境优化策略
1.单文件 或 内联
在 Vite 中,所有的静态资源都有两种构建方式,一种是打包成一个单文件,另一种是通过 base64 编码的格式内嵌到代码中。
Vite 中内置的优化方案是下面这样的:
-
如果静态资源体积 >= 4KB,则提取成单独的文件
-
如果静态资源体积 < 4KB,则作为 base64 格式的字符串内联
上述的4 KB
即为提取成单文件的临界值,当然,这个临界值你可以通过build.assetsInlineLimit
自行配置,如下代码所示:
// vite.config.ts
{build: {// 8 KBassetsInlineLimit: 8 * 1024}
}
svg 格式的文件不受这个临时值的影响,始终会打包成单独的文件,因为它和普通格式的图片不一样,需要动态设置一些属性
2.图片压缩 (强烈推荐)
图片资源的体积往往是项目产物体积的大头,如果能尽可能精简图片的体积,那么对项目整体打包产物体积的优化将会是非常明显的。在 JavaScript 领域有一个非常知名的图片压缩库imagemin,作为一个底层的压缩工具,前端的项目中经常基于它来进行图片压缩,比如 Webpack 中大名鼎鼎的image-webpack-loader
。社区当中也已经有了开箱即用的 Vite 插件——vite-plugin-imagemin
,首先让我们来安装它:
npm install vite-plugin-imagemin imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo -D
随后在 Vite 配置文件中引入:
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { resolve } from "path";
import viteImagemin from "vite-plugin-imagemin";
// ... 其他已有导入 ...export default defineConfig({// ... 其他配置保持不变 ...plugins: [vue(),// ... 已有插件 ...viteImagemin({gifsicle: {optimizationLevel: 7,interlaced: false},mozjpeg: {quality: 75,progressive: true},// 无损压缩配置,无损压缩下图片质量不会变差optipng: {optimizationLevel: 7},// 有损压缩配置,有损压缩下图片质量可能会变差pngquant: {quality: [0.8, 0.9],speed: 4},svgo: {plugins: [{ name: 'removeViewBox' },{ name: 'removeEmptyAttrs', active: false }]}})]
});
⚙️ 六、配置项调整
在 vite.config.js
中定制行为:
export default {// 静态资源基础路径(CDN 部署时使用)base: '/dist/', // 扩展资源检测类型assetsInclude: ['*.pdf', '*.csv'],// 调整内联阈值(单位:字节)build: {assetsInlineLimit: 8 * 1024, // 8KBtarget: 'es2015' // 构建目标}
};
``` [1](@ref) [47](@ref)---### 📂 六、动态路径生成
结合 `import.meta.url` 解析资源路径(SSR 不可用):
```javascript
// 动态生成图片 URL
function getImageUrl(name) {return new URL(`./imgs/${name}.png`, import.meta.url).href;
}
- 要求:路径必须是静态字符串,否则生产环境可能报错
总结:不同场景推荐方式
场景 | 推荐方式 | 示例 |
---|---|---|
图片/字体等常规资源 | 默认 import | import img from './logo.png' |
非标准资源(如 Houdini) | ?url 后缀 | import worklet from './worklet.js?url' |
原始内容(如 GLSL 代码) | ?raw 后缀 | import code from './shader.glsl?raw' |
无需处理的文件(如 PDF) | 放 public 目录 | 访问路径:/manual.pdf |
Electron 主进程资源路径 | ?asset 后缀 | import exe from './app.exe?asset' |