溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

vue ssr 實現(xiàn)方式(學習筆記)

發(fā)布時間:2020-09-11 21:26:47 來源:腳本之家 閱讀:210 作者:大海Jarvis 欄目:web開發(fā)

為什么要寫本文呢,話說現(xiàn)在vue-ssr 官網(wǎng)上對 vue 服務端渲染的介紹已經(jīng)很全面了,包括各種服務端渲染框架比如 Nuxt.js 、 集成 Koa 和vue-server-renderer 的 node.js 框架 egg.js,都有自己的官網(wǎng)和團隊在維護,文檔真是面面俱到功能強大,但是,我個人在剛開始看這些資料的時候,總是忍不住發(fā)起靈魂三問:“我是誰?我在哪?我在干什么?”,提前沒有相關知識的人開始學這些,肯定是要走一些彎路或者卡在某個點一段時間的,所以我想把我的學習經(jīng)驗做下總結,一方面方便自己以后查閱,一方面也會在文中加一些針對官網(wǎng)上沒有細說的點的理解,希望能幫助你減少些學習成本,畢竟這是一個知識共享的時代嘛。本文不涉及到源碼解析,主要講解如何實現(xiàn) vue 的服務端渲染,比較適合 vue-ssr 小白閱讀,下面我們進入正文:

先說下基本概念:

ssr 的全稱是 server side render,服務端渲染,vue ssr 的意思就是在服務端進行 vue 的渲染,直接對前端返回帶有數(shù)據(jù),并且是渲染好的HTML頁面;而不是返回一個空的HTML頁面,再由vue 通過異步請求來獲取數(shù)據(jù),再重新補充到頁面中。

這么做的最主要原因,就是搜索引擎優(yōu)化,也就是SEO,這更利于網(wǎng)絡爬蟲去爬取和收集數(shù)據(jù)。

為什么這樣就有利于網(wǎng)絡爬蟲爬取呢?

這里簡單說一下爬蟲的爬取方式,爬蟲通過訪問 URL 獲取一個頁面后,會獲取當前HTML中已存在的數(shù)據(jù),也可以理解為把拿到的 HTML 頁面轉為了字符串內容,然后解析、存儲這些內容,但是如果頁面中有些數(shù)據(jù)是通過異步請求獲得的,那么爬蟲是不會等待異步請求返回之后才結束對頁面數(shù)據(jù)的解析的,這樣就會沒有爬取到這部分數(shù)據(jù),很不利于其他搜索引擎的收錄。

這也就是為什么單頁面網(wǎng)站是不具備良好的SEO效果的,因為單頁面返回的就是一個基本為空的 HTML 文件,里面就一個帶有ID的元素等待掛載而已,頁面的內容都是通過 js 后續(xù)生成的,比如這樣:

<!DOCTYPE html>
<html lang="en">
 <head><title>Hello</title></head>
 <body><div id="app"></div></body>
 <script src="bundle.js"></script>
</html>

但對于很多公司來說,公司的產(chǎn)品是希望能被百度、谷歌等搜索引擎收錄之后,進行排名,進一步的被用戶搜索到,能更利于品牌的推廣、流量變現(xiàn)等操作,要實現(xiàn)這些,就必須保證產(chǎn)品的網(wǎng)頁是能夠被網(wǎng)絡爬蟲爬取到的,顯然一個完整的帶有全部數(shù)據(jù)的頁面更利于爬蟲的爬取,當然現(xiàn)在也有很多方法可以去實現(xiàn)針對頁面異步數(shù)據(jù)的爬取,github 上也開源了很多的爬蟲代碼,但是這顯然對于爬蟲來說更加的不友好、成本更高。

SSR 當然也是有著其他的好處的,比如首屏頁面加載速度更快,用戶等待時間更短等,其他更多概念可以查看官網(wǎng) https://ssr.vuejs.org/zh/ ,這些官網(wǎng)上都有介紹。

代碼實現(xiàn)

下面我們結合官網(wǎng)上的代碼,做一下代碼實操,來加深下理解:

在官網(wǎng)中,提供了一個使用模塊 vue-server-renderer 簡單實現(xiàn) vue 服務端渲染的示例:

新建一個文件夾vue-ssr-demo,進入其中執(zhí)行如下命令:

// 安裝模塊 
npm install vue vue-server-renderer --save

創(chuàng)建文件 server.js

// vue-ssr-demo/server.js 示例代碼

//第一步,創(chuàng)建vue實例
const Vue = require('vue');
const app = new Vue({
 template: "<div>hello world</div>"
});

//第二步,創(chuàng)建一個renderer
const renderer = require('vue-server-renderer').createRenderer();
//第三步,將vue渲染為HTML
renderer.renderToString(app, (err, html)=>{
 if(err){
  throw err;
 }
 console.log(html);
});

保存以上代碼后,在 vue-ssr-demo 文件夾下打開命令行工具,執(zhí)行 node server.js 命令,可得到如下 HTML 內容:

➜ vue-ssr-demo node server.js
<div data-server-rendered="true">hello world</div>

好,上面的例子中我們已經(jīng)讓 vue 在服務端,也就是 node 環(huán)境下運行起來了,到這里其實已經(jīng)實現(xiàn)了 vue 的服務端渲染了。

可是,實際項目中使用哪有這么簡單,起碼數(shù)據(jù)還沒渲染啊,那接下來我們看看如何渲染數(shù)據(jù):

vue-ssr 渲染數(shù)據(jù)的方式有兩種,我們先看下第一種:

// server.js
const data_vue = {
 word: 'Hello World!'
};
//第一步,創(chuàng)建vue實例
const Vue = require('vue');
//vue 實例化過程中插入數(shù)據(jù)
const app = new Vue({
 data: data_vue,
 template: "<div>{{word}}</div>"
});

//第二步,創(chuàng)建一個renderer
const renderer = require('vue-server-renderer').createRenderer();

//第三步,將vue渲染為HTML
renderer.renderToString(app, (err, html)=>{
 if(err){
  throw err;
 }
 console.log(html);
}); 

第一種方式,在創(chuàng)建 vue 實例時,將需要的數(shù)據(jù)傳入 vue 的模板,使用方法與客戶端 vue 一樣;運行 server.js 結果如下,數(shù)據(jù) data_vue 已經(jīng)插入到 vue 模板里面了:

➜ vue-ssr-demo node server.js
<div data-server-rendered="true">Hello World!</div> 

第二種,模板插值,這里我們也直接先放代碼:

const data_vue = {
 word: 'Hello World!'
};
const data_tpl = {
 people: 'Hello People!'
};
//第一步,創(chuàng)建vue實例
const Vue = require('vue');
const app = new Vue({
 data: data_vue,
 template: "<div>{{word}}</div>"
});

//第二步,創(chuàng)建一個 renderer 實例
const renderer = require('vue-server-renderer').createRenderer({
 template: "<!--vue-ssr-outlet--><div>{{people}}</div>"
});

//第三步,將vue渲染為HTML
renderer.renderToString(app, data_tpl, (err, html)=>{
 if(err){
  throw err;
 }
 console.log(html);
});

這里我們增加了數(shù)據(jù) data_tpl,你會發(fā)現(xiàn),在 renderToString 方法中傳入了這個參數(shù),那么這個參數(shù)作用在哪里呢?這就要看下官網(wǎng)中關于 createRenderer 和 renderToString 方法的介紹了,

createRenderer: 使用(可選的)選項創(chuàng)建一個 Renderer 實例。
const { createRenderer } = require('vue-server-renderer')
const renderer = createRenderer({ / 選項 / })

在選項中,就有一個參數(shù)叫 template,看官網(wǎng)怎么說的:

template: 為整個頁面的 HTML 提供一個模板。此模板應包含注釋 <!--vue-ssr-outlet-->,作為渲染應用程序內容的占位符。
為整個頁面的 HTML 提供一個模板。此模板應包含注釋 <!--vue-ssr-outlet-->,作為渲染應用程序內容的占位符。

模板還支持使用渲染上下文 (render context) 進行基本插值:

使用雙花括號 (double-mustache) 進行 HTML 轉義插值 (HTML-escaped interpolation);

使用三花括號 (triple-mustache) 進行 HTML 不轉義插值 (non-HTML-escaped interpolation)。

根據(jù)介紹,在創(chuàng)建 renderer 實例時,可以通過 template 參數(shù)聲明一個模板,這個模板用來干嘛呢?就用來掛載 vue 模板渲染完成之后生成的 HTML。這里要注意一下,當創(chuàng)建 renderer 實例時沒有聲明 template 參數(shù),那么默認渲染完就是 vue 模板生成的 HTML;當創(chuàng)建 renderer 實例時聲明了 template 參數(shù),一定要在模板中增加一句注釋 “<!--vue-ssr-outlet-->” 作為 vue 模板插入的占位符,否則會報找不到插入模板位置的錯誤。

再次運行 server.js ,結果如下,vue 模板已成功插入,且 template 模板中的 {{people}} 變量也因在 renderToString 方法中第二位參數(shù)的傳入,顯示了數(shù)據(jù):

 vue-ssr-demo node server.js
<div data-server-rendered="true">Hello World!</div><div>Hello People!</div>

如果我們把 template 換成一個 HTML 頁面的基本架構,來包裹 vue 模板,是不是就能得到一個完整頁面了呢?我們來試一下:

const data_vue = {
 word: 'Hello World!'
};
const data_tpl = {
 people: 'Hello People!'
};
//第一步,創(chuàng)建vue實例
const Vue = require('vue');
const app = new Vue({
 data: data_vue,
 template: "<div>{{word}}</div>"
});

//第二步,創(chuàng)建一個renderer
const renderer = require('vue-server-renderer').createRenderer({
 template: `<!DOCTYPE html>
 <html lang="en">
  <head><title>Hello</title></head>
  <body>
  <!--vue-ssr-outlet--><div>{{people}}</div>
  </body>
 </html>`
});

//第三步,將vue渲染為HTML
renderer.renderToString(app, data_tpl, (err, html)=>{
 if(err){
  throw err;
 }
 console.log(html);
});

運行 server.js ,結果如下,我們得到了一個完整的 HTML 頁面,且成功插入了數(shù)據(jù):

 vue-ssr-demo node server.js
<!DOCTYPE html>
<html lang="en">
  <head><title>Hello</title></head>
  <body>
  <div data-server-rendered="true">Hello World!</div><div>Hello People!</div>
  </body>
</html>

好,現(xiàn)在頁面生成了,該怎么顯示呢?這里我們借助下框架 Koa 實現(xiàn),先來安裝:

npm install koa -S

然后修改 server.js ,如下:

const data_vue = {
 word: 'Hello World!'
};
const data_tpl = {
 people: 'Hello People!'
};

const Koa = require('koa');
//創(chuàng)建 koa 實例
const koa = new Koa();

const Vue = require('vue');

//創(chuàng)建一個renderer
const renderer = require('vue-server-renderer').createRenderer({
 template: `<!DOCTYPE html>
 <html lang="en">
  <head><title>Hello</title></head>
  <body>
  <!--vue-ssr-outlet--><div>{{people}}</div>
  </body>
 </html>`
});

// 對于任何請求,app將調用該異步函數(shù)處理請求:
koa.use(async (ctx, next) => {
 // await next();
 
 //創(chuàng)建vue實例
 const app = new Vue({
  data: data_vue,
  template: "<div>{{word}}</div>"
 });

 //將vue渲染為HTML
 const body = await renderer.renderToString(app, data_tpl);
 ctx.body = body;
});

// 在端口3001監(jiān)聽:
koa.listen(3001);
console.log('app started at port 3001...');

運行 server.js :

 vue-ssr-demo node server.js
app started at port 3001...

然后打開瀏覽器,輸入網(wǎng)址 http://localhost:3001/ ,即可看到運行后的效果。

這樣就實現(xiàn)了一個簡單的服務端渲染項目,但是我們在平常開發(fā)的時候,肯定不會這么簡單的去構建一個項目,必然會用到一些,比如打包、壓縮的工具,這篇就寫到這里,下一篇我們嘗試使用 webpack 來構建一個 vue 的服務端渲染項目。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI