shared/ 目录允许你共享可在 Vue 应用和 Nitro 服务器中使用的代码。
shared/ 目录在 Nuxt v3.14+ 中可用。shared/ 目录中的代码不能导入任何 Vue 或 Nitro 代码。为什么你不能混用 Vue 和 Nitro 代码
Nuxt 会构建两个彼此独立的包:Vue 应用(客户端和服务端渲染)以及 Nitro 服务器(API 路由、服务器中间件、服务器插件)。它们彼此独立打包,并运行在不同的上下文中。shared/ 目录中的代码会被两个包同时使用,因此不能从任一侧进行导入。
Nitro 中的 Vue 应用代码
组件和组合式函数需要 Vue 应用运行时,并且通常还需要 Nuxt 上下文(例如 useNuxtApp() 或 useRoute()),而 Nitro 中不存在这些内容。将它们导入到服务器代码中可能会导致构建错误或运行时错误,并且还可能把 Vue 应用的依赖带入你的服务器包中。
Vue 应用中的 Nitro 代码
仅限服务器的代码(例如 Node API、Nitro 工具函数或服务器路由处理器)绝不能在浏览器中运行。将其导入到你的应用中可能会破坏客户端构建、在浏览器中引发运行时错误,或者把服务器逻辑泄露到客户端包里。
仅类型导入
import type 会在编译时被擦除,不会把运行时代码拉入另一个包中,因此跨边界只导入类型看起来可能可行。即便如此,也请把共享类型(例如 API 响应类型)放在 shared/types/ 中,因为它们会在两个上下文中自动导入。这样可以保持边界清晰,避免以后不小心把类型导入变成值导入,并且也符合 Nuxt 为应用、服务器和共享代码分别设置的 类型上下文。
用法
方法 1: 命名导出
export const capitalize = (input: string) => {
return input[0] ? input[0].toUpperCase() + input.slice(1) : ''
}
方法 2: 默认导出
export default function (input: string) {
return input[0] ? input[0].toUpperCase() + input.slice(1) : ''
}
现在你可以在 Nuxt 应用和 server/ 目录中使用这些自动导入的工具了。
<script setup lang="ts">
const hello = capitalize('hello')
</script>
<template>
<div>
{{ hello }}
</div>
</template>
export default defineEventHandler((event) => {
return {
hello: capitalize('hello'),
}
})
文件如何被扫描
只有位于 shared/utils/ 和 shared/types/ 目录下的文件会被自动导入。位于这些目录子目录中的文件不会被自动导入,除非你将这些子目录添加到 imports.dirs 和 nitro.imports.dirs。
-| shared/
---| capitalize.ts # 不会自动导入
---| formatters
-----| lower.ts # 不会自动导入
---| utils/
-----| lower.ts # 自动导入
-----| formatters
-------| upper.ts # 不会自动导入
---| types/
-----| bar.ts # 自动导入
你在 shared/ 文件夹中创建的其他任何文件,都必须使用 #shared 别名手动导入(该别名由 Nuxt 自动配置):
// For files directly in the shared directory
import capitalize from '#shared/capitalize'
// 对于位于子目录中的文件
import lower from '#shared/formatters/lower'
// 对于 utils 内某文件夹中的文件
import upper from '#shared/utils/formatters/upper'
此别名确保无论导入文件位置在哪里,导入路径都保持一致。