详解如何使用Vue2做服务端渲染

标签:帮助中心    日期:2017-11-01 11:39    录入:汇盛国际平台    浏览:

  

[vue服务端渲染,vue,js,2,0服务端渲染]详解如何使用Vue2做服务端渲染

  

花费了一个月时间,终于在新养车之家项目中成功部署了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方法)来将需要的数据拿到。最后再通过  

  
  
  window.__initial_state=data
  
  

将其写入网页,最后将服务端渲染好的网页返回回去。

  

  

接下来客户端会将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事件,让页面显示错误信息。

★★★小编:汇盛国际注册 整理文章,欢迎大家转载 ★★★
上一篇:javascript中if和switch,==和===详解
下一篇:没有了
点击右上角的分享按钮即可收藏汇盛国际平台注册 随时随地与好友一起分享精彩内容噢