基于源码深度解析
2026-03-18 | 技术深度解读
第一部分:基础架构
第二部分:Nuxt 实例
第三部分:运行时
第四部分:数据与路由
Nuxt 3 是基于 Vue 3 的全栈框架,提供服务端渲染、静态生成、自动导入等特性。
核心特性
技术栈
┌─────────────────────────────────────────┐
│ Nuxt 3 全栈架构 │
├─────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌─────────┐│
│ │ Client │ │ Server │ │ Build ││
│ └──────────┘ └──────────┘ └─────────┘│
│ ↓ ↓ ↓ │
│ ┌─────────────────────────────────────┐│
│ │ Nuxt App (运行时核心) ││
│ │ • createNuxtApp() ││
│ │ • Plugin System ││
│ │ • Hook System ││
│ └─────────────────────────────────────┘│
│ ↓ │
│ ┌──────────┐ ┌──────────┐ ┌─────────┐│
│ │ useFetch │ │ useRouter│ │ useState││
│ └──────────┘ └──────────┘ └─────────┘│
│ ↓ │
│ ┌─────────────────────────────────────┐│
│ │ Nitro Server Engine ││
│ └─────────────────────────────────────┘│
└─────────────────────────────────────────┘
1. Nuxt 初始化 - 加载配置、解析模块
2. Vite 构建 - 客户端和服务端代码打包
3. Nitro 打包 - 服务端引擎构建
4. 路由生成 - 基于文件系统生成路由
5. 预渲染 - 静态页面生成(可选)
// nuxt.ts - Nuxt 初始化流程
export async function loadNuxt(opts: LoadNuxtOptions) {
const nuxt = await createNuxt(opts)
await initNuxt(nuxt)
return nuxt
}
核心模块
模块生命周期
模块定义: 使用 defineNuxtModule 创建可复用模块,支持钩子、配置和依赖管理。
// nuxt.ts - 核心数据结构
export interface Nuxt {
// 核心配置
options: NuxtConfig
hooks: Hookable<NuxtHooks>
// 构建信息
builder: NuxtBuilder | null
vfs: Record<string, string>
// 模块管理
modules: NuxtModule[]
plugins: NuxtPlugin[]
// 资源
templates: NuxtTemplate[]
imports: Import[]
components: Component[]
}
// Nuxt 实例是整个应用的核心
// 管理配置、模块、插件、模板等
// nuxt.ts - 创建 Nuxt 实例
export async function createNuxt(options: NuxtOptions) {
// 1. 创建基础实例
const nuxt: Nuxt = {
options,
hooks: createHooks(),
vfs: {},
modules: [],
plugins: [],
templates: [],
imports: [],
components: [],
// ... 其他属性
}
// 2. 设置构建器
nuxt.builder = await loadBuilder(nuxt)
// 3. 返回实例
return nuxt
}
// 创建钩子系统
function createHooks() {
return createHooks<NuxtHooks>()
}
// nuxt.ts - 初始化 Nuxt
export async function initNuxt(nuxt: Nuxt) {
// 1. 执行 modules:before 钩子
await nuxt.callHook('modules:before')
// 2. 解析和安装模块
await resolveModules(nuxt)
// 3. 执行 modules:done 钩子
await nuxt.callHook('modules:done')
// 4. 生成模板
await generateTemplates(nuxt)
// 5. 准备构建
await nuxt.callHook('ready')
}
// 模块解析是初始化的核心
async function resolveModules(nuxt: Nuxt) {
for (const module of nuxt.options.modules) {
await installModule(nuxt, module)
}
}
// module.ts - 安装模块
export async function installModule(
nuxt: Nuxt,
module: NuxtModule | string
) {
// 1. 解析模块路径
const resolvedModule = typeof module === 'string'
? await import(module)
: module
// 2. 调用模块 setup 函数
const result = await resolvedModule.setup(nuxt)
// 3. 注册插件
if (result?.plugins) {
nuxt.plugins.push(...result.plugins)
}
// 4. 添加导入
if (result?.imports) {
nuxt.imports.push(...result.imports)
}
// 5. 执行钩子
await nuxt.callHook('module:installed', resolvedModule)
}
Nuxt 运行时负责客户端和服务端的应用初始化、插件执行、数据管理等。
客户端运行时
服务端运行时
// app/nuxt.ts - NuxtApp 接口定义
export interface NuxtApp {
// Vue 应用
vueApp: App<Element>
versions: Record<string, string>
// Hook 系统
hooks: Hookable<RuntimeNuxtHooks>
hook: NuxtApp['hooks']['hook']
callHook: NuxtApp['hooks']['callHook']
// 上下文执行
runWithContext: <T>(fn: T) => ReturnType<T>
// 状态
payload: NuxtPayload
static: { data: Record<string, any> }
// SSR
ssrContext?: NuxtSSRContext
isHydrating?: boolean
// 注入
provide: (name: string, value: any) => void
}
// app/nuxt.ts - 创建 NuxtApp
export function createNuxtApp(options: CreateOptions) {
let hydratingCount = 0
const nuxtApp: NuxtApp = {
_id: options.id || 'nuxt-app',
_scope: effectScope(),
versions: { nuxt: __NUXT_VERSION__, vue: vueApp.version },
// Payload 管理
payload: shallowReactive({
data: shallowReactive({}),
state: reactive({}),
once: new Set<string>(),
_errors: shallowReactive({}),
}),
// Hydration 控制
isHydrating: import.meta.client,
deferHydration() { /* ... */ },
// ... 其他属性
}
return nuxtApp
}
Nuxt 插件在应用初始化时执行,可以注入全局属性、注册钩子、初始化第三方库。
// 插件定义
export interface Plugin {
(nuxt: NuxtApp): Promise<void> | void
meta?: ResolvedPluginMeta
}
// 定义插件
export function defineNuxtPlugin(plugin: Plugin) {
return Object.assign(plugin, {
[NuxtPluginIndicator]: true
})
}
// 使用示例
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.provide('myPlugin', { /* ... */ })
})
// app/nuxt.ts - 执行插件
export async function applyPlugins(
nuxtApp: NuxtApp,
plugins: Plugin[]
) {
const resolvedPlugins = new Set<string>()
const unresolvedPlugins = []
// 插件依赖解析
async function executePlugin(plugin: Plugin) {
// 检查依赖
const unresolved = plugin.dependsOn?.filter(
name => !resolvedPlugins.has(name)
)
if (unresolved?.length > 0) {
unresolvedPlugins.push([new Set(unresolved), plugin])
} else {
// 执行插件
await applyPlugin(nuxtApp, plugin)
resolvedPlugins.add(plugin._name)
}
}
// 并行/串行执行
for (const plugin of plugins) {
await executePlugin(plugin)
}
}
应用 Hooks
页面 Hooks
// 注册 Hook
nuxtApp.hook('app:mounted', () => {
console.log('App mounted!')
})
// app/nuxt.ts - 服务端上下文
export interface NuxtSSRContext {
url: string // 请求 URL
event: H3Event // H3 事件对象
runtimeConfig: RuntimeConfig // 运行时配置
noSSR: boolean // 是否禁用 SSR
// Nuxt 实例
nuxt: NuxtApp
payload: Partial<NuxtPayload> // Payload 数据
head: VueHeadClient // Head 管理
// 渲染控制
error?: boolean
teleports?: Record<string, string>
// 内部属性
['~renderResponse']?: Partial<RenderResponse>
['~payloadReducers']: Record<string, (data: any) => any>
['~sharedPrerenderCache']?: { /* ... */ }
}
Payload是服务端渲染数据传输到客户端的核心机制。
// Payload 结构
export interface NuxtPayload {
path?: string // 当前路径
serverRendered?: boolean // 是否 SSR
prerenderedAt?: number // 预渲染时间戳
data: Record<string, any> // 数据缓存
state: Record<string, any> // 应用状态
once: Set<string> // 单次标记
config?: RuntimeConfig // 配置
error?: NuxtError // 错误信息
_errors: Record<string, NuxtError>
}
// 服务端设置
nuxtApp.payload.serverRendered = true
nuxtApp.payload.path = nuxtApp.ssrContext.url
// 客户端读取
const __NUXT__ = window.__NUXT__
Nuxt 3提供多个 composables 进行数据获取:useFetch、useAsyncData、useLazyFetch 等。
| Composable | 特点 | 使用场景 |
|---|---|---|
| useFetch | 封装 $fetch + useAsyncData | HTTP 请求 |
| useAsyncData | 通用异步数据管理 | 任意异步操作 |
| useLazyFetch | 非阻塞加载 | 延迟数据 |
| $fetch | 原生 fetch 封装 | 简单请求 |
// composables/asyncData.ts - 核心 API
export function useAsyncData<ResT>(
key: MaybeRefOrGetter<string>,
handler: AsyncDataHandler<ResT>,
opts?: AsyncDataOptions<ResT>
): AsyncData<ResT> {
const nuxtApp = useNuxtApp()
// 1. 获取或创建 AsyncData 实例
if (!nuxtApp._asyncData[key]) {
nuxtApp._asyncData[key] = buildAsyncData(
nuxtApp, key, handler, opts
)
}
// 2. 服务端:立即执行
if (import.meta.server && opts.server !== false) {
nuxtApp._asyncData[key].execute()
}
// 3. 客户端:从 payload 恢复或执行
if (import.meta.client) {
if (nuxtApp.isHydrating && nuxtApp.payload.data[key]) {
// Hydration: 使用服务端数据
} else {
nuxtApp._asyncData[key].execute()
}
}
return nuxtApp._asyncData[key]
}
// composables/asyncData.ts - 配置选项
export interface AsyncDataOptions<ResT> {
// 服务端行为
server?: boolean // 是否在服务端执行(默认 true)
lazy?: boolean // 是否延迟加载(默认 false)
// 数据处理
default?: () => DefaultT // 默认值
transform?: (data: ResT) => DataT // 数据转换
pick?: KeysOf<DataT> // 提取字段
// 缓存
getCachedData?: (key, nuxtApp) => DataT
// 响应式
watch?: MultiWatchSources // 监听源
immediate?: boolean // 立即执行
// 性能
deep?: boolean // 深度响应(默认 true)
dedupe?: 'cancel' | 'defer' // 去重策略
timeout?: number // 超时时间
}
// composables/asyncData.ts - 构建 AsyncData
function buildAsyncData(
nuxtApp: NuxtApp,
key: string,
handler: AsyncDataHandler,
options: AsyncDataOptions
) {
const asyncData = {
// 响应式状态
data: ref(options.default()),
pending: ref(true),
error: ref(undefined),
status: shallowRef('idle'),
// 执行方法
async execute(opts?: AsyncDataExecuteOptions) {
asyncData.status.value = 'pending'
try {
const result = await handler(nuxtApp, { signal })
// 数据转换
let data = options.transform
? await options.transform(result)
: result
asyncData.data.value = data
asyncData.status.value = 'success'
// 保存到 payload
nuxtApp.payload.data[key] = data
} catch (err) {
asyncData.error.value = err
asyncData.status.value = 'error'
}
}
}
return asyncData
}
Payload 缓存
静态缓存
自定义缓存
const { data } = await useFetch('/api/data', {
getCachedData(key, nuxtApp) {
// 自定义缓存逻辑
return nuxtApp.static.data[key]
}
})
// composables/fetch.ts - useFetch 实现
export const useFetch = createUseFetch({
name: 'createUseFetch',
factory() {
return function useFetch(request, opts = {}) {
// 1. 生成请求 key
const key = computed(() =>
'$f' + hash([request, ...generateOptionSegments(opts)])
)
// 2. 合并默认选项
const _fetchOptions = reactive({
...fetchDefaults,
...opts
})
// 3. 调用 useAsyncData
return useAsyncData(key, () => {
const _$fetch = opts.$fetch || $fetch
return _$fetch(request, {
signal,
..._fetchOptions
})
}, {
server: opts.server,
lazy: opts.lazy,
watch: [request, _fetchOptions]
})
}
}
})
// composables/asyncData.ts - 去重逻辑
function execute(opts) {
// 1. 检查是否有进行中的请求
if (nuxtApp._asyncDataPromises[key]) {
if ((opts.dedupe ?? options.dedupe) === 'defer') {
// defer: 等待现有请求
return nuxtApp._asyncDataPromises[key]
}
// cancel: 取消现有请求
}
// 2. 创建新请求
const promise = handler(nuxtApp, { signal })
.then(result => {
// 保存结果
asyncData.data.value = result
delete nuxtApp._asyncDataPromises[key]
})
// 3. 存储请求 Promise
nuxtApp._asyncDataPromises[key] = promise
return promise
}
Nuxt 路由基于文件系统自动生成,支持动态路由、嵌套路由、中间件等。
路由文件
路由特性
// composables/router.ts - 路由访问
export const useRouter = () => {
return useNuxtApp()?.$router as Router
}
export const useRoute = () => {
// 优先从注入获取(支持嵌套路由)
if (hasInjectionContext()) {
return inject(PageRouteSymbol, useNuxtApp()._route)
}
return useNuxtApp()._route
}
// 使用示例
const router = useRouter()
const route = useRoute()
// 导航
router.push('/about')
// 获取参数
const id = route.params.id
// composables/router.ts - 导航函数
export const navigateTo = (
to: RouteLocationRaw | undefined | null,
options?: NavigateToOptions
) => {
// 1. 处理外部链接
if (isExternal) {
if (options?.replace) {
location.replace(toPath)
} else {
location.href = toPath
}
return
}
// 2. 服务端:设置 redirect
if (import.meta.server) {
nuxtApp.ssrContext!['~renderResponse'] = {
status: options?.redirectCode || 302,
headers: { location: encodedHeader }
}
return
}
// 3. 客户端:vue-router 导航
return options?.replace
? router.replace(encodedTo)
: router.push(encodedTo)
}
// composables/router.ts - 中间件系统
export interface RouteMiddleware {
(to: RouteLocationNormalized, from: RouteLocationNormalized):
ReturnType<NavigationGuard>
}
// 定义中间件
export function defineNuxtRouteMiddleware(middleware: RouteMiddleware) {
return middleware
}
// 注册中间件
export const addRouteMiddleware = (
name: string | RouteMiddleware,
middleware?: RouteMiddleware,
options?: { global?: boolean }
) => {
if (global || typeof name !== 'string') {
nuxtApp._middleware.global.push(mw)
} else {
nuxtApp._middleware.named[name] = mw
}
}
// 使用示例
export default defineNuxtRouteMiddleware((to, from) => {
if (!isAuthenticated()) {
return navigateTo('/login')
}
})
// pages/module.ts - 页面模块
export default defineNuxtModule({
meta: { name: 'nuxt:pages' },
async setup(options, nuxt) {
// 1. 扫描 pages 目录
const pagesDirs = getLayerDirectories(nuxt)
.map(dirs => dirs.appPages)
// 2. 解析路由
const resolvePagesRoutes = async (pattern) => {
const pages = await _resolvePagesRoutes(pattern, nuxt)
await handleRouteRules(pages)
return pages
}
// 3. 生成路由文件
addTemplate({
filename: 'routes.mjs',
getContents({ app }) {
const { routes, imports } = normalizeRoutes(app.pages)
return [...imports, `export default ${routes}`].join('\n')
}
})
}
})
// 路由生成流程
┌────────────────────────────────────┐
│ pages/ │
│ ├── index.vue │
│ ├── about.vue │
│ └── users/[id].vue │
└─────────────┬──────────────────────┘
↓
┌────────────────────────────────────┐
│ resolvePagesRoutes() │
│ • 扫描文件 │
│ • 解析路径 │
│ • 提取元信息 │
└─────────────┬──────────────────────┘
↓
┌────────────────────────────────────┐
│ normalizeRoutes() │
│ • 生成 vue-router 配置 │
│ • 添加动态导入 │
│ • 设置路由守卫 │
└─────────────┬──────────────────────┘
↓
┌────────────────────────────────────┐
│ routes.mjs │
│ export default [ │
│ { path: '/', component: ... }, │
│ { path: '/about', ... }, │
│ { path: '/users/:id', ... } │
│ ] │
└────────────────────────────────────┘
Nuxt 3使用 Nitro 作为服务端引擎,支持多种部署目标(Node、Serverless、Edge)。
打包流程
部署目标
// core/server.ts - 服务端打包
export async function bundleServer(nuxt: Nuxt) {
try {
// 1. 加载服务端构建器
const { bundle } = !nuxt.options.server.builder
? await loadServerBuilder(nuxt)
: nuxt.options.server.builder
// 2. 执行打包
await bundle(nuxt)
} catch (error: any) {
// 3. 错误处理
await nuxt.callHook('build:error', error)
throw error
}
}
// 加载默认构建器
async function loadServerBuilder(nuxt: Nuxt) {
return await importModule('@nuxt/nitro-server', {
url: [directoryToURL(nuxt.options.rootDir)]
})
}
// Nitro 是 Nuxt 的服务端引擎
// 特性:
// • 跨平台部署
// • 自动代码分割
// • 文件系统 API
// • 热重载
// • 缓存策略
// server/api/hello.ts
export default defineEventHandler((event) => {
return { message: 'Hello Nuxt!' }
})
// server/middleware/auth.ts
export default defineEventHandler((event) => {
const auth = getHeader(event, 'authorization')
if (!auth) {
throw createError({
statusCode: 401,
message: 'Unauthorized'
})
}
})
// SSR 渲染流程
┌─────────────────────────────────┐
│ 客户端请求 │
│ GET /users/123 │
└────────────┬────────────────────┘
↓
┌─────────────────────────────────┐
│ Nitro Server │
│ • 路由匹配 │
│ • 创建 SSRContext │
└────────────┬────────────────────┘
↓
┌─────────────────────────────────┐
│ createNuxtApp() │
│ • 初始化应用 │
│ • 执行插件 │
│ • 运行中间件 │
└────────────┬────────────────────┘
↓
┌─────────────────────────────────┐
│ useAsyncData 执行 │
│ • 数据预取 │
│ • 保存到 payload │
└────────────┬────────────────────┘
↓
┌─────────────────────────────────┐
│ Vue SSR Renderer │
│ • renderToString() │
│ • 生成 HTML │
│ • 注入 payload │
└────────────┬────────────────────┘
↓
┌─────────────────────────────────┐
│ 返回 HTML + __NUXT__ │
└─────────────────────────────────┘
Hydration是客户端接管服务端渲染的 HTML,使其变为可交互的 Vue 应用的过程。
// app/nuxt.ts - Hydration 控制
const nuxtApp: NuxtApp = {
isHydrating: import.meta.client,
deferHydration() {
if (!nuxtApp.isHydrating) return () => {}
hydratingCount++
let called = false
return () => {
if (called) return
called = true
hydratingCount--
if (hydratingCount === 0) {
nuxtApp.isHydrating = false
return nuxtApp.callHook('app:suspense:resolve')
}
}
}
}
// 使用:延迟 Hydration
const defer = nuxtApp.deferHydration()
// ... 异步操作完成后
defer()
useState
// 跨组件共享状态
const counter = useState('counter', () => 0)
// 等价于
const counter = useState('counter')
if (!counter.value) {
counter.value = 0
}
Pinia 集成
// stores/user.ts
export const useUserStore = defineStore('user', {
state: () => ({
name: '',
email: ''
}),
actions: {
async fetchUser() {
const data = await $fetch('/api/user')
this.name = data.name
}
}
})
// Nuxt 自动导入机制
// 1. 内置 composables
// useFetch, useState, useRouter...
// 2. 组件自动导入
// components/ 目录下的组件
// 3. 工具函数自动导入
// utils/ 目录下的函数
// 4. 自定义导入
// nuxt.config.ts
export default defineNuxtConfig({
imports: {
dirs: ['composables', 'utils']
}
})
// 生成的 imports.d.ts
declare global {
const useState: typeof import('#app')['useState']
const useFetch: typeof import('#app')['useFetch']
// ...
}
Islands允许组件独立渲染,减少客户端 JavaScript 负载。
// 服务端组件
// components/Comments.server.vue
<template>
<div class="comments">
<!-- 仅在服务端渲染 -->
{{ comments }}
</div>
</template>
// 客户端组件
// components/Interactive.client.vue
<template>
<button @click="handleClick">
Click me
</button>
</template>
// 使用
<Comments /> <!-- 服务端 -->
<Interactive /> <!-- 客户端 -->
// pages/module.ts - 预渲染配置
nuxt.hook('nitro:build:before', (nitro) => {
// 注入 SSR 路由
nitro.options.ssrRoutes = [
...nitro.options.ssrRoutes || [],
...toRou3Patterns(nuxt.apps.default?.pages || [])
]
// 预渲染配置
nitro.options.prerender.routes ||= []
// 添加静态页面
if (nitro.options.static) {
for (const route of prerenderRoutes) {
const rules = nitro.routing.routeRules.matchAll('', route)
if (rules.prerender) {
nitro.options.prerender.routes.push(route)
}
}
}
})
// nuxt.config.ts
export default defineNuxtConfig({
nitro: {
prerender: {
routes: ['/', '/about', '/contact']
}
}
})
构建优化
运行时优化
缓存策略
监控
工厂模式
观察者模式
组合模式
代理模式
| 特性 | Nuxt 3 | Next.js | SvelteKit |
|---|---|---|---|
| 基础框架 | Vue 3 | React | Svelte |
| 构建工具 | Vite | Turbopack/Webpack | Vite |
| 服务端引擎 | Nitro | Node.js | Node.js |
| 自动导入 | ✅ | ❌ | ✅ |
| 文件路由 | ✅ | ✅ | ✅ |
| SSR | ✅ | ✅ | ✅ |
数据获取
状态管理
性能优化
SEO
Q: Hydration mismatch 错误?
A: 确保服务端和客户端渲染一致,避免在渲染时使用浏览器 API。
Q: useFetch 数据重复请求?
A: 检查 key 是否唯一,使用 dedupe 选项,确保 payload 正确传递。
Q: 插件执行顺序?
A: 使用 enforce: 'pre'/'post',dependsOn 指定依赖,parallel 并行执行。
// 1. 开启调试模式
// nuxt.config.ts
export default defineNuxtConfig({
debug: true
})
// 2. 查看 Hook 调用
nuxtApp.hook('app:created', () => {
console.log('App created', nuxtApp)
})
// 3. Payload 调试
console.log('Payload:', nuxtApp.payload)
console.log('Static data:', nuxtApp.static.data)
// 4. 路由调试
console.log('Routes:', useRouter().getRoutes())
// 5. 组件状态
const { data, pending, error } = await useFetch('/api/data')
watchEffect(() => {
console.log('Data:', data.value)
console.log('Pending:', pending.value)
console.log('Error:', error.value)
})
即将推出
社区趋势
Nuxt 3正在快速演进,持续关注 RFC 和官方博客获取最新特性。
┌──────────────────────────────────────┐
│ Nuxt 3 全栈渲染链路 │
├──────────────────────────────────────┤
│ 构建时 │
│ ├─ createNuxt() 创建实例 │
│ ├─ initNuxt() 初始化 │
│ ├─ resolveModules() 解析模块 │
│ └─ bundleServer() 服务端打包 │
├──────────────────────────────────────┤
│ 运行时 │
│ ├─ createNuxtApp() 创建应用 │
│ ├─ applyPlugins() 执行插件 │
│ ├─ useAsyncData() 数据获取 │
│ └─ useRouter() 路由管理 │
├──────────────────────────────────────┤
│ 服务端 │
│ ├─ Nitro Server Engine │
│ ├─ SSR Context │
│ ├─ Payload 传输 │
│ └─ HTML 渲染 │
├──────────────────────────────────────┤
│ 客户端 │
│ ├─ Hydration 水合 │
│ ├─ 状态恢复 │
│ └─ 交互激活 │
└──────────────────────────────────────┘
| 文件路径 | 功能 |
|---|---|
| packages/nuxt/src/core/nuxt.ts | Nuxt 实例创建 |
| packages/nuxt/src/core/server.ts | 服务端打包 |
| packages/nuxt/src/app/nuxt.ts | 应用运行时 |
| packages/nuxt/src/app/composables/asyncData.ts | 数据获取 |
| packages/nuxt/src/app/composables/fetch.ts | HTTP 请求 |
| packages/nuxt/src/app/composables/router.ts | 路由系统 |
| packages/nuxt/src/pages/module.ts | 页面模块 |
Nuxt 3是一个精心设计的全栈框架,通过模块化架构、插件系统和 Nitro 引擎实现了灵活高效的开发体验。
核心优势
关键概念
感谢阅读! 🎉