Skip to content
静态资源处理

静态资源处理

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。