您現在的位置是:首頁 > 藝術

Vue 服務端渲染原理解析與入門實戰

由 西嶺老溼 發表于 藝術2022-08-09
簡介npm run generate 命令就是用來專門做靜態匯出的,這個命令執行後,Nuxt 會根據路由配置,將應用的全部內容生成對應的 HTML 靜態站點資源,這個命令會建立一個 dist 資料夾,所有靜態化後的資原始檔均在其中

渲染資料是什麼意思

開篇

在開始之前我們需要先來搞清楚一個問題:什麼是服務端渲染 ?

在以往的概念裡,渲染的工作更多的是放在客戶端進行的,那麼為什麼現在我們要讓服務端來做這個工作?

服務端渲染和客戶端渲染有什麼不同之處嗎?

其實服務端渲染的工具有很多,看著手冊很快就能上手,並沒有什麼難度,關鍵在於,我們什麼場景下需要使用服務端渲染,什麼樣的渲染方案更適合我們的專案;知其然,知其所以然,我們需要先搞清楚服務端渲染的基本概念和原理,服務端渲染為什麼會出現,到底解決了我們的什麼問題,掌握整體的渲染邏輯和思路,我們才能在學習工具使用時,輕鬆自在,而即便以後工具有了變化和更新,我們也能得心應手,不會再說 “學不動” 了;

這個邏輯就是所謂的道、法、術、器的概念;不要僅僅停留在工具的使用和一些工具的奇技淫巧中,更多的要向法、道的層面成長;

什麼是 SSR ?

現代化的前端專案,大部分都是單頁應用程式,也就是我們說的 SPA ,整個應用只有一個頁面,透過元件的方式,展示不同的頁面內容,所有的資料透過請求伺服器獲取後,在進行客戶端的拼裝和展示;這就是目前前端框架的預設渲染邏輯,我們稱為:客戶端渲染方案( Client Side Render 簡稱:CSR );

載入渲染過程如下:HTML/CSS 程式碼 ——> 載入 JavaScript 程式碼 ——> 執行 JavaScript 程式碼 ——> 渲染頁面資料

Vue 服務端渲染原理解析與入門實戰

SPA 應用的客戶端渲染方式,最大的問題有兩個方面:

1:白屏時間過長,使用者體驗不好;

2:HTML 中無內容,SEO 不友好;

這個問題的原因在於,首次載入時,需要先下載整個 SPA 指令碼程式,瀏覽器執行程式碼邏輯後,才能去獲取頁面真正要展示的資料,而 SPA 指令碼的下載需要較長的等待和執行時間,同時,下載到瀏覽器的 SPA 指令碼是沒有頁面資料的, 瀏覽器實際並沒有太多的渲染工作,因此使用者看到的是沒有任何內容的頁面,不僅如此,因為頁面中沒有內容,搜尋引擎的爬蟲爬到的也是空白的內容,也就不利於 SEO 關鍵字的獲取;

相較於傳統的站點,瀏覽器獲取到的頁面都是經過伺服器處理的有內容的靜態頁面,有過後端程式設計經驗的可能會比較熟悉一些,頁面結構和內容,都是透過伺服器處理後,返回給客戶端;

全宇宙首發動圖,全流程展現

Vue 服務端渲染原理解析與入門實戰

兩相比較我們會發現,傳統站點的頁面資料合成在後臺伺服器,而 SPA 應用的頁面資料合成在瀏覽器,但是無論那種,最終的渲染展示,還是交給瀏覽器完成的,所以,不要誤會,我們這裡所說的 服務端渲染 和 客戶端渲染,指的是頁面結構和資料合成的工作,不是瀏覽器展示的工作;

那麼能不能借助傳統網站的思路來解決 SPA 的問題又能夠保留SPA的優勢呢?不管是白屏時間長還是 SEO 不友好,實際都是首屏的頁面結構先回到瀏覽器,然後再獲取資料後合成導致的問題,那麼,首屏的頁面結構和資料,只要像傳統站點一樣,先在服務端合成後再返回,同時將 SPA 指令碼的載入依然放到首屏中,此時返回的頁面就是結構和資料都有的完整內容了,這樣瀏覽器在展示首頁資料的同時也能載入 SPA 指令碼,搜尋引擎的爬蟲同樣也能獲取到對應的資料,解決 SEO 的問題;為了更好的理解這個邏輯,我畫了一個流程圖:

Vue 服務端渲染原理解析與入門實戰

沒錯,這就是我們所說的 服務端渲染的基本邏輯,服務端渲染也就是 SSR (Server Side Rendering) ;

白屏時間過長的問題得以解決,因為首次載入時,伺服器會先將渲染好的靜態頁面返回,在靜態頁面中再次載入請求 SPA 指令碼;

基本原理:首頁內容及資料,在使用者請求之前生成為靜態頁面,同時加入 SPA 的指令碼程式碼引入,在瀏覽器渲染完成靜態頁面後,請求 SPA 指令碼應用,之後的頁面互動依然是客戶端渲染;

Vue 服務端渲染原理解析與入門實戰

明白了其中的原理,也就是到了道、法的境界,接下來,讓我們下凡進入術、器的應用層面感受一下;

其中 Vue 框架和 React 框架都有對應的比較成熟的 SSR 解決方案,React對應的是 Next。js 框架,Vue 對應的就是 Nuxt。js,當然,如果你對這些都不感興趣,也可以自己實現一個 SSR 的服務端應用,我自己之前也寫過一個,如果你感興趣,想看看我實現的程式碼,可以留言給我,回頭做成教程發出來;

Vue 服務端渲染原理解析與入門實戰

我們以 Vue 對應的 Nuxt。js 為例,來具體感受服務端渲染;

Nuxt。js 應用

Nuxt。js 是一個基於 Vue。js 的通用應用框架。Nuxt。js 預設了利用 Vue。js 開發

服務端渲染

的應用所需要的各種配置,為基於 Vue。js 的應用提供生成對應的靜態站點的功能。開啟 Nuxt。js官網:https://www。nuxtjs。cn/ ,學習指南寫的非常詳細且通俗易懂,根據指南,我們可以看到有兩種安裝方式,一種使用 create-nuxt-app 腳手架工具,另一種是自己手動建立;

安裝

腳手架安裝

接下來我們分別嘗試不同的安裝方式,先使用腳手架進行安裝,執行命令 :npx create-nuxt-app creact-nuxt

接著,在命令列中會有很多的選擇項,分別有專案名稱、開發語言、UI元件庫、伺服器框架、測試框架、HTTP請求庫等等,可以根據自己的需要進行不同的選擇,安裝成功過後,命令列中會給出對應的提示資訊。

Vue 服務端渲染原理解析與入門實戰

我們可以根據提示資訊,執行專案,專案有開發環境和生產環境兩種執行方式,開發環境下直接使用 npm run dev 即可,而要執行生產環境,則需要先進行 build 編譯,編譯成功後才能開啟專案執行;

因為專案是剛剛初始化的,我們並沒有寫任何內容,所以,不管使用那種執行方式,我們能看到的都是下面這個頁面內容;

Vue 服務端渲染原理解析與入門實戰

手動安裝

不同於腳手架安裝,手動安裝需要我們自己建立專案並安裝所需擴充套件和外掛,還需要我們自己寫好元件程式碼,然後配置執行命令,才能啟動執行,但是,手動建立更加考驗大家對專案的整體把控能力;

執行命令:mkdir nuxtnpm 建立資料夾後,切換目錄:cd nuxtnpm ;

然後執行命令:npm init -y 建立專案並生成 package。json 檔案;

使用命令:npm install nuxt ——save 安裝 Nuxt。js 框架;

在 nuxtnpm 目錄中,建立 pages 目錄及 pages/index。vue 元件檔案,在元件檔案中,寫如下程式碼,打聲招呼:

最後,我們還要在 package。json 檔案中,配置執行命令的指令碼引數:

“scripts”: {

“test”: “echo \”Error: no test specified\“ && exit 1”,

“dev”: “nuxt”,

“build”: “nuxt build”,

“start”: “nuxt start”,

“generate”: “nuxt generate”

},

配置好命令引數後,就和前面的執行套路是一樣的了:

npm run dev 啟動一個熱載入的 Web 伺服器(開發模式)

npm run build 編譯專案,利用 webpack 編譯應用,壓縮 JS 和 CSS 資源(釋出用);

npm run start 以生產模式啟動一個 Web 伺服器 (需要先進行專案編譯)。

專案執行後,我們就可以看到剛剛寫的元件內容了;

Vue 服務端渲染原理解析與入門實戰

需要注意的是,pages 目錄是必須的,Nuxt。js 框架會自動讀取該目錄下所有的 。vue 檔案並自動生成對應的路由配置。

路由

基礎路由

基礎路由不需要配置,Nuxt。js 會根據 pages 中的資料夾及檔案,自動生成的路由配置

假設 pages 的目錄結構如下:

pages/

——| user/

——-| index。vue

——-| one。vue

——| index。vue

那麼,Nuxt。js 自動生成的路由配置如下:

router: {

routes: [

{

name: ‘index’,

path: ‘/’,

component: ‘pages/index。vue’

},

{

name: ‘user’,

path: ‘/user’,

component: ‘pages/user/index。vue’

},

{

name: ‘user-one’,

path: ‘/user/one’,

component: ‘pages/user/one。vue’

}

}

同樣的,在 /。nuxt/router。js 檔案中,我們也能夠看到相關內容;

路由導航

Nuxt 中的路由導航有三種方式,一種就是普通的 a 標籤跳轉,太過於基礎這裡就不說了,兩外兩種分別是 nuxt-link 元件和程式設計式導航,nuxt-link 元件用於在頁面中新增連結跳轉到其他頁面,目前 的作用和 router-link 一致,推薦閱讀 Vue 路由文件 來了解它的使用方法,所以,你在Vue 中如何使用,在Nuxt 中同樣如何使用就可以了。

而程式設計式導航的用法,同樣與 Vue 中的使用方式一致:

動態路由

在 Nuxt。js 裡面定義帶引數的動態路由,需要建立對應的

以下劃線作為字首

的 Vue 檔案 或 目錄。

下劃線後面的名字隨意命名,但是在獲取動態路由引數時,檔案的名字就是獲取的關鍵字,用法與 Vue-Router 基本一致:

\pages\user_kk.vue

訪問:http://localhost:3000/user/3

Vue 服務端渲染原理解析與入門實戰

在 Nuxt。js 執行 generate 命令時,動態路由會被忽略,(後面重點講)

巢狀路由

你可以透過 vue-router 的子路由建立 Nuxt。js 應用的巢狀路由。建立內嵌子路由,需要新增一個 Vue 檔案,同時新增一個

與該檔案同名

的目錄用來存放子檢視元件。在父元件(。vue檔案) 內增加 用於顯示子檢視內容。

Vue 服務端渲染原理解析與入門實戰

父元件檔案內容

\pages\order.vue

巢狀子元件檔案及內容

\pages\order\index.vue

巢狀元件預設顯示,訪問路徑:http://localhost:3000/order

\pages\order\info.vue

訪問路徑:http://localhost:3000/order/info

\pages\order\list.vue

訪問路徑:http://localhost:3000/order/list

非同步資料-asyncData

Nuxt。js 擴充套件了 Vue。js,增加了一個叫 asyncData 的方法,使得我們可以在設定元件的資料之前能非同步獲取或處理資料。asyncData 方法會在元件(

限於頁面元件

)每次載入之前被呼叫。它可以在服務端或路由更新之前被呼叫。Nuxt。js 會將 asyncData 返回的資料融合元件 data 方法返回的資料一併返回給當前元件。

Nuxt。js 對 SSG 的支援

在開始之前,我們需要先了解 SSG 的含義,SSG(

Static Site Generators

):靜態站點生成。

就是將應用中用到的所有頁面,全部生成靜態檔案的方案;靜態站點生成方案,更適合 CDN、快取、內容資料無變化的頁面,比如:宣傳頁、部落格文章、幫助文件、新聞頁面、電商產品列表等眾多應用場景;因為頁面都是事先生成好的,一次構建,反覆使用,訪問速度快。

那麼,在 Nuxt。js 中如何將應用靜態化匯出呢?npm run generate 命令就是用來專門做靜態匯出的,這個命令執行後,Nuxt 會根據路由配置,將應用的全部內容生成對應的 HTML 靜態站點資源,這個命令會建立一個 dist 資料夾,所有靜態化後的資原始檔均在其中。

Vue 服務端渲染原理解析與入門實戰

前面說

在 Nuxt.js 執行 generate 命令時,動態路由會被忽略。

動態路由手動配置

如果想讓 Nuxt。js 為動態路由也生成靜態檔案,需要指定動態路由引數的值,並配置到 routes 陣列中去。

我們可以在 nuxt。config。js 中為 /users/:id 路由配置如下:

module。exports= {

generate: {

routes: [‘/users/1’, ‘/users/2’, ‘/users/3’]

}

}

動態路由資料生成

但是如果路由

動態引數

的值是動態的而不是固定的,應該怎麼做呢?

可以使用一個返回 Promise 物件型別的 函式,意思就是,傳送請求獲取所有資料,根據返回的資料,生成所有可能的路由,再根據所有路由,生成全部的靜態檔案

nuxt.config.js

constaxios=require(‘axios’)

module。exports= {

generate: {

// 生成路由檔案,而不是目錄

subFolders:false,

routes() {

// 請求資料

returnaxios。get(‘http://127。0。0。1:80/three’)。then(res=> {

constresData=JSON。parse(res。data);

returnresData。map(user=> {

// 拼裝路由

return‘/user/’+user。id

})

})

}

}

}

非同步資料-asyncData 與 mounted 的區別

mounted 在靜態站點生成時,不會執行獲取資料,程式碼會被編譯進靜態生成的 JS 中,瀏覽器渲染時才會被執行,

asyncData 在匯出靜態站點時,會執行程式碼,並將資料直接編譯進 HTML 中,程式碼不會編譯到靜態檔案的 JS 中;

推薦文章