什么是服务端渲染?

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

服务端渲染的优点

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

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

服务端渲染的缺点

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

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

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

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

import Vue from 'vue';
import App from './App.vue';
import createStore from './store/index.js';

function createApp() {
  const store = createStore();
  const app = new Vue({
      store,
      render: h => h(App)
  });
  return {app, store}
}

const { app, store } = createApp();

// 使用window.__INITIAL_STATE__中的数据替换整个state中的数据,这样服务端渲染结束后,客户端也可以自由操作state中的数据
if (window.__INITIAL_STATE__) {
  store.replaceState(window.__INITIAL_STATE__);
}

app.$mount('#app');

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

import Vue from 'vue';
import App from './App.vue';
import createStore from './store/index.js';

export default function(context) {
  // context是上下文对象
  const store = createStore();
  let app = new Vue({
    store,
    render: h => h(App)
  });

  // 找到所有 asyncData 方法
  let components = App.components;
  let asyncDataArr = []; // promise集合
  for (let key in components) {
    if (!components.hasOwnProperty(key)) continue;
    let component = components[key];
    if (component.asyncData) {
      asyncDataArr.push(component.asyncData({store})) // 把store传给asyncData
    }
  }
  // 所有请求并行执行
  return Promise.all(asyncDataArr).then(() => {
    // context.state 赋值成什么,window.__INITIAL_STATE__ 就是什么
    // 这下你应该明白entry-client.js中window.__INITIAL_STATE__是哪来的了,它是在服务端渲染期间被添加进上下文的
    context.state = store.state;
    return app;
  });
};

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

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

export default {
  asyncData: function({store}) {
    return store.dispatch('GET_ARTICLE') // 返回promise
  },
  computed: {
    article() {
      return this.$store.state.article
    }
  }
}

第二步:配置webpack

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

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

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

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

module.exports = merge(base, {
  target: 'node', // 指定是node环境
  entry: {
    server: path.join(__dirname, '../entry-server.js')
  },
  output: {
    filename: '[name].js', // server.js
    libraryTarget: 'commonjs2' // 必须按照 commonjs规范打包才能被服务器调用。
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, '../index.ssr.html'),
      filename: 'index.ssr.html',
      files: {
        js: 'client.js'
      }, // client.js需要在html中引入
      excludeChunks: ['server'] // server.js只在服务端执行,所以不能打包到html中
    })
  ]
});

第三步:启动服务

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

const bundle = fs.readFileSync(path.resolve(__dirname, 'dist/server.js'), 'utf-8');
const renderer = require('vue-server-renderer').createBundleRenderer(bundle, {
  template: fs.readFileSync(path.resolve(__dirname, 'dist/index.ssr.html'), 'utf-8') // 服务端渲染数据
});

server.get('*', (req, res) => {
  renderer.renderToString((err, html) => {
    // console.log(html)
    if (err) {
      console.error(err);
      res.status(500).end('服务器内部错误');
      return;
    }
    res.end(html);
  })
});

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. Elasticsearch学习笔记二

    PS:上一篇已经介绍了ES的一些基础概念以及单机版ES的安装,配置,本文主要介绍ES的集群管理,CRUD以及简单聚合查询. 集群管理 ES的集群部署起来也很方便,将单机版SCP复制几分,修改elast ...

  2. centos中安装基础环境

    进入到相关目录cd /usr/bin安装python3yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-dev ...

  3. haskell实现简易计算器

    > module Main where > import System.IO > import Data.Char > import Control.Monad > im ...

  4. BOM 浏览器对象模型_同源限制

    “同源政策”(same-origin policy) 浏览器安全的基石 协议相同 域名相同 端口相同 1995年,同源政策由 Netscape 公司引入浏览器.目前,所有浏览器都实行这个政策 A 网页 ...

  5. 使用Java Low Level REST Client操作elasticsearch

    Java REST客户端有两种风格: Java低级别REST客户端(Java Low Level REST Client,以后都简称低级客户端算了,难得码字):Elasticsearch的官方low- ...

  6. C语言面试题分类->宏定义

    1.写一个“标准”宏,这个宏输入两个参数并返回较小的一个 答:#define MIN(x, y) ((x)<(y)?(x):(y))//注意x,y要加括号,因为x,y如果有复合运算会出现问题. ...

  7. Linux 命令分类学习

    Linux常用命令大全(非常全!!!) 系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q ...

  8. 校园服务nabcd需求分析

    我们的团队是敲啥都队 口号是敲啥都队敲啥都对 1.你的创意解决了用户的什么需求?(N) 我们校园服务1主要为了节省学生所浪费的没必要的时间.当你还是大一新生的时候,你是否对大学的规划一无所知,你是否迷 ...

  9. 干货|爱奇艺CDN巡检系统技术解析

    小结: 1. 中心处理系统 /1/将定制后的巡检任务拆分,通过配置与任务分发系统.CMDB*( configuration management database)将派发到边缘拨测系统/2/处理边缘拨 ...

  10. Go笔记

    #Go在win下安装 1. https://golang.google.cn/dl/下载 amd64 版本的zip包 2. 解压后将bin目录添加入path 3. go version可显示版本信息