知海

静态资源处理

vite-main使用指南

静态资源处理

将资源导入为 URL

导入静态资源会返回解析后的公共 URL 以供使用:

js twoslash 复制代码
import 'vite/client'
// ---cut---
import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl

例如,imgUrl 在开发环境会是 /src/img.png,在生产构建中会变成 /assets/img.2d8efhg.png

其行为类似于 webpack 的 file-loader。区别在于导入既可以使用绝对公共路径(开发时基于项目根目录),也可以使用相对路径。

  • CSS 中的 url() 引用以相同方式处理。
  • 如果使用 Vue 插件,Vue SFC 模板中的资源引用会自动转换为导入。
  • 常见的图片、媒体和字体文件类型会自动被识别为资源。你可以使用 assetsInclude 选项 扩展内部列表。
  • 被引用的资源会作为构建资源图的一部分,获得哈希文件名,并可被插件用于优化处理。
  • 小于 assetsInlineLimit 选项 字节的资源会被内联为 Base64 数据 URL。
  • Git LFS 占位符会自动排除在内联之外,因为它们不包含所代表文件的内容。如需内联,请确保在构建前通过 Git LFS 下载文件内容。
  • 默认情况下,TypeScript 不会将静态资源导入识别为有效模块。要解决此问题,请引入 vite/client

::: tip 通过 url() 内联 SVG
当通过 JS 手动构造 url() 并传入 SVG 的 URL 时,变量需要用双引号包裹。

js twoslash 复制代码
import 'vite/client'
// ---cut---
import imgUrl from './img.svg'
document.getElementById('hero-img').style.background = `url("${imgUrl}")`

显式 URL 导入

内部列表或 assetsInclude 中未包含的资源,可以使用 ?url 后缀显式导入为 URL。例如,这在导入 Houdini Paint Worklets 时非常有用。

js twoslash 复制代码
import 'vite/client'
// ---cut---
import workletURL from 'extra-scalloped-border/worklet.js?url'
CSS.paintWorklet.addModule(workletURL)

显式内联处理

资源可以使用 ?inline?no-inline 后缀分别显式导入为内联或非内联。

js twoslash 复制代码
import 'vite/client'
// ---cut---
import imgUrl1 from './img.svg?no-inline'
import imgUrl2 from './img.png?inline'

将资源导入为字符串

资源可以使用 ?raw 后缀导入为字符串。

js twoslash 复制代码
import 'vite/client'
// ---cut---
import shaderString from './shader.glsl?raw'

将脚本导入为 Worker

脚本可以使用 ?worker?sharedworker 后缀导入为 Web Worker。

js twoslash 复制代码
import 'vite/client'
// ---cut---
// 生产构建中的独立 chunk
import Worker from './shader.js?worker'
const worker = new Worker()
js twoslash 复制代码
import 'vite/client'
// ---cut---
// sharedworker
import SharedWorker from './shader.js?sharedworker'
const sharedWorker = new SharedWorker()
js twoslash 复制代码
import 'vite/client'
// ---cut---
// 内联为 Base64 字符串
import InlineWorker from './shader.js?worker&inline'

查看 Web Worker 部分 了解更多详情。

public 目录

如果你有以下资源:

  • 在源代码中从未被引用(例如 robots.txt
  • 必须保持完全相同的文件名(不进行哈希)
  • ……或者你只是不想为了获取 URL 而先导入资源

那么你可以将资源放在项目根目录下的专用 public 目录中。此目录中的资源在开发环境中会以根路径 / 提供服务,并原样复制到 dist 目录的根目录。

该目录默认为 <root>/public,但可以通过 publicDir 选项 进行配置。

注意,你应始终使用根绝对路径来引用 public 资源——例如,public/icon.png 在源代码中应引用为 /icon.png。 tip 在导入和 public 目录之间做选择

一般而言,除非你确实需要 public 目录提供的保证,否则请优先导入资源

new URL(url, import.meta.url)

import.meta.url 是一个原生 ESM 特性,用于暴露当前模块的 URL。将其与原生 URL 构造函数 结合,我们可以使用来自 JavaScript 模块的相对路径获取静态资源的完整解析后 URL:

js 复制代码
const imgUrl = new URL('./img.png', import.meta.url).href

document.getElementById('hero-img').src = imgUrl

这在现代浏览器中可以原生运行——实际上,Vite 在开发环境中完全不需要处理这段代码!

此模式还支持通过模板字符串创建动态 URL:

js 复制代码
function getImageUrl(name) {
  // 注意:这不包含子目录中的文件
  return new URL(`./dir/${name}.png`, import.meta.url).href
}

在生产构建期间,Vite 会执行必要的转换,以便即使在打包和资源哈希之后,URL 仍然指向正确的位置。但是,URL 字符串必须是静态的才能被分析,否则代码将保持原样,如果 build.target 不支持 import.meta.url,可能会导致运行时错误。

js 复制代码
// Vite 不会转换此代码
const imgUrl = new URL(imagePath, import.meta.url).href
``` details 工作原理

Vite 会将 getImageUrl 函数转换为:

js 复制代码
import __img0png from './dir/img0.png'
import __img1png from './dir/img1.png'

function getImageUrl(name) {
  const modules = {
    './dir/img0.png': __img0png,
    './dir/img1.png': __img1png,
  }
  return new URL(modules[`./dir/${name}.png`], import.meta.url).href
}

::: warning 不适用于 SSR
此模式不适用于使用 Vite 进行服务端渲染(SSR)的情况,因为 import.meta.url 在浏览器和 Node.js 中具有不同的语义。服务端 bundle 也无法提前确定客户端主机 URL。

帮助我们改进文档

发现翻译问题或内容错误?请告诉我们。