亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

詳解如何使用Vue2做服務端渲染

2019-11-19 16:59:32
字體:
來源:轉載
供稿:網友

花費了一個月時間,終于在新養車之家項目中成功部署了vue2服務端渲染(SSR),并且使用上了Vuex 負責狀態管理,首屏加載時間從之前4G網絡下的1000ms,提升到了現在500-700ms之間,SSR的優勢有很多,現在讓我來跟你細細道來。

技術棧

服務端:Nodejs(v6.3)

前端框架 Vue2.1.10

前端構建工具:webpack2.2 && gulp

代碼檢查:eslint

源碼:es6

前端路由:vue-router2.1.0

狀態管理:vuex2.1.0

服務端通信:axios

日志管理:log4js

項目自動化部署工具:jenkins

Vue2與服務端渲染(SSR)

Vue2.0在服務端創建了虛擬DOM,因此可以在服務端可以提前渲染出來,解決了單頁面一直存在的問題:SEO和初次加載耗時較多的問題。同時在真正意義上做到了前后端共用一套代碼。

SSR的實現原理

客戶端請求服務器,服務器根據請求地址獲得匹配的組件,在調用匹配到的組件返回 Promise (官方是preFetch方法)來將需要的數據拿到。最后再通過

<script>window.__initial_state=data</script>

將其寫入網頁,最后將服務端渲染好的網頁返回回去。

接下來客戶端會將vuex將寫入的 __initial_state__ 替換為當前的全局狀態樹,再用這個狀態樹去檢查服務端渲染好的數據有沒有問題。遇到沒被服務端渲染的組件,再去發異步請求拿數據。說白了就是一個類似React的 shouldComponentUpdate 的Diff操作。

Vue2使用的是單向數據流,用了它,就可以通過 SSR 返回唯一一個全局狀態, 并確認某個組件是否已經SSR過了。

開啟服務端渲染(SSR)

Web框架目前我們使用的是express,之前使用過一次時間的koa來做SSR,結果發現坑很多,相關的案例太少,有些坑不太好解決,所以為了線上項目的穩定,從而選擇了express。

SSR流程圖

安裝SSR相關

復制代碼 代碼如下:

npm install --save express vue-server-renderer lru-cache es6-promise serialize-javascript vue vue-router axios

vue更新到2.0之后,作者就宣告不再對vue-resource更新,并且vue-resource不支持SSR,所以我推薦使用axios, 在服務端和客戶端可以同時使用。

vue2使用了虛擬DOM, 因此對瀏覽器環境和服務端環境要分開渲染, 要創建兩個對應的入口文件。

瀏覽器入口文件 client-entry.js

使用 $mount 直接掛載

服務端入口文件 server-entry

使用vue的SSR功能直接將虛擬DOM渲染成網頁

client-entry.js 文件

import 'es6-promise/auto';import { app, store } from './app';store.replaceState(window.__INITIAL_STATE__);app.$mount('#app');

在 client-entry.js 文件中引入了app.js, 判斷如果在服務端渲染時已經寫入狀態,則將vuex的狀態進行替換,使得服務端渲染的html和vuex管理的數據是同步的。然后將vue實例掛載到html指定的節點中。

server-entry 文件

import { app, router, store } from './app';const isDev = process.env.NODE_ENV !== 'production';  export default context => { const s = isDev && Date.now(); router.push(context.url); const matchedComponents = router.getMatchedComponents(); if (!matchedComponents.length) {  return Promise.reject({ code: '404' }); }   return Promise.all(matchedComponents.map(component => {  if (component.preFetch) {   return component.preFetch(store);  } })).then(() => {  return app; });};

在 server-entry 文件中服務端會傳遞一個context對象,里面包含當前用戶請求的url,vue-router 會跳轉到當前請求的url中,通過 router.getMatchedComponents( ) 來獲得當前匹配組件,則去調用當前匹配到的組件里的 preFetch 鉤子,并傳遞store(Vuex下的狀態),會返回一個 Promise 對象,并在then方法中將現有的vuex state 賦值給context,給服務端渲染使用,最后返回vue實例,將虛擬DOM渲染成網頁。服務端會將vuex初始狀態也生成到頁面中。 如果 vue-router 沒有匹配到請求的url,直接返回 Promise中的reject方法,傳入404,這時候會走到下方renderStream的error事件,讓頁面顯示錯誤信息。

// 處理所有的get請求app.get('*', (req, res) => { // 等待編譯 if (!renderer) {  return res.end('waiting for compilation... refresh in a moment.'); } var s = Date.now(); const context = { url: req.url }; // 渲染我們的Vue實例作為流 const renderStream = renderer.renderToStream(context);   // 當塊第一次被渲染時 renderStream.once('data', () => {    // 將預先的HTML寫入響應  res.write(indexHTML.head); });   // 每當新的塊被渲染 renderStream.on('data', chunk => {    // 將塊寫入響應  res.write(chunk); });   // 當所有的塊被渲染完成 renderStream.on('end', () => {  // 當vuex初始狀態存在  if (context.initialState) {    // 將vuex初始狀態以script的方式寫入到頁面中   res.write(    `<script>window.__INITIAL_STATE__=${     serialize(context.initialState, { isJSON: true })    }</script>`   );  }    // 將結尾的HTML寫入響應  res.end(indexHTML.tail); });   // 當渲染時發生錯誤 renderStream.on('error', err => {  if (err && err.code === '404') {   res.status(404).end('404 | Page Not Found');   return;  }  res.status(500).end('Internal Error 500'); });})

上面是vue2.0的服務端渲染方式,用流式渲染的方式,將HTML一邊生成一邊寫入相應流,而不是在最后一次全部寫入。這樣的效果就是頁面渲染速度將會很快。還可以引入 lru-cache 這個模塊對數據進行緩存,并設置緩存時間,我一般設置15分鐘的緩存時間。

可以參考vue ssr 官方演示項目的服務端實現 https://github.com/vuejs/vue-hackernews-2.0/blob/master/server.js

axios在客戶端和服務端的使用

創建2個文件用于客戶端和服務端的的通信

create-api-client.js 文件(用于客戶端)

const axios = require('axios');let api;axios.defaults.timeout = 10000;axios.interceptors.response.use((res) => { if (res.status >= 200 && res.status < 300) {  return res; } return Promise.reject(res);}, (error) => { // 網絡異常 return Promise.reject({message: '網絡異常,請刷新重試', err: error});});if (process.__API__) { api = process.__API__;} else { api = {  get: function(target, params = {}) {   const suffix = Object.keys(params).map(name => {    return `${name}=${JSON.stringify(params[name])}`;   }).join('&');   const urls = `${target}?${suffix}`;   return new Promise((resolve, reject) => {    axios.get(urls, params).then(res => {     resolve(res.data);    }).catch((error) => {     reject(error);    });   });  },  post: function(target, options = {}) {   return new Promise((resolve, reject) => {    axios.post(target, options).then(res => {     resolve(res.data);    }).catch((error) => {     reject(error);    });   });  } };}module.exports = api;

create-api-server.js 文件(用于服務端)

const isProd = process.env.NODE_ENV === 'production';const axios = require('axios');let host = isProd ? 'http://yczj.api.autohome.com.cn' : 'http://t.yczj.api.autohome.com.cn';let cook = process.__COOKIE__ || '';let api;axios.defaults.baseURL = host;axios.defaults.timeout = 10000;axios.interceptors.response.use((res) => { if (res.status >= 200 && res.status < 300) {  return res; } return Promise.reject(res);}, (error) => { // 網絡異常 return Promise.reject({message: '網絡異常,請刷新重試', err: error, type: 1});});if (process.__API__) { api = process.__API__;} else { api = {  get: function(target, options = {}) {   return new Promise((resolve, reject) => {    axios.request({     url: target,     method: 'get',     headers: {      'Cookie': cook     },     params: options    }).then(res => {     resolve(res.data);    }).catch((error) => {     reject(error);    });   });  },  post: function(target, options = {}) {   return new Promise((resolve, reject) => {    axios.request({     url: target,     method: 'post',     headers: {      'Cookie': cook     },     params: options    }).then(res => {     resolve(res.data);    }).catch((error) => {     reject(error);    });   });  } };} module.exports = api;

由于在服務端,接口不會主動攜帶 cookie,所以需要在headers里寫入cookie。由于接口數據經常發生變化,所以沒有做緩存。

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品国模在线视频| 永久免费精品影视网站| 日韩欧美在线观看视频| 神马国产精品影院av| 久久影视三级福利片| 欧美乱大交xxxxx另类电影| 日本不卡高字幕在线2019| 欧美日韩国产在线| 精品国产31久久久久久| 一区二区三区视频免费在线观看| 97超碰国产精品女人人人爽| 久久久成人av| 操人视频在线观看欧美| 精品综合久久久久久97| 中文字幕视频一区二区在线有码| 精品国产乱码久久久久酒店| 欧美激情亚洲综合一区| 中文字幕亚洲图片| 国产精品主播视频| 欧美裸体xxxx极品少妇| 国产999精品久久久影片官网| 精品久久久久人成| 久久国产天堂福利天堂| 国产亚洲精品久久久久久牛牛| 77777少妇光屁股久久一区| www.国产一区| 欧美激情2020午夜免费观看| 国产美女精品视频| 欧美乱人伦中文字幕在线| 91成人国产在线观看| 日韩美女免费视频| 1769国内精品视频在线播放| 国产精品久久久久久久av电影| 国产亚洲精品美女| 精品国产91乱高清在线观看| 日韩成人激情视频| 欧美视频在线观看免费网址| 亚洲午夜未删减在线观看| 欧美激情视频一区二区三区不卡| 久久中文精品视频| 精品久久中文字幕| 久久久久国产一区二区三区| 国产美女精品视频免费观看| 自拍偷拍亚洲一区| 日韩av在线最新| 国产精品黄色影片导航在线观看| 欧美俄罗斯乱妇| 国产小视频91| 韩曰欧美视频免费观看| 成人深夜直播免费观看| 成人深夜直播免费观看| 精品国产精品三级精品av网址| 亚洲一区精品电影| 伊人一区二区三区久久精品| 亚洲a区在线视频| 国产日韩精品电影| 日韩精品在线观看一区二区| wwwwwwww亚洲| 日韩免费精品视频| 亚洲欧美中文字幕在线一区| 丝袜情趣国产精品| 国产精品99久久久久久白浆小说| 日韩电影第一页| 久久伊人免费视频| 久久久这里只有精品视频| 国产精品一二三在线| 国产成人免费av电影| 国产成人激情视频| 97婷婷大伊香蕉精品视频| 日韩在线视频线视频免费网站| 国产精品亚洲片夜色在线| 精品久久久久久中文字幕大豆网| 国产精品爱久久久久久久| 在线激情影院一区| 九九综合九九综合| 久久精视频免费在线久久完整在线看| 国产一区二区三区免费视频| 伊人伊成久久人综合网小说| 日韩亚洲欧美成人| 777午夜精品福利在线观看| 亚洲第一中文字幕在线观看| 成人午夜在线视频一区| 免费成人高清视频| 国产精品久久久久久婷婷天堂| 国产精品h在线观看| 日韩成人网免费视频| 成人精品久久一区二区三区| 久久综合久久88| 午夜精品久久久久久99热软件| 日韩免费av一区二区| 国产精品在线看| 亚洲自拍偷拍网址| 色偷偷av一区二区三区| 成人精品一区二区三区| 欧美猛交免费看| 韩剧1988在线观看免费完整版| 精品成人在线视频| 日韩精品极品毛片系列视频| 川上优av一区二区线观看| 久久久久久久91| 色狠狠久久aa北条麻妃| 亚洲免费人成在线视频观看| 国产精品欧美日韩一区二区| 91久久国产婷婷一区二区| 亚洲国产天堂网精品网站| 亚洲电影在线观看| 欧美福利视频在线| 精品视频9999| 成人久久一区二区| 亚洲一二在线观看| 亚洲欧美国产制服动漫| 亚洲人成电影网站色www| 亚洲一区二区三区sesese| 97人人模人人爽人人喊中文字| 日韩欧美在线字幕| 国产精品18久久久久久麻辣| 91精品久久久久久综合乱菊| 亚洲天堂av高清| 精品女同一区二区三区在线播放| 欧美在线视频观看免费网站| 国产精品久久久久9999| 久久成人国产精品| 精品一区二区三区四区在线| 亚洲综合小说区| 国产在线播放91| 欧美性猛交xxxx乱大交3| 日韩激情av在线免费观看| 亚洲人成毛片在线播放| 亚洲午夜色婷婷在线| 欧美激情一区二区三区在线视频观看| 国产精品视频免费在线观看| 国产一区二区三区四区福利| 97视频在线观看免费| 久久香蕉频线观| 日韩电影在线观看中文字幕| 日韩精品免费一线在线观看| 日韩一区二区在线视频| 日韩精品亚洲视频| 亚洲一级片在线看| 亚洲а∨天堂久久精品9966| 日韩精品极品视频免费观看| 高清欧美性猛交xxxx黑人猛交| 午夜精品久久久久久久久久久久| 亚洲人午夜精品| 亚洲国产日韩欧美在线动漫| 国产精品爱久久久久久久| 亚洲人成网站999久久久综合| www.亚洲男人天堂| 日韩欧美在线网址| 日韩精品黄色网| 中文字幕日韩专区| 91午夜理伦私人影院| 久久精品影视伊人网| 日韩在线免费高清视频| 国模精品一区二区三区色天香| 国语自产精品视频在线看抢先版图片| 亚洲福利视频专区| 麻豆乱码国产一区二区三区| 亚洲高清福利视频| 亚洲高清一区二| 久久久精品999| 久久99精品久久久久久青青91| 九九综合九九综合| 国产视频观看一区|