Appearance
Vite 静态资源处理
Vite 提供了强大的静态资源处理能力,支持多种资源类型和处理方式,让开发者能够高效地管理项目中的静态文件。
静态资源类型
图像资源
Vite 支持常见的图像格式:
javascript
// 导入图像资源
import logo from './assets/logo.png'
// 在 HTML 中使用
const img = document.createElement('img')
img.src = logo
// 或在 Vue 模板中
<template>
<img src="./assets/logo.png" alt="Logo" />
</template>
字体资源
// 在 CSS 中使用自定义字体
@font-face {
font-family: 'CustomFont';
src: url('./fonts/custom-font.woff2') format('woff2'),
url('./fonts/custom-font.woff') format('woff');
}
.custom-text {
font-family: 'CustomFont', sans-serif;
}
视频和音频资源
import videoFile from './assets/video.mp4'
import audioFile from './assets/audio.mp3'
// 在 HTML 中使用
const video = document.createElement('video')
video.src = videoFile
资源导入方式
静态导入
// 静态导入 - 构建时处理
import imgUrl from './assets/image.png'
import svgUrl from './assets/icon.svg'
const image = new Image()
image.src = imgUrl
动态导入
// 动态导入 - 按需加载
async function loadAsset(assetName) {
const module = await import(`./assets/${assetName}.png`)
return module.default
}
// 使用
const imagePath = await loadAsset('background')
URL 导入
// 使用 ?url 后缀获取资源 URL
import imgUrl from './assets/image.png?url'
// 使用 ?raw 后缀获取资源原始内容
import fileContent from './assets/data.txt?raw'
// 使用 ?worker 后缀创建 Web Worker
import Worker from './worker.js?worker'
Public 目录
Public 目录用途
public 目录用于存放不需要经过构建处理的静态资源:
public/
├── favicon.ico
├── robots.txt
├── manifest.json
└── images/
└── hero-bg.jpg
引用 Public 目录资源
<!-- 在 HTML 中引用 -->
<link rel="icon" href="/favicon.ico" />
<!-- 在 CSS 中引用 -->
.hero {
background-image: url('/images/hero-bg.jpg');
}
<!-- 在 JS 中引用 -->
const faviconUrl = '/favicon.ico'
Public 目录 vs 资源导入
// ❌ 错误 - 不应导入 public 目录中的文件
import '/public/some-file.js' // 这不会工作
// ✅ 正确 - 直接使用 URL
const publicFile = '/some-file.js'
// ✅ 正确 - 导入源码目录中的文件
import asset from './assets/some-file.js'
资源处理配置
资源内联限制
// vite.config.js
export default {
build: {
assetsInlineLimit: 4096 // 4KB 以下的资源将内联为 base64
}
}
自定义资源处理
// vite.config.js
export default {
assetsInclude: [
'**/*.gltf', // 包含 glTF 3D 模型文件
'**/*.bin', // 包含二进制文件
'**/*.md' // 包括 Markdown 文件
]
}
CSS 资源处理
CSS 中的资源引用
/* 相对路径引用 */
.component {
background-image: url('./assets/bg.png');
border-image: url('../images/border.svg') 30 round;
}
/* Public 目录资源 */
.hero {
background-image: url('/images/hero-bg.jpg'); /* 不会被处理,直接复制 */
}
预处理器中的资源
// SCSS 中使用资源
$bg-image: './assets/background.png';
.component {
background-image: url($bg-image);
&::before {
content: url('./assets/icon.svg');
}
}
资源优化
图像优化
// 使用现代图像格式
// vite.config.js
export default {
build: {
rollupOptions: {
output: {
assetFileNames: (assetInfo) => {
// 为不同类型的资源使用不同的命名策略
if (assetInfo.name.endsWith('.png') ||
assetInfo.name.endsWith('.jpg') ||
assetInfo.name.endsWith('.jpeg')) {
return 'assets/images/[name]-[hash][extname]'
}
return 'assets/[name]-[hash][extname]'
}
}
}
}
}
SVG 处理
// 直接导入 SVG 作为字符串
import svgContent from './assets/icon.svg?raw'
// 或作为 React 组件(如果配置了相应插件)
import Icon from './assets/icon.svg'
资源路径处理
基础路径配置
// vite.config.js
export default {
base: '/my-app/' // 部署到子路径时使用
}
构建时路径处理
// 构建后路径会自动调整
import imgUrl from './assets/image.png'
// 开发时: http://localhost:5173/src/assets/image.png
// 生产时: /my-app/assets/image-[hash].png
高级资源处理
自定义资源加载器
// plugins/resource-loader.js
export default function resourceLoader() {
return {
name: 'resource-loader',
resolveId(id) {
if (id.endsWith('.data')) {
return id
}
},
load(id) {
if (id.endsWith('.data')) {
const content = fs.readFileSync(id, 'utf-8')
return `export default ${JSON.stringify(content)}`
}
}
}
}
// 在 vite.config.js 中使用
// vite.config.js
import resourceLoader from './plugins/resource-loader'
export default {
plugins: [resourceLoader()]
}
资源预加载
<!-- 手动预加载关键资源 -->
<link rel="modulepreload" href="/assets/critical.js">
<link rel="preload" href="/assets/font.woff2" as="font" type="font/woff2" crossorigin>
条件资源加载
// 根据环境条件加载资源
async function loadConditionalAsset() {
if (import.meta.env.MODE === 'development') {
return await import('./assets/dev-data.json?raw')
} else {
return await import('./assets/prod-data.json?raw')
}
}
最佳实践
资源组织
src/
├── assets/
│ ├── images/ # 图像资源
│ ├── icons/ # 图标资源
│ ├── fonts/ # 字体文件
│ └── data/ # 数据文件
├── components/
└── public/ # 不需要构建的资源
└── favicon.ico
资源导入策略
// ✅ 推荐 - 静态导入小资源
import smallIcon from '@/assets/icons/small-icon.svg'
// ✅ 推荐 - 动态导入大资源
async function loadLargeAsset() {
const largeAsset = await import('@/assets/large-video.mp4')
return largeAsset.default
}
// ✅ 推荐 - 使用 Public 目录存放大文件
const videoUrl = '/videos/large-video.mp4'
资源缓存优化
// vite.config.js
export default {
build: {
rollupOptions: {
output: {
assetFileNames: ({ name }) => {
// 为不同类型的资源使用不同的缓存策略
const extType = name.split('.').pop()
if (['png', 'jpg', 'jpeg', 'gif', 'svg', 'webp'].includes(extType)) {
return `assets/images/[name].[hash][extname]`
}
if (['woff', 'woff2', 'ttf', 'eot'].includes(extType)) {
return `assets/fonts/[name].[hash][extname]`
}
return `assets/[name].[hash][extname]`
}
}
}
}
}
常见问题
路径问题
// ❌ 错误 - 相对路径可能不正确
const img = document.createElement('img')
img.src = './assets/image.png' // 在不同页面可能失效
// ✅ 正确 - 使用导入或绝对路径
import imgUrl from './assets/image.png'
img.src = imgUrl
// 或使用绝对路径(来自 public 目录)
img.src = '/assets/image.png'
资源大小问题
// 检查资源大小,避免过大资源影响性能
// build-plugin.js
export default function assetSizeChecker() {
return {
name: 'asset-size-checker',
generateBundle(options, bundle) {
for (const [fileName, chunk] of Object.entries(bundle)) {
if (chunk.type === 'asset' && fileName.endsWith('.png')) {
const size = chunk.source.length
if (size > 1024 * 100) { // 100KB
console.warn(`Asset ${fileName} is ${size} bytes, consider optimization`)
}
}
}
}
}
}
通过合理使用 Vite 的静态资源处理功能,您可以优化应用的加载性能,提高用户体验,并有效管理项目中的各种静态资源。