Skip to content
On this page

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 的静态资源处理功能,您可以优化应用的加载性能,提高用户体验,并有效管理项目中的各种静态资源。