Vue.js 与 Nuxt.js 的关系
如果说 Vue.js 简化了复杂前端项目的心智模型,那么 Nuxt.js 则在 Vue 的基础上进一步扩展了服务端渲染的能力。Nuxt 遵循 "约定大于配置" 的设计理念,通过严格的目录结构和文件命名规范来简化开发流程。
核心对比
| 对比维度 | Vue.js | Nuxt.js |
|---|---|---|
| 框架定位 | 独立前端框架 | 基于 Vue 的全栈框架 |
| 生命周期 | Vue 完整生命周期 | 扩展了应用层、页面层、构建层生命周期 |
| 内置组件 | RouterLink、Transition、KeepAlive 等 | NuxtPage、NuxtLink、ClientOnly 等 |
| 路由系统 | 手动配置 vue-router | 基于文件系统的自动路由 |
| 目录结构 | 自由组织 | 约定式目录(pages、components、server 等) |
| 构建工具 | Vite / Webpack | Vite + Webpack 5 双支持 |
| SSR 支持 | 需额外配置 | 开箱即用 |
核心概念详解
1. 自动导入(Auto Imports)
Nuxt 提供了三层自动导入机制:
Built-in Auto Imports:Nuxt 自动导入其内置的组合式函数:
// 无需 import,直接使用
const { data, pending } = await useFetch('/api/home')
const app = useNuxtApp()
const config = useRuntimeConfig()
typescript
Vue Auto Imports:Vue 核心函数无需手动导入:
// 以下函数无需 import
const count = ref(0)
const doubled = computed(() => count.value * 2)
watch(count, (newVal) => console.log(newVal))
typescript
Directory-based Auto Imports:基于目录的自动导入:
| 目录 | 自动导入内容 |
|---|---|
components/ | Vue 组件 |
composables/ | 组合式函数(对应 Vue 项目中的 hooks) |
utils/ | 工具函数 |
// composables/useCounter.ts
export function useCounter() {
const count = ref(0)
const increment = () => count.value++
return { count, increment }
}
// 页面中直接使用,无需 import
const { count, increment } = useCounter()
typescript
注意事项:如果在 Nuxt 实例创建之前调用组合式 API,会收到 "Nuxt instance is unavailable" 错误。这与 Vue 3 的规则一致。
2. 渲染模式(Rendering Modes)
Nuxt 支持三种渲染模式:
Universal Rendering(通用渲染 / SSR)
这是 Nuxt 的默认渲染模式,工作流程如下:
浏览器请求 → Node.js 服务器渲染 HTML → 返回完整 HTML
↓
同时返回 JS 响应式代码
↓
浏览端 Hydration(水合)
↓
Vue.js 接管页面交互
text
Hydration(水合):服务端渲染的静态 HTML 与客户端 Vue 实例"混合"的过程。水合完成后,页面既保留了 SSR 的首屏速度,又具备了 SPA 的交互能力。
| 优点 | 缺点 |
|---|---|
| 更快的首屏加载 | 开发复杂度更高 |
| 对 SEO 友好 | 服务器资源消耗更大 |
| 支持 OG 标签和社交分享 |
Client-side Rendering(客户端渲染)
等同于纯 Vue SPA 应用,适用于不需要 SEO 的场景:
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
'/admin/**': { ssr: false } // 管理后台无需 SSR
}
})
typescript
Hybrid Rendering(混合渲染)
通过 routeRules 配置不同页面的渲染策略:
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true }, // 首页预渲染
'/blog/**': { swr: 3600 }, // 博客页面:缓存 1 小时
'/admin/**': { ssr: false }, // 管理后台:纯客户端
'/api/**': { cors: true }, // API:允许跨域
}
})
typescript
3. Nuxt 内置组件
ClientOnly
包裹仅在浏览器端渲染的组件,避免 SSR 时访问 window、document 等浏览器 API:
<template>
<ClientOnly>
<BrowserOnlyComponent />
<template #fallback>
<p>加载中...</p>
</template>
</ClientOnly>
</template>
vue
NuxtPage
等价于 Vue Router 的 <RouterView />,用于渲染匹配的页面组件:
<!-- app.vue -->
<template>
<div>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</div>
</template>
vue
NuxtLayout
布局组件,用于在页面外层包裹公共框架(如 Header、Footer、Sidebar):
<!-- layouts/default.vue -->
<template>
<div>
<AppHeader />
<slot />
<AppFooter />
</div>
</template>
vue
NuxtLink
等价于 Vue Router 的 <RouterLink />,用于页面导航:
<template>
<NuxtLink to="/about">关于我们</NuxtLink>
</template>
vue
4. 服务端引擎(Nitro)
Nuxt 3 使用 Nitro 作为服务端引擎,它带来了一项关键能力:
npx nuxt build
bash
构建后在 .output/ 目录生成的分发包:
- 包含 Nuxt 在任何环境中运行的完整运行时代码
- 不依赖
node_modules - 跨平台运行:Node.js、Cloudflare Workers、Vercel、Netlify 等
- 支持 Edge Side Rendering(ESR,边缘渲染)
Nitro 可独立使用,是一个功能完善的跨平台 Web 框架,提供丰富的 API 层扩展能力。
5. 模块系统(Modules)
Nuxt 提供了官方模块市场,可以在 nuxt.com/modules 搜索和集成功能模块。
官方推荐模块:
| 模块 | 功能 |
|---|---|
| @nuxt/devtools | 开发者调试工具 |
| @nuxt/image | 图片优化 |
| @nuxt/content | Markdown 内容管理 |
| @pinia/nuxt | Pinia 状态管理 |
| @vueuse/nuxt | VueUse 工具函数 |
| pinia-plugin-persistedstate/nuxt | Pinia 持久化 |
6. 版本演进
| 特性 | Nuxt 2 | Nuxt Bridge | Nuxt 3 |
|---|---|---|---|
| Vue 版本 | Vue 2 | Vue 2 | Vue 3 |
| TypeScript | 部分支持 | 部分支持 | 全量支持 |
| ESM | 部分支持 | 改进 | 全量支持 |
| Composition API | 不支持 | 部分支持 | 完整支持 |
<script setup> | 不支持 | 支持 | 支持 |
| Vite | 不支持 | 不支持 | 支持 |
| Webpack | 4 | 4 | 5 |
学习建议
- 通读官方文档的 Get Started 部分,理解 Nuxt 的核心思想与 Vue 的异同
- 理解目录约定:
pages/、components/、composables/、server/各自的作用 - 实践渲染模式:尝试配置不同的
routeRules,体验混合渲染的灵活性 - 善用模块市场:优先在官方模块中寻找解决方案,避免重复造轮子
前端技术之间有共通性。掌握了 Vue + Vite 的知识后再学习 Nuxt.js,会发现许多概念是互通的。Nuxt 本质上是在 Vue 生态之上做了一层"约定",让 SSR 开发更加高效。
↑