5月31日 16:17

Vite 如何加载图片、CSS 和 public 静态资源?

Vite 处理静态资源时,先分清两类文件:一类在 src 里被代码引用,会进入构建图;另一类放在 public,按原路径复制到输出目录。开发环境为了快,Vite 通常让浏览器直接请求资源;生产构建时,Rollup 会接管引用、加 hash、压缩或内联。

src 中的图片和字体怎么加载

放在 src/assets 的图片、字体、视频,只要被 JS、TS、Vue、React 组件或 CSS 引用,Vite 就能分析到它们。开发时导入结果通常是一个可访问 URL,构建后会变成带 hash 的文件名,方便长期缓存。

ts
import logoUrl from './assets/logo.png' const img = new Image() img.src = logoUrl document.body.appendChild(img)

这种方式最稳,因为 base、输出目录和文件 hash 都由 Vite 处理。不要在代码里拼 /src/assets/${name}.png,开发时可能能访问,构建后就容易失效。

?url、?raw、?inline 有什么区别

默认导入图片、字体等资源时,Vite 返回 URL。?raw 会把文件内容当字符串返回,适合文本模板、shader;?inline 会强制内联成 base64;?url 则显式要求返回资源地址。

ts
import fileUrl from './manual.pdf?url' import shader from './shader.glsl?raw' import icon from './icon.svg?inline'

内联能少一次请求,但会让 JS 或 CSS 变大,也会让缓存粒度变粗。小 SVG 可以内联,大图片不要为了省请求硬塞进 bundle。

CSS 也是模块

Vite 允许直接导入 CSS,也支持 CSS Modules 和 Sass、Less 等预处理器。开发时样式会被注入并支持 HMR;生产时会提取、压缩,并根据 chunk 关系输出。

ts
import './global.css' import styles from './button.module.css' button.className = styles.primary

CSS Modules 适合组件局部样式,全局 CSS 适合 reset、主题变量和少量基础规则。不要把所有页面样式都塞进入口文件,否则异步页面拆包后仍会被全局样式影响。

public 目录适合固定路径文件

public 下的文件会原样复制到构建输出根目录,不会被 hash、压缩或依赖分析。站点图标、robots.txt、第三方验证文件、必须固定 URL 的下载文件适合放这里。

html
<link rel="icon" href="/favicon.ico" /> <img src="/brand/banner.png" />

如果资源需要版本化缓存,就不要放 public;如果外部系统必须按固定路径访问,public 更合适。部署在子路径时要特别注意 base,根路径写死会导致线上资源 404。

常用配置怎么写

ts
import { defineConfig } from 'vite' export default defineConfig({ base: '/app/', assetsInclude: ['**/*.glb'], build: { assetsInlineLimit: 4096, rollupOptions: { output: { assetFileNames: 'assets/[name]-[hash][extname]' } } } })

assetsInclude 适合让 Vite 把自定义后缀当资源处理,比如 3D 模型或特殊二进制文件。如果需要读取内容并转换成代码,就应该写插件,而不是只加资源匹配。

追问

src/assets 和 public 应该怎么选?

被组件或样式引用、希望加 hash 的资源放 src/assets。必须固定路径、给浏览器或第三方平台直接读取的文件放 public。取舍在于是否进入构建图:进入构建图更利于缓存和路径改写,不进入构建图更直接但不受 Vite 保护。

assetsInlineLimit 调大是不是一定更快?

不一定。调大会减少请求,但会增大 JS 或 CSS 体积,首屏解析和缓存失效成本也会增加。边界是只内联很小、稳定、首屏必用的资源,大图和复用图片通常单独输出更好。

为什么生产环境图片路径变了?

生产构建会给资源加 hash,并把它们复制到输出目录,这是为了长期缓存。代码只应该使用 import 得到的 URL,不要依赖开发时看到的 /src/... 地址。常见坑是接口返回源码相对路径,构建后前端无法再访问。

CSS 为什么没有按源文件拆开?

Vite 的 CSS 输出跟 JS chunk 关系有关,不是按目录机械拆分。同步入口样式可能合并,异步页面样式可能独立输出。取舍是请求数量和缓存粒度,排查时应看构建产物和引用链,而不是只看源文件名。

标签:Vite