新聞中心
開篇
在開始之前我們需要先來搞清楚一個問題:什么是服務端渲染 ?

米林網站制作公司哪家好,找創(chuàng)新互聯(lián)!從網頁設計、網站建設、微信開發(fā)、APP開發(fā)、成都響應式網站建設公司等網站項目制作,到程序開發(fā),運營維護。創(chuàng)新互聯(lián)于2013年創(chuàng)立到現(xiàn)在10年的時間,我們擁有了豐富的建站經驗和運維經驗,來保證我們的工作的順利進行。專注于網站建設就選創(chuàng)新互聯(lián)。
在以往的概念里,渲染的工作更多的是放在客戶端進行的,那么為什么現(xiàn)在我們要讓服務端來做這個工作?
服務端渲染和客戶端渲染有什么不同之處嗎?
其實服務端渲染的工具有很多,看著手冊很快就能上手,并沒有什么難度,關鍵在于,我們什么場景下需要使用服務端渲染,什么樣的渲染方案更適合我們的項目;知其然,知其所以然,我們需要先搞清楚服務端渲染的基本概念和原理,服務端渲染為什么會出現(xiàn),到底解決了我們的什么問題,掌握整體的渲染邏輯和思路,我們才能在學習工具使用時,輕松自在,而即便以后工具有了變化和更新,我們也能得心應手,不會再說 “學不動” 了;
這個邏輯就是所謂的道、法、術、器的概念;不要僅僅停留在工具的使用和一些工具的奇技淫巧中,更多的要向法、道的層面成長;
什么是 SSR ?
現(xiàn)代化的前端項目,大部分都是單頁應用程序,也就是我們說的 SPA ,整個應用只有一個頁面,通過組件的方式,展示不同的頁面內容,所有的數(shù)據(jù)通過請求服務器獲取后,在進行客戶端的拼裝和展示;這就是目前前端框架的默認渲染邏輯,我們稱為:客戶端渲染方案( Client Side Render 簡稱: CSR );
加載渲染過程如下: HTML/CSS 代碼 --> 加載 JavaScript 代碼 --> 執(zhí)行 JavaScript 代碼 --> 渲染頁面數(shù)據(jù)
SPA 應用的客戶端渲染方式,最大的問題有兩個方面:
1:白屏時間過長,用戶體驗不好;
2:HTML 中無內容,SEO 不友好;
這個問題的原因在于,首次加載時,需要先下載整個 SPA 腳本程序,瀏覽器執(zhí)行代碼邏輯后,才能去獲取頁面真正要展示的數(shù)據(jù),而 SPA 腳本的下載需要較長的等待和執(zhí)行時間,同時,下載到瀏覽器的 SPA 腳本是沒有頁面數(shù)據(jù)的, 瀏覽器實際并沒有太多的渲染工作,因此用戶看到的是沒有任何內容的頁面,不僅如此,因為頁面中沒有內容,搜索引擎的爬蟲爬到的也是空白的內容,也就不利于 SEO 關鍵字的獲??;
相較于傳統(tǒng)的站點,瀏覽器獲取到的頁面都是經過服務器處理的有內容的靜態(tài)頁面,有過后端編程經驗的可能會比較熟悉一些,頁面結構和內容,都是通過服務器處理后,返回給客戶端;
全宇宙首發(fā)動圖,全流程展現(xiàn)
兩相比較我們會發(fā)現(xiàn),傳統(tǒng)站點的頁面數(shù)據(jù)合成在后臺服務器,而 SPA 應用的頁面數(shù)據(jù)合成在瀏覽器,但是無論那種,最終的渲染展示,還是交給瀏覽器完成的,所以,不要誤會,我們這里所說的 服務端渲染 和 客戶端渲染,指的是頁面結構和數(shù)據(jù)合成的工作,不是瀏覽器展示的工作;
那么能不能借助傳統(tǒng)網站的思路來解決 SPA 的問題又能夠保留SPA的優(yōu)勢呢?不管是白屏時間長還是 SEO 不友好,實際都是首屏的頁面結構先回到瀏覽器,然后再獲取數(shù)據(jù)后合成導致的問題,那么,首屏的頁面結構和數(shù)據(jù),只要像傳統(tǒng)站點一樣,先在服務端合成后再返回,同時將 SPA 腳本的加載依然放到首屏中,此時返回的頁面就是結構和數(shù)據(jù)都有的完整內容了,這樣瀏覽器在展示首頁數(shù)據(jù)的同時也能加載 SPA 腳本,搜索引擎的爬蟲同樣也能獲取到對應的數(shù)據(jù),解決 SEO 的問題;為了更好的理解這個邏輯,我畫了一個流程圖:
沒錯,這就是我們所說的 服務端渲染的基本邏輯,服務端渲染也就是 SSR (Server Side Rendering) ;
白屏時間過長的問題得以解決,因為首次加載時,服務器會先將渲染好的靜態(tài)頁面返回,在靜態(tài)頁面中再次加載請求 SPA 腳本;
基本原理:首頁內容及數(shù)據(jù),在用戶請求之前生成為靜態(tài)頁面,同時加入 SPA 的腳本代碼引入,在瀏覽器渲染完成靜態(tài)頁面后,請求 SPA 腳本應用,之后的頁面交互依然是客戶端渲染;
明白了其中的原理,也就是到了道、法的境界,接下來,讓我們下凡進入術、器的應用層面感受一下;
其中 Vue 框架和 React 框架都有對應的比較成熟的 SSR 解決方案,React對應的是 Next.js 框架,Vue 對應的就是 Nuxt.js,當然,如果你對這些都不感興趣,也可以自己實現(xiàn)一個 SSR 的服務端應用,我自己之前也寫過一個,如果你感興趣,想看看我實現(xiàn)的代碼,可以留言給我,回頭做成教程發(fā)出來;
我們以 Vue 對應的 Nuxt.js 為例,來具體感受服務端渲染;
Nuxt.js 應用
Nuxt.js 是一個基于 Vue.js 的通用應用框架。Nuxt.js 預設了利用 Vue.js 開發(fā)服務端渲染的應用所需要的各種配置,為基于 Vue.js 的應用提供生成對應的靜態(tài)站點的功能。打開 Nuxt.js官網:https://www.nuxtjs.cn/ ,學習指南寫的非常詳細且通俗易懂,根據(jù)指南,我們可以看到有兩種安裝方式,一種使用 create-nuxt-app 腳手架工具,另一種是自己手動創(chuàng)建;
安裝
腳手架安裝
接下來我們分別嘗試不同的安裝方式,先使用腳手架進行安裝,執(zhí)行命令 : npx create-nuxt-app creact-nuxt
接著,在命令行中會有很多的選擇項,分別有項目名稱、開發(fā)語言、UI組件庫、服務器框架、測試框架、HTTP請求庫等等,可以根據(jù)自己的需要進行不同的選擇,安裝成功過后,命令行中會給出對應的提示信息。
我們可以根據(jù)提示信息,運行項目,項目有開發(fā)環(huán)境和生產環(huán)境兩種運行方式,開發(fā)環(huán)境下直接使用 npm run dev 即可,而要運行生產環(huán)境,則需要先進行 build 編譯,編譯成功后才能開啟項目運行;
因為項目是剛剛初始化的,我們并沒有寫任何內容,所以,不管使用那種運行方式,我們能看到的都是下面這個頁面內容;
手動安裝
不同于腳手架安裝,手動安裝需要我們自己創(chuàng)建項目并安裝所需擴展和插件,還需要我們自己寫好組件代碼,然后配置執(zhí)行命令,才能啟動運行,但是,手動創(chuàng)建更加考驗大家對項目的整體把控能力;
執(zhí)行命令: mkdir nuxtnpm 創(chuàng)建文件夾后,切換目錄:cd nuxtnpm ;
然后執(zhí)行命令:npm init -y 創(chuàng)建項目并生成 package.json 文件;
使用命令:npm install nuxt --save 安裝 Nuxt.js 框架;
在 nuxtnpm 目錄中,創(chuàng)建 pages 目錄及 pages/index.vue 組件文件,在組件文件中,寫如下代碼,打聲招呼:
-
-
嗨 Nuxt.js
-
- export default {
- }
最后,我們還要在 package.json 文件中,配置運行命令的腳本參數(shù):
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1",
- "dev": "nuxt",
- "build": "nuxt build",
- "start": "nuxt start",
- "generate": "nuxt generate"
- },
配置好命令參數(shù)后,就和前面的運行套路是一樣的了:
npm run dev 啟動一個熱加載的 Web 服務器(開發(fā)模式)
npm run build 編譯項目,利用 webpack 編譯應用,壓縮 JS 和 CSS 資源(發(fā)布用);
npm run start 以生產模式啟動一個 Web 服務器 (需要先進行項目編譯)。
項目運行后,我們就可以看到剛剛寫的組件內容了;
需要注意的是,pages 目錄是必須的,Nuxt.js 框架會自動讀取該目錄下所有的 .vue 文件并自動生成對應的路由配置。
路由
基礎路由
基礎路由不需要配置,Nuxt.js 會根據(jù) 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 組件用于在頁面中添加鏈接跳轉到其他頁面,目前
而編程式導航的用法,同樣與 Vue 中的使用方式一致:
-
-
nuxt-link 跳轉:
-
Go to user
-
編程式導航 跳轉:
-
-
- import axios from 'axios'
- export default {
- methods:{
- clickBtn(){
- this.$router.push('/user')
- }
- }
- }
動態(tài)路由
在 Nuxt.js 里面定義帶參數(shù)的動態(tài)路由,需要創(chuàng)建對應的 以下劃線作為前綴 的 Vue 文件 或 目錄。
下劃線后面的名字隨意命名,但是在獲取動態(tài)路由參數(shù)時,文件的名字就是獲取的關鍵字,用法與 Vue-Router 基本一致:
\pages\user_kk.vue
-
-
動態(tài)路由-route
-
-
獲取參數(shù),打?。?nbsp;{{$route.params.kk}}
-
控制臺也有輸出
-
- export default {
- mounted(){
- // 獲取路由參數(shù),控制臺打印
- console.log(this.$route.params.kk)
- }
- }
- .mis{
- background: coral;
- }
訪問:
http://localhost:3000/user/3
在 Nuxt.js 執(zhí)行 generate 命令時,動態(tài)路由會被忽略,(后面重點講)
嵌套路由
你可以通過 vue-router 的子路由創(chuàng)建 Nuxt.js 應用的嵌套路由。創(chuàng)建內嵌子路由,需要添加一個 Vue 文件,同時添加一個與該文件同名的目錄用來存放子視圖組件。在父組件(.vue文件) 內增加
父組件文件內容
\pages\order.vue
-
-
嵌套路由
-
-
-
- export default {
- }
嵌套子組件文件及內容
\pages\order\index.vue 嵌套組件默認顯示,訪問路徑:
http://localhost:3000/order
-
-
嵌套子路由 - index
-
-
-
-
- export default {
- }
-
\pages\order\info.vue 訪問路徑: http://localhost:3000/order/info
-
- order->info
-
\pages\order\list.vue 訪問路徑: http://localhost:3000/order/list
-
-
order-> list
-
{{dataObj[0].name}}
-
- import axios from 'axios'
- export default {
- async asyncData({ params }) {
- // 發(fā)送請求,獲取數(shù)據(jù)
- const { data } = await axios.get(`http://127.0.0.1`);
- // 解析數(shù)據(jù)
- const dataObj = JSON.parse(data);
- // 返回數(shù)據(jù)后,Nuxt 會合并data方法的數(shù)據(jù)給組件,無需額外代碼
- return { dataObj };
- },
- }
異步數(shù)據(jù)-asyncData
Nuxt.js 擴展了 Vue.js,增加了一個叫 asyncData 的方法,使得我們可以在設置組件的數(shù)據(jù)之前能異步獲取或處理數(shù)據(jù)。asyncData 方法會在組件(限于頁面組件)每次加載之前被調用。它可以在服務端或路由更新之前被調用。Nuxt.js 會將 asyncData 返回的數(shù)據(jù)融合組件 data 方法返回的數(shù)據(jù)一并返回給當前組件。
-
- user-index page
-
-
-
-
{{ v.name }}
-
-
-
-
-
- import axios from "axios";
- export default {
- async asyncData({ params }) {
- // 發(fā)送請求,獲取數(shù)據(jù)
- const { data } = await axios.get(`http://127.0.0.1`);
- // 解析數(shù)據(jù)
- const dataObj = JSON.parse(data);
- // 返回數(shù)據(jù)后,Nuxt 會合并data方法的數(shù)據(jù)給組件,無需額外代碼
- return { dataObj };
- },
- };
-
Nuxt.js 對 SSG 的支持
在開始之前,我們需要先了解 SSG 的含義,SSG(Static Site Generators):靜態(tài)站點生成。
就是將應用中用到的所有頁面,全部生成靜態(tài)文件的方案;靜態(tài)站點生成方案,更適合 CDN、緩存、內容數(shù)據(jù)無變化的頁面,比如:宣傳頁、博客文章、幫助文檔、新聞頁面、電商產品列表等眾多應用場景;因為頁面都是事先生成好的,一次構建,反復使用,訪問速度快。
那么,在 Nuxt.js 中如何將應用靜態(tài)化導出呢?npm run generate 命令就是用來專門做靜態(tài)導出的,這個命令執(zhí)行后,Nuxt 會根據(jù)路由配置,將應用的全部內容生成對應的 HTML 靜態(tài)站點資源,這個命令會創(chuàng)建一個 dist 文件夾,所有靜態(tài)化后的資源文件均在其中。
前面說 在 Nuxt.js 執(zhí)行 generate 命令時,動態(tài)路由會被忽略。
動態(tài)路由手動配置
如果想讓 Nuxt.js 為動態(tài)路由也生成靜態(tài)文件,需要指定動態(tài)路由參數(shù)的值,并配置到 routes 數(shù)組中去。
我們可以在 nuxt.config.js 中為 /users/:id 路由配置如下:
- module.exports = {
- generate: {
- routes: ['/users/1', '/users/2', '/users/3']
- }
- }
動態(tài)路由數(shù)據(jù)生成
但是如果路由動態(tài)參數(shù)的值是動態(tài)的而不是固定的,應該怎么做呢?
可以使用一個返回 Promise 對象類型的 函數(shù),意思就是,發(fā)送請求獲取所有數(shù)據(jù),根據(jù)返回的數(shù)據(jù),生成所有可能的路由,再根據(jù)所有路由,生成全部的靜態(tài)文件
nuxt.config.js
- const axios = require('axios')
-
- module.exports = {
- generate: {
- // 生成路由文件,而不是目錄
- subFolders:false,
- routes() {
- // 請求數(shù)據(jù)
- return axios.get('http://127.0.0.1:80/three').then(res => {
- const resData = JSON.parse(res.data);
- return resData.map(user => {
- // 拼裝路由
- return '/user/' + user.id
- })
- })
- }
- }
- }
異步數(shù)據(jù)-asyncData 與 mounted 的區(qū)別
mounted 在靜態(tài)站點生成時,不會執(zhí)行獲取數(shù)據(jù),代碼會被編譯進靜態(tài)生成的 JS 中,瀏覽器渲染時才會被執(zhí)行,
asyncData 在導出靜態(tài)站點時,會執(zhí)行代碼,并將數(shù)據(jù)直接編譯進 HTML 中,代碼不會編譯到靜態(tài)文件的 JS 中;
【責任編輯: 龐桂玉 TEL:(010)68476606】
標題名稱:Vue服務端渲染原理及入門
標題網址:http://fisionsoft.com.cn/article/cdshpco.html


咨詢
建站咨詢
