首先,服務(wù)端渲染是什么郑兴?所謂SSR其實(shí)就是將渲染好的并且?guī)в袛?shù)據(jù)的html頁(yè)面返回給前端(而不是返回一個(gè)空的html頁(yè)面,剩下的數(shù)據(jù)通過(guò)vue發(fā)送異步請(qǐng)求獲取。得到數(shù)據(jù)后重新填充到頁(yè)面中)
其次贝乎,為什么需要SSR情连?最直接的原因就是搜索引擎優(yōu)化(SEO),其他的好處有首屏加載更快览效、頁(yè)面呈現(xiàn)等待的時(shí)間更短(用戶體驗(yàn)更好了)却舀。但最重要的還是SEO,對(duì)于網(wǎng)站最重要的就是能讓百度或者谷歌的爬蟲(chóng)爬取獲得更好的排名進(jìn)而容易被用戶搜索到實(shí)現(xiàn)品牌推廣朽肥、變現(xiàn)禁筏。而這一切的基礎(chǔ)就是需要我們的網(wǎng)頁(yè)被爬蟲(chóng)抓取,但是爬蟲(chóng)(尤其是百度的)更傾向于爬帶數(shù)據(jù)的完整的html頁(yè)面衡招,異步的東西比較難被爬蟲(chóng)獲取(但也是可以獲取的篱昔,不過(guò)實(shí)現(xiàn)相對(duì)困難些)。
下面是srr過(guò)程(偽代碼形式)始腾,拷貝到常用編輯器會(huì)更好看州刽。最后加上vue-ssr結(jié)構(gòu)圖
// 服務(wù)器端的文件
const app = new Vue({})
const store = new Vuex.Store({})
const router = new Router({
????routes:[
????????{path:'/p1',component:page1},
????????{path:'/p2',component:page1},
????????{path:'/p3',component:page3}
????]
})
/*
* entry-server.js 服務(wù)端的入口文件
* 該文件做的事情就是根據(jù)服務(wù)器接收到的url返回相應(yīng)的組件。
* 但是這個(gè)過(guò)程是在服務(wù)器上做的@思K胍巍!奶栖!
* ----------------------------------------------
* 暴露出去一個(gè)能拿到上下文(即context)的函數(shù)
* 將http請(qǐng)求的url地址push到router里
* 返回一個(gè)promise
* ----------------------------------------------
* 該函數(shù)會(huì)接受一個(gè)來(lái)自服務(wù)器的參數(shù)(就是上下文context)
* 通過(guò)promise返回一個(gè)vue的實(shí)例(就是then里的app)
*/
export default (context) => {
????router.push(context.url)
????/*
????* 在all里面需要做了些事情匹表。
????* 根據(jù)context上的url,router.getMatchedComponents()拿到對(duì)應(yīng)的組件宣鄙。
????* 對(duì)組件進(jìn)行遍歷,判斷組件是否需要請(qǐng)求服務(wù)端數(shù)據(jù)(需要就請(qǐng)求)
????* 等組件都拿到了數(shù)據(jù)袍镀,再更新context上的狀態(tài)
????*/
????return Promise.all(router.getMatchedComponents().map(
????????????component => {
????????????????if(component.fetchServerData) {
????????????????????return component.fetchServerData(store)
????????????????}
????????}
????))
????.then(function(){
????????context.state = store.state
????????return app
????})
}
// ?客戶瀏覽器需要做的只是將服務(wù)端的文件同步過(guò)來(lái),然后將vue實(shí)例掛載到服務(wù)端渲染的DOM上
store.replaceState(window.__INITIAL_STATE__)
app.$mount('#app')
解釋下這張圖
左邊是源代碼冻晤,app.js被server/client共用苇羡,在生產(chǎn)環(huán)境下是不用執(zhí)行的。
右邊是編譯后的文件鼻弧,兩份打包后的文件设江。
????一份運(yùn)行在服務(wù)器端,在服務(wù)器上有一個(gè)打包的渲染函數(shù)負(fù)責(zé)渲染輸出瀏覽器所需要的html頁(yè)面
????一份運(yùn)行在瀏覽器端攘轩,負(fù)責(zé)跟這份html頁(yè)面交互叉存,判斷當(dāng)前服務(wù)器返回的數(shù)據(jù)是否是當(dāng)前URL對(duì)應(yīng)頁(yè)面的數(shù)據(jù)。如果不是的話它會(huì)請(qǐng)求一次服務(wù)器再渲染度帮,如果是的話它就按照正常vue架構(gòu)接管頁(yè)面