Nuxt 是基于 Vue 的高層框架,專注于服務器端渲染應用開發。它封裝了繁瑣的配置和通用模式,提供了開箱即用的 SSR 功能,使開發者能夠專注于編寫業務邏輯。
1.?Nuxt?的核心特性
-
SSR 支持:默認支持服務端渲染,提高應用性能和 SEO。
-
路由自動生成(約定式路由):基于文件系統的路由生成,無需手動配置。
-
異步數據獲取:提供 asyncData 和 fetch 方法,方便獲取數據。
-
模塊系統:豐富的模塊生態,支持插件擴展功能。
-
開發體驗:內置熱重載、錯誤處理等,提升開發效率。
2.?安裝和創建 Nuxt?項目
使用命令行工具快速創建 Nuxt 項目:
pnpm dlx nuxi@latest init my-nuxt-app
按照提示選擇項目配置,如包管理器、UI 框架、服務器框架等。
3.?項目結構解析
-
assets/:未編譯的靜態資源,如樣式、圖片等。
-
components/:Vue 組件,可在頁面和布局中復用。
-
layouts/:布局組件,定義頁面的整體結構。
-
pages/:頁面組件,Nuxt? 根據此目錄生成路由。
-
plugins/:插件目錄,用于擴展 Vue 功能。
-
static/:靜態文件,直接映射到應用的根路徑。
-
store/:Pinia 狀態管理目錄。
4.?路由與頁面
Nuxt?基于 pages/ 目錄自動生成路由:
-
基本路由:pages/index.vue 對應 / 路徑。
-
嵌套路由:在 pages 下創建文件夾,嵌套的 .vue 文件對應嵌套路由。
-
動態路由:使用下劃線 _ 定義動態參數,如 pages/user/_id.vue 對應 /user/:id 。
pages/
├── index.vue // /
├── about.vue // /about
├── user/
│ ├── index.vue // /user
│ └── _id.vue // /user/:id
5.?組件與布局
-
組件(Components):可復用的 Vue 組件,放在 components/ 目錄。
-
布局(Layouts):定義頁面的基礎結構,如導航欄、頁腳等,默認布局為 layouts/default.vue。
在頁面中指定布局:
<template><div><!-- 頁面內容 --></div>
</template><script>
export default {layout: 'custom' // 引用 layouts/custom.vue 作為布局
}
</script>
6.?數據獲取
6.1.?asyncData 方法
-
在組件(頁面)渲染之前調用。
-
接收上下文對象 context,可用于獲取參數、請求數據等。
-
返回的數據將合并到組件的 data 中。
<template><div><h1>{{ post.title }}</h1><p>{{ post.content }}</p></div>
</template><script>
export default {async asyncData({ params }) {const { id } = paramsconst post = await fetchPostById(id)return { post }}
}
</script>
6.2.?fetch 方法(Nuxt 2.12+)
-
在組件實例化之后調用。
-
可以訪問組件實例 this,但不返回數據。
-
適用于需要在組件中使用 this 的場景。
7.?中間件和插件
7.1.?中間件
-
在頁面或路由渲染之前執行的函數。
-
用于權限校驗、日志記錄等。
-
創建在 middleware/ 目錄下。
// middleware/auth.js
export default function ({ store, redirect }) {if (!store.state.authenticated) {return redirect('/login')}
}
在頁面中使用:
export default {middleware: 'auth'
}
7.2.?插件
-
擴展 Vue 的功能,如引入第三方庫。
-
創建在 plugins/ 目錄下。
-
在 nuxt.config.js 中注冊。
// plugins/axios.js
import axios from 'axios'export default ({ app }, inject) => {const api = axios.create({baseURL: 'https://api.example.com'})inject('api', api)
}
在組件中使用:
export default {asyncData({ $api }) {return $api.get('/posts').then(res => {return { posts: res.data }})}
}
8.?動態路由和嵌套路由
8.1.?動態路由參數
-
使用下劃線定義動態參數。
-
可通過 context.params 獲取參數值。
8.2.?嵌套路由
-
使用 pages/ 下的目錄結構定義嵌套路由。
-
在父組件中添加 <nuxt-child /> 渲染子路由。
pages/
├── user/
│ ├── _id.vue // /user/:id
│ ├── _id/
│ │ ├── profile.vue // /user/:id/profile
│ │ └── settings.vue // /user/:id/settings
在 _id.vue中:
<template><div><h1>User {{ $route.params.id }}</h1><nuxt-child /></div>
</template>
9.?SEO 優化
-
站點地圖(Sitemap):使用 @nuxtjs/sitemap 模塊自動生成。
-
結構化數據:在頁面中添加結構化數據,提升搜索引擎理解。
-
Meta 標簽管理:使用 head 方法定義頁面的標題和 meta 信息。
export default {head() {return {title: this.post.title,meta: [{ hid: 'description', name: 'description', content: this.post.description }]}}
}
10.?部署 Nuxt 應用
10.1. 服務器渲染模式部署
-
需要一個 Node.js 服務器運行 Nuxt.js 應用。
-
構建和啟動:
npm run build
npm run start
10.2.?靜態站點生成(SSG)
-
生成靜態的 HTML 文件,部署到靜態服務器。
-
適用于內容不經常變化的站點。
npm run generate
11.?性能優化
-
代碼拆分:利用 webpack 的代碼拆分功能,按需加載組件。
-
緩存:使用緩存策略,緩存頁面和 API 請求。
-
異步組件:使用異步組件加載,減少初始包大小。
-
圖片優化:使用合適的圖片格式和尺寸,減少加載時間。
12.?模塊系統和擴展
Nuxt 支持模塊化,可以通過模塊擴展功能:
-
官方模塊:如 Axios 模塊、PWA 模塊、Auth 模塊等。
-
社區模塊:豐富的社區模塊可供使用。
安裝和使用模塊:
npm install @nuxtjs/axios
在 nuxt.config.js 中:
export default {modules: ['@nuxtjs/axios'],axios: {// Axios 模塊配置}
}
13.?Nuxt 的工作流程
Nuxt 在開發和運行時的工作流程主要包括:
13.1.?編譯階段
-
路由生成:掃描 pages/、server/ 目錄,生成路由配置。
-
模板編譯:將 Vue 組件模板編譯為渲染函數。
-
打包:使用 webpack 打包生成服務器端和客戶端的代碼。
13.2. 運行階段
-
服務器渲染:接收請求,執行對應的頁面組件,生成 HTML。
-
客戶端激活:在瀏覽器端,Vue.js 接管頁面,激活組件的交互功能。
14.?服務端渲染流程詳解
1. 請求接收:服務器接收到客戶端請求。
2. 路由匹配:根據請求的 URL,匹配對應的頁面組件。
3. 數據預取:
-
執行頁面組件的 asyncData 或 fetch 方法,獲取數據。
-
數據獲取可以是異步的,如調用 API 接口。
4. 渲染頁面:
-
將組件渲染為 HTML 字符串。
-
包含初始的狀態數據。
5. 響應返回:將生成的 HTML 返回給客戶端。
15.?客戶端激活
-
客戶端接收到 HTML 后,加載 JavaScript 文件。
-
Vue.js 接管頁面,將靜態的 HTML 轉換為可交互的 DOM。
-
過程中會對比服務端和客戶端的虛擬 DOM,確保一致性。
16.?熱重載與開發體驗
16.1. 熱重載(HMR)
-
在開發環境中,修改代碼后,頁面自動更新,無需手動刷新。
-
提高開發效率。
16.2. 錯誤處理
-
友好的錯誤提示,便于調試和定位問題。
17.?參考資料
-
Vue.js 官方文檔:https://cn.vuejs.org/
-
Nuxt.js 官方文檔:Nuxt: The Progressive Web Framework
-
Vue.js 社區:https://forum.vuejs.org/
-
SEO 標簽優化:https://seosetsups.com/blog/open-graph/
-
prerender:https://github.com/prerender/prerender