资源管理
Geprüfte Übersetzung ·0 % geprüft
Nuxt 使用两个目录来处理诸如样式表、字体或图像之类的资源。
public/目录中的内容会原样从服务器根目录提供。app/assets/目录按照惯例包含你希望构建工具(Vite 或 webpack)处理的所有资源。
Public 目录
public/ 目录用作静态资源的公共服务器,可通过应用程序中定义的 URL 公开访问。
你可以在应用程序代码中,或在浏览器中通过根 URL / 获取 public/ 目录中的文件。
示例
例如,引用 public/img/ 目录中的图像文件,该文件可通过静态 URL /img/nuxt.png 访问:
<template>
<img
src="/img/nuxt.png"
alt="发现 Nuxt"
>
</template>Assets 目录
Nuxt 使用 Vite(默认)或 webpack 构建和打包你的应用。这些构建工具的主要功能是处理 JavaScript 文件,但它们可以通过 插件(针对 Vite)或 加载器(针对 webpack)扩展来处理其它类型的资源,比如样式表、字体或 SVG。这一步会转换原始文件,主要是为了性能或缓存目的(例如样式表压缩或浏览器缓存失效)。
按照惯例,Nuxt 使用 app/assets/ 目录存储这些文件,但此目录不会被自动扫描,你也可以使用任何其他名称。
在应用程序代码中,你可以使用 ~/assets/ 路径引用位于 app/assets/ 目录中的文件。
示例
例如,引用一个图像文件,如果构建工具配置了处理该文件扩展名,则此文件将被处理:
<template>
<img
src="~/assets/img/nuxt.png"
alt="发现 Nuxt"
>
</template>/assets/my-file.png 这样的静态 URL 提供 app/assets/ 目录中的文件。如果你需要静态 URL,请使用 public/ 目录。静态 vs. 动态 src
当模板中的 src 是静态字符串字面量时,构建工具会将其重写为一个运行时辅助函数,以解析最终 URL。像 /img/nuxt.png 这样的公共路径会被包装,以便在页面渲染时应用你的 app.baseURL;像 ~/assets/img/nuxt.png 这样的打包路径还会变成一个导入,并解析为带哈希的输出文件。
<template>
<!-- 静态路径会被重写:app.baseURL 会在运行时应用,打包文件会带哈希。 -->
<img src="/img/nuxt.png">
<img src="~/assets/img/nuxt.png">
</template>由于 app.baseURL 是在运行时应用的,即使基础 URL 只在部署时才知道(例如通过 NUXT_APP_BASE_URL 设置),静态公共路径也能正常工作,而且无论文件是否经过构建处理都可以使用。这种解析只会发生在构建工具能够看到的字面量路径上。
一个值在运行时拼接出来的绑定 :src 对构建工具来说是不可见的,因此不会发生这些重写。该字符串会原样使用:
<template>
<!-- 这不会生效:路径是在运行时拼接的,所以 Vite 从未将其视为导入。 -->
<img :src="`~/assets/img/${name}.png`">
</template>因此,像 /img/${name}.png 这样在运行时构建的公共路径不会添加 app.baseURL 前缀。如果你的应用部署在源站根目录以下,请使用 useRuntimeConfig().app.baseURL 为其添加前缀(例如通过 joinURL)。
下面的各节将介绍当路径只在运行时才知道时,如何处理每种情况。
公共资源
如果文件不需要经过处理或添加哈希,请将它们放入 public/ 目录,并通过 URL 引用:
<script setup lang="ts">
const props = defineProps<{
name: string
}>()
const imageUrl = computed(() => `/img/${props.name}.png`)
</script>
<template>
<img
:src="imageUrl"
:alt="props.name"
>
</template>public/ 中的文件会保留原始文件名。
使用 Vite 的打包资源
下面的方法专用于 Vite,也就是 Nuxt 的默认构建器。
当可能的文件是已知的时,请显式列出它们的导入:
<script setup lang="ts">
const props = defineProps<{
theme: 'light' | 'dark'
}>()
const logos = {
light: () => import('./assets/img/logo-light.png?url'),
dark: () => import('./assets/img/logo-dark.png?url'),
}
const logoUrl = (await logos[props.theme]()).default
</script>
<template>
<img
:src="logoUrl"
alt="Nuxt"
>
</template>每个导入都使用字面量路径,因此 Vite 可以在构建时找到这两个文件,同时在运行时只加载选中的模块。
当很多文件共享同一个目录和扩展名时,使用 变量动态导入,而不是逐个列出每个文件:
async function getImageUrl (name: string) {
const image = await import(`./assets/img/${name}.png?url`)
return image.default
}在这个示例中,只有文件名可以是动态的。在导入中保留目录和扩展名,可以让 Vite 在构建时找到可能的文件。
对于更广泛的模式,或者用于显式映射可用文件,请使用 import.meta.glob:
const images = import.meta.glob<string>('./assets/img/*.{png,jpg,svg}', {
query: '?url',
import: 'default',
})
async function getImageUrl (name: string) {
const load = images[`./assets/img/${name}.png`]
if (!load) {
throw new Error(`Unknown image: ${name}`)
}
return await load()
}Glob 导入默认是懒加载的。如果 URL 必须同步可用,请添加 eager: true:
const images = import.meta.glob<string>('./assets/img/*.{png,jpg,svg}', {
query: '?url',
import: 'default',
eager: true,
})每个匹配到的资源仍然会包含在构建输出中。懒加载导入会按需加载每个匹配项,而急切加载的 glob 会预先加载所有匹配项,可能会增加初始 JavaScript 体积,或将小型资源内联。
new URL(..., import.meta.url) 模式 不适用于 SSR。