静态资源处理
Vite 对静态资源的处理非常灵活:导入为 URL、字符串、内联 base64,支持 Glob 批量导入、JSON 导入、Web Worker 等。
资源导入方式
导入为 URL(默认)
import imgUrl from './img.png'
// imgUrl = '/src/img.png'(开发时)
// imgUrl = '/assets/img.hash.png'(构建时)
document.getElementById('hero').src = imgUrl这是最常见的用法。支持的资源类型:图片(png/jpg/gif/svg/webp/avif)、字体(woff/woff2/eot/ttf/otf)、视频、音频等。
显式 URL 导入
// 使用 ?url 后缀显式获取 URL
import workletURL from 'extra-scalloped-border/worklet.js?url'
// workletURL = '/@fs/.../worklet.js'
CSS.paintWorklet.addModule(workletURL)导入为字符串(Raw)
// 使用 ?raw 后缀导入为纯文本字符串
import txt from './file.txt?raw'
// txt = "文件内容字符串"
import shader from './shader.glsl?raw'
// 用作文本处理(如 WebGL Shader 代码)
导入为 Worker
// 使用 ?worker 后缀导入为 Web Worker 构造函数
import MyWorker from './worker.js?worker'
const worker = new MyWorker()
worker.postMessage('hello')Worker 构建产物会被拆分为独立 chunk。
Shared Worker
import MySharedWorker from './worker.js?sharedworker'
const worker = new MySharedWorker()内联 (base64)
// 使用 ?inline 后缀强制内联为 base64(无视 assetsInlineLimit)
import imgBase64 from './small-img.png?inline'
// imgBase64 = "data:image/png;base64,iVBORw0KGgo..."
public 目录
public/ 目录下的资源不会被构建处理,直接复制到输出目录。引用时使用绝对路径(以 / 开头):
public/
├── favicon.ico → /favicon.ico
├── robots.txt → /robots.txt
└── images/
└── logo.png → /images/logo.png// 错误:不能在 JS 中 import public 中的文件
import logo from '/images/logo.png' // ❌ 不会工作
// 正确:直接使用绝对路径字符串
<img src="/images/logo.png" alt="logo" />public vs assets
| 维度 | public/ |
assets/(src 中 import) |
|---|---|---|
| 构建处理 | ❌ 不经过,原样复制 | ✅ 经过构建、hash、压缩 |
| 引用方式 | HTML/JS 中绝对路径 | JS import,Vite 返回处理后 URL |
| 文件名 | 保持原名 | 添加 hash(缓存策略) |
| 内联 base64 | 不可能 | 小文件自动内联 |
| 适用场景 | 不需要处理的文件:robots.txt、favicon | 需要构建优化的资源:组件图片、图标 |
💡 最佳实践:需要 hash 缓存和构建优化的资源放
assets,不需要处理的放public。
new URL() 构造导入
Vite 支持 new URL() 构造动态导入:
// 静态
const imgUrl = new URL('./img.png', import.meta.url).href
// 开发: http://localhost:5173/src/img.png
// 构建: /assets/img.hash.png
// 动态(支持模板字符串)
function getImageUrl(name) {
return new URL(`./dir/${name}.png`, import.meta.url).href
}🚨 陷阱:
new URL()的动态参数必须是模板字符串且变量部分是完整文件名或路径段,不能是纯变量拼接。new URL(variable, import.meta.url)不会工作。
Glob 导入(多文件批量导入)
Vite 支持通过 import.meta.glob 批量导入文件:
// 1. 默认:懒加载,返回 { path: () => Promise }
const modules = import.meta.glob('./dir/*.js')
// {
// './dir/foo.js': () => import('./dir/foo.js'),
// './dir/bar.js': () => import('./dir/bar.js'),
// }
// 使用
const mod = await modules['./dir/foo.js']()
// 2. 直接导入(Eager):{ path: module }
const modules = import.meta.glob('./dir/*.js', { eager: true })
// {
// './dir/foo.js': { default: ..., namedExport: ... },
// './dir/bar.js': { default: ..., namedExport: ... },
// }
// 3. 导入为 URL
const urls = import.meta.glob('./images/*.png', {
query: '?url',
import: 'default',
eager: true,
})
// 4. 导入为字符串
const texts = import.meta.glob('./articles/*.md', {
query: '?raw',
import: 'default',
})
// 5. 支持嵌套匹配
const modules = import.meta.glob([
'./components/**/*.jsx',
'./pages/**/*.jsx',
])
// 6. 排除模式
const modules = import.meta.glob('./dir/*.js', {
exclude: ['./dir/bar.js'],
})| 选项 | 说明 |
|---|---|
eager |
true:直接导入;false(默认):懒加载 |
query |
添加后缀,如 '?raw'、'?url' |
import |
指定导出名,如 'default'、'namedExport' |
exclude |
排除匹配的文件 |
Glob 遍历文件系统
// 适合批量加载 Markdown 文章
const articles = import.meta.glob('./posts/*.md', {
eager: true,
query: '?raw',
import: 'default',
})
Object.entries(articles).forEach(([path, content]) => {
console.log(path, content.substring(0, 50))
})JSON 与命名导入
// 导入整个 JSON
import pkg from './package.json'
console.log(pkg.name)
// 具名导入(支持 Tree Shaking)
import { name, version } from './package.json'
console.log(name, version)SVG 处理
方式一:导入为 URL(默认)
import logoUrl from './logo.svg'
<img src={logoUrl} />方式二:导入为组件(需要插件)
npm i -D vite-plugin-svgr// vite.config.js
import svgr from 'vite-plugin-svgr'
export default defineConfig({
plugins: [svgr()],
})// 直接作为 React 组件使用
import Logo from './logo.svg?react'
<Logo width={48} height={48} />方式三:导入为 Raw 字符串(内联 SVG)
import svgRaw from './icon.svg?raw'
<div dangerouslySetInnerHTML={{ __html: svgRaw }} />WebAssembly (WASM)
// Vite 原生支持 .wasm 文件导入
import init, { add } from './add.wasm'
const instance = await init()资源内联阈值
export default defineConfig({
build: {
// 小于此值的资源会被内联为 base64(单位:字节)
assetsInlineLimit: 4096, // 4KB
// 设为 0 禁用内联
// assetsInlineLimit: 0,
},
})⚡ 性能提示:4KB 是经验值。太小则 HTTP 请求多,太大则 base64 增加 JS 体积。CDN 使用 HTTP/2 时,可适当减小阈值甚至设为 0。