首先,服务端渲染是什么?所谓SSR其实就是将渲染好的并且带有数据的html页面返回给前端(而不是返回一个空的html页面,剩下的数据通过vue发送异步请求获取。得到数据后重新填充到页面中)
其次,为什么需要SSR?最直接的原因就是搜索引擎优化(SEO),其他的好处有首屏加载更快、页面呈现等待的时间更短(用户体验更好了)。但最重要的还是SEO,对于网站最重要的就是能让百度或者谷歌的爬虫爬取获得更好的排名进而容易被用户搜索到实现品牌推广、变现。而这一切的基础就是需要我们的网页被爬虫抓取,但是爬虫(尤其是百度的)更倾向于爬带数据的完整的html页面,异步的东西比较难被爬虫获取(但也是可以获取的,不过实现相对困难些)。
下面是srr过程(伪代码形式),拷贝到常用编辑器会更好看。最后加上vue-ssr结构图
// 服务器端的文件
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 服务端的入口文件
* 该文件做的事情就是根据服务器接收到的url返回相应的组件。
* 但是这个过程是在服务器上做的!!!!
* ----------------------------------------------
* 暴露出去一个能拿到上下文(即context)的函数
* 将http请求的url地址push到router里
* 返回一个promise
* ----------------------------------------------
* 该函数会接受一个来自服务器的参数(就是上下文context)
* 通过promise返回一个vue的实例(就是then里的app)
*/
export default (context) => {
router.push(context.url)
/*
* 在all里面需要做了些事情。
* 根据context上的url,router.getMatchedComponents()拿到对应的组件。
* 对组件进行遍历,判断组件是否需要请求服务端数据(需要就请求)
* 等组件都拿到了数据,再更新context上的状态
*/
return Promise.all(router.getMatchedComponents().map(
component => {
if(component.fetchServerData) {
return component.fetchServerData(store)
}
}
))
.then(function(){
context.state = store.state
return app
})
}
// 客户浏览器需要做的只是将服务端的文件同步过来,然后将vue实例挂载到服务端渲染的DOM上
store.replaceState(window.__INITIAL_STATE__)
app.$mount('#app')
解释下这张图
左边是源代码,app.js被server/client共用,在生产环境下是不用执行的。
右边是编译后的文件,两份打包后的文件。
一份运行在服务器端,在服务器上有一个打包的渲染函数负责渲染输出浏览器所需要的html页面
一份运行在浏览器端,负责跟这份html页面交互,判断当前服务器返回的数据是否是当前URL对应页面的数据。如果不是的话它会请求一次服务器再渲染,如果是的话它就按照正常vue架构接管页面