vue-ssr| 从0到1实现ssr | 思路篇

2,440 阅读4分钟
文末附上具体实现链接 建议对照食用

第一阶段:Vue+koa实现简单服务端渲染,将数据替换模板html的占位符以便seo

核心问题:如何在服务器先编译vue项目的入口页面获得完整的html后再返回给浏览器?
解决思路:vue提供了依赖包vue-server-renderer,可以做到通过【vue实例】生成html代码
  • koa:搭建node服务器

  • vue:后台搭建vue项目

  • vue-server-renderer:将vue的html以数据渲染后转为字符串

  • koa根据请求返回vue

【附】采用模板渲染
  • vue-server-renderer创建渲染器时支持传递一个配置对象,
    • fs以utf-8读取模板html并传给配置对象的template属性
    • 创建渲染器时传递配置对象
结果:至此,我们完成了对html的处理
遗留问题:但css、js等仍未实现

第二阶段:webpack实现编译Vue项目

核心问题:打包编译vue项目,以实现处理js、css等逻辑
解决思路:配置webpack+构建vue项目结构
loader
  • vue-style-loader + css-loader:css

  • vue-loader:将解析.vue文件,提取每个语言块,如有必要,将它们通过其他加载器进行管道传输,最后将它们组装回ES 模块,其默认导出为 Vue.js 组件选项对象。

  • babel-loader:es降级处理

    • @babel/core :核心库
    • @babel/preset-env:预设
plugins
  • html-webpack-plugin : 模板页引入
  • vue-loader/lib/plugin(不需要单独下载):将定义过的其它规则复制并应用到 .vue 文件里相应语言的块
【附】vue-template-compiler也需要下载,因为vue-loader和vue-template-compiler必须保持同一版本
构建vue项目结构

这就不说了,main.js作为入口文件引入导出vue实例

结果:实现webpack编译vue项目的基本结构
遗留问题:1. 未将第一阶段实现的服务端渲染功能和第二阶段实现的编译vue项目功能联系起来;2. 编译之后的js、css如何与服务端渲染出来的html相互关联

第三阶段:返回渲染后的html且css、js功能实现(客户端激活)

核心问题:编译client入口之后的js、css如何与服务端渲染出来的html相互关联
解决思路:1. 在入口组件的最外层div上指定id为app,这样client.js才能找到这个挂载点(vue谓之:客户端激活)2. 在html中引入client编译出的js文件,注意vue提供了两个api,避免我们每次都要手动引这个js文件
结果:访问首页页面展示及js功能均正常

第四阶段:集成路由

核心问题:当用户输入某个子页面地址,即走服务端渲染时,如何实现匹配
解决思路:1. 在创建vue实例的函数中注入router,这样就能保证每次请求的vm实例及路由互相隔离 2. vue提供的渲染方法renderToString支持传递配置信息url,当请求来时,我们可以取请求的url传递进去同时在返回服务器端返回vm实例前先将router进行跳转
结果:集成路由

第五阶段:集成vuex

核心问题:1. 服务端渲染的页面,可能会有数据请求的需求,如何处理;2. 数据请求后可能会导致store中的state被改变,如何去通知浏览器使用新的state
解决思路:
  1. 服务器端规定组件如果可能为服务器渲染页面,则将请求数据放在一个特定名称的方法中(asyncData),这样,在服务器返回app实例前就可以判断,如果有这个方法,则执行,获取数据后再向下执行,这样,渲染页面的时候就是新数据了 ;
  2. vue-ssr中会默认将server-entry.js中context的state属性值挂载到window.__INITIAL_STATE__,所以在server-entry返回app前我们可以先将新的store挂载在context.state上,然后可以在store中进行判断,如果存在此属性(即表明是浏览器环境),则使用store.replaceState进行替换,这样就实现浏览器端是使用新的state了

具体实现链接