什么是服务端渲染?

简单理解是将组件或页面通过服务器生成html字符串,再发送到浏览器,最后将静态标记"混合"为客户端上完全交互的应用程序。

服务端渲染的优点

  1. 更好的SEO,搜索引擎爬虫可以抓取渲染好的页面

  2. 更快的内容到达时间(首屏加载更快),因为服务端只需要返回渲染好的HTML,这部分代码量很小的,所以用户体验更好

服务端渲染的缺点

  1. 首先就是开发成本比较高,比如某些声明周期钩子函数(如beforeCreate、created)能同时运行在服务端和客户端,因此第三方库要做特殊处理,才能在服务器渲染应用程序中运行。

  2. 由于服务端渲染要用Nodejs做中间层,所以部署项目时,需要处于Node.js server运行环境。在高流量环境下,还要做好服务器负载和缓存策略

第一步:编写entry-client.js和entry-server.js

entry-client.js只在浏览器环境下执行,所以需要显示调用$mount方法,挂载DOM节点

  1. import Vue from 'vue';
  2. import App from './App.vue';
  3. import createStore from './store/index.js';
  4. function createApp() {
  5. const store = createStore();
  6. const app = new Vue({
  7. store,
  8. render: h => h(App)
  9. });
  10. return {app, store}
  11. }
  12. const { app, store } = createApp();
  13. // 使用window.__INITIAL_STATE__中的数据替换整个state中的数据,这样服务端渲染结束后,客户端也可以自由操作state中的数据
  14. if (window.__INITIAL_STATE__) {
  15. store.replaceState(window.__INITIAL_STATE__);
  16. }
  17. app.$mount('#app');

entry-server.js需要导出一个函数,在服务端渲染期间会被调用

  1. import Vue from 'vue';
  2. import App from './App.vue';
  3. import createStore from './store/index.js';
  4. export default function(context) {
  5. // context是上下文对象
  6. const store = createStore();
  7. let app = new Vue({
  8. store,
  9. render: h => h(App)
  10. });
  11. // 找到所有 asyncData 方法
  12. let components = App.components;
  13. let asyncDataArr = []; // promise集合
  14. for (let key in components) {
  15. if (!components.hasOwnProperty(key)) continue;
  16. let component = components[key];
  17. if (component.asyncData) {
  18. asyncDataArr.push(component.asyncData({store})) // 把store传给asyncData
  19. }
  20. }
  21. // 所有请求并行执行
  22. return Promise.all(asyncDataArr).then(() => {
  23. // context.state 赋值成什么,window.__INITIAL_STATE__ 就是什么
  24. // 这下你应该明白entry-client.js中window.__INITIAL_STATE__是哪来的了,它是在服务端渲染期间被添加进上下文的
  25. context.state = store.state;
  26. return app;
  27. });
  28. };

上面的asyncData是干嘛用的?其实,这个函数是专门请求数据用的,你可能会问请求数据为什么不在beforeCreate或者created中完成,还要专门定义一个函数?虽然beforeCreatecreated在服务端也会被执行(其他周期函数只会在客户端执行),但是我们都知道请求是异步的,这就导致请求发出后,数据还没返回,渲染就已经结束了,所以无法把 Ajax 返回的数据也一并渲染出来。因此需要想个办法,等到所有数据都返回后再渲染组件

asyncData需要返回一个promise,这样就可以等到所有请求都完成后再渲染组件。下面是在foo组价中使用asyncData的示例,在这里完成数据的请求

  1. export default {
  2. asyncData: function({store}) {
  3. return store.dispatch('GET_ARTICLE') // 返回promise
  4. },
  5. computed: {
  6. article() {
  7. return this.$store.state.article
  8. }
  9. }
  10. }

第二步:配置webpack

webpack配置比较简单,但是也需要针对client和server端单独配置

webpack.client.conf.js显然是用来打包客户端应用的

  1. module.exports = merge(base, {
  2. entry: {
  3. client: path.join(__dirname, '../entry-client.js')
  4. }
  5. });

webpack.server.conf.js用来打包服务端应用,这里需要指定node环境

  1. module.exports = merge(base, {
  2. target: 'node', // 指定是node环境
  3. entry: {
  4. server: path.join(__dirname, '../entry-server.js')
  5. },
  6. output: {
  7. filename: '[name].js', // server.js
  8. libraryTarget: 'commonjs2' // 必须按照 commonjs规范打包才能被服务器调用。
  9. },
  10. plugins: [
  11. new HtmlWebpackPlugin({
  12. template: path.join(__dirname, '../index.ssr.html'),
  13. filename: 'index.ssr.html',
  14. files: {
  15. js: 'client.js'
  16. }, // client.js需要在html中引入
  17. excludeChunks: ['server'] // server.js只在服务端执行,所以不能打包到html中
  18. })
  19. ]
  20. });

第三步:启动服务

打包完成后就可以启动服务了,在start.js中我们需要把server.js加载进来,然后通过renderToString方法把渲染好的html返回给浏览器

  1. const bundle = fs.readFileSync(path.resolve(__dirname, 'dist/server.js'), 'utf-8');
  2. const renderer = require('vue-server-renderer').createBundleRenderer(bundle, {
  3. template: fs.readFileSync(path.resolve(__dirname, 'dist/index.ssr.html'), 'utf-8') // 服务端渲染数据
  4. });
  5. server.get('*', (req, res) => {
  6. renderer.renderToString((err, html) => {
  7. // console.log(html)
  8. if (err) {
  9. console.error(err);
  10. res.status(500).end('服务器内部错误');
  11. return;
  12. }
  13. res.end(html);
  14. })
  15. });

Vue 服务端渲染(SSR)的更多相关文章

  1. Egg + Vue 服务端渲染工程化实现

    在实现 egg + vue 服务端渲染工程化实现之前,我们先来看看前面两篇关于Webpack构建和Egg的文章: 在 Webpack工程化解决方案easywebpack 文章中我们提到了基于 Vue ...

  2. vue服务端渲染axios预取数据

    首先是要参考vue服务端渲染教程:https://ssr.vuejs.org/zh/data.html. 本文主要代码均参考教程得来.基本原理如下,拷贝的原文教程. 为了解决这个问题,获取的数据需要位 ...

  3. vue服务端渲染简单入门实例

    想到要学习vue-ssr的同学,自不必多说,一定是熟悉了vue,并且多多少少做过几个项目.然后学习vue服务端渲染无非解决首屏渲染的白屏问题以及SEO友好. 话不多说,笔者也是研究多日才搞明白这个服务 ...

  4. [vue] vue服务端渲染nuxt.js

    初始化 使用脚手架工具 create-nuxt-app 快速创建 npx create-nuxt-app <项目名> npx create-nuxt-app 执行一些选择 在集成的服务器端 ...

  5. 解析Nuxt.js Vue服务端渲染摸索

    本篇文章主要介绍了详解Nuxt.js Vue服务端渲染摸索,写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下.如有不足之处,欢迎批评指正. Nuxt.js 十分简单易用.一个简单 ...

  6. vue服务端渲染之nuxtjs

    前言 本篇主要针对nuxtjs中的一些重要概念整理和代码实现! 在学习vue服务端渲染之前,先搞清楚几个概念: 什么是客户端渲染(CSR) 什么是服务端渲染(SSR) CSR和SSR有什么异同 客户端 ...

  7. vue服务端渲染提取css

    vue服务端渲染,提取css单独打包的好处就不说了,在这里主要说的是抽取css的方法 要从 *.vue 文件中提取 CSS,可以使用 vue-loader 的 extractCSS 选项(需要 vue ...

  8. 实例PK(Vue服务端渲染 VS Vue浏览器端渲染)

    Vue 2.0 开始支持服务端渲染的功能,所以本文章也是基于vue 2.0以上版本.网上对于服务端渲染的资料还是比较少,最经典的莫过于Vue作者尤雨溪大神的 vue-hacker-news.本人在公司 ...

  9. Vue服务端渲染和Vue浏览器端渲染的性能对比

    Vue 2.0 开始支持服务端渲染的功能,所以本文章也是基于vue 2.0以上版本.网上对于服务端渲染的资料还是比较少,最经典的莫过于Vue作者尤雨溪大神的 vue-hacker-news.本人在公司 ...

随机推荐

  1. ubantu安全卸载火狐浏览器

    首先查看浏览器相应的安装包,命令: dpkg --get-selections |grep firefox 2.删除相面出现的包的命令: sudo apt-get purge pck1-name  p ...

  2. 根据文件大小自动判断单位B,KB,MB,GB

    <php> /** * 文件大小格式化 * @param integer $size 初始文件大小,单位为byte * @return array 格式化后的文件大小和单位数组,单位为by ...

  3. CSS 使用absolute 是<div>居中

    <style>        .col-center-block {            position: absolute;            top: 50%;         ...

  4. [LeetCode] Short Encoding of Words 单词集的短编码

    Given a list of words, we may encode it by writing a reference string S and a list of indexes A. For ...

  5. 安装Percona版本的MySQL主从复制

    准备两台虚拟机,按顺序执行1.1节的公共部分 1.1 首先安装 cmake # yum –y install cmake     //也需要安装gcc-c++,openssl openssl-deve ...

  6. git-format-patch

    使用方法: git diff ${old-commit} ${new-commit} > commit-operation.patch OR git format- b1af44f > c ...

  7. (转载)CentOS6 Linux系统添加永久静态路由的方法

    https://blog.csdn.net/magerguo/article/details/49636231

  8. SQL - 1.区分login、user、schema和role

        Login Login 是Server一级的概念,表示登录Server的凭证,比如在Server_A上有一个数据库DA,那么想要访问数据库DA,第一步要做的事情就是先登录到Hosting该数据 ...

  9. 为什么不能用 JS 获取剪贴板上的内容?

    为什么不能用 JS 获取剪贴板上的内容? 为什么不能用 JS 获取剪贴板上的内容? 发一串口令给朋友朋友复制这串口令,然后访问你的网站你在网站上用 JS 读取朋友剪贴板上的口令根据不同的口令,显示不同 ...

  10. 电子产品使用感受之-- AirPods + Apple Watch S4 = Smart iPod ?