接触前端SSR服务器端渲染

176 阅读2分钟

简介

通常我们开发为了良好的用户体验和前后端分离,大多都是单页应用,通过接口获取后端数据在浏览器中输出组件,进行生成 DOM 和操作 DOM 来实现用户交互。然而,也可以将同一个组件渲染为服务器端的 HTML 字符串,将它们直接发送到浏览器,最后将静态标记"混合"为客户端上完全交互的应用程序,这就是服务器端渲染。

对比单页面项目服务器端渲染有哪些好处

  1. 更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面,单页应用是根据路由,通过 ajax 异步的更新页面一个部门来实现应用效果,这样抓取工具是无法获取页面。
  2. 对于缓慢的网络或运行缓慢的设备。可提供获取网页速度,有良好的用户体验,由于单页应用在第一次加载时,需要将一个打包好(requirejs 或 webpack 打包)的 js 发送到浏览器后,才能启动应用。

使用vue SSR

这里我们使用 Node.js server 的服务器端单页面应用程序渲染。

创建项目引入依赖

环境:Node.js 版本 6+ 创建好文件夹后,安装vue以及vue服务端渲染需要的依赖:

    npm init
    npm install vue vue-server-renderer --save

安装Node.js Web 应用程序框架express:

npm install express --save

新建一个demo.js来引入依赖并启动我们的服务:

const Vue = require('vue');
const vsRenderer = require('vue-server-renderer')
const server = require('express')();

server.get('*', (req, res) => {
  res.send('Hello World!')
})

server.listen(8080);

EE3B4080-AAC3-4fa9-A6AA-2EC388B8C7F6.png

创建页面模板

新建一个index.html模板:

<html>
  <head>
    <!-- 使用双花括号(double-mustache)进行 HTML 转义插值(HTML-escaped interpolation) -->
    <title>{{ title }}</title>

    <!-- 使用三花括号(triple-mustache)进行 HTML 不转义插值(non-HTML-escaped interpolation) -->
    {{{ metas }}}
  </head>
  <body>
    <!--vue-ssr-outlet-->
  </body>
</html>

注意 <!--vue-ssr-outlet--> 注释 -- 这里将是应用程序 HTML 标记注入的地方。

然后,我们可以读取和传输文件到 Vue renderer 中:

const renderer = require('vue-server-renderer').createRenderer({
  template: require('fs').readFileSync('./index.html', 'utf-8')
})

renderer.renderToString(app, (err, html) => {
  console.log(html) // html 将是注入应用程序内容的完整页面
})

整合

最后我们代码整合一下,完成简单的ssrdemo:

const Vue = require('vue');
const vsRenderer = require('vue-server-renderer')
const server = require('express')();
const template = require('fs').readFileSync('./index.html', 'utf-8');
const renderer = vsRenderer.createRenderer({
  template,
});

const context = {
    title: 'vue ssr',
    metas: `
        <meta name="keyword" content="vue,ssr">
        <meta name="description" content="vue srr demo">
    `,
};

server.get('*', (req, res) => {
  const app = new Vue({
    data: {
      url: req.url
    },
    template: `<div>Hello SSR</div>`,
  });

  renderer
  .renderToString(app, context, (err, html) => {
    console.log(html);
    console.log('err', err)
    if (err) {
      res.status(500).end('Internal Server Error')
      return;
    }
    res.end(html);
  });
})

server.listen(8080);

222.png