vue ssr从认识到构建一个工程项目(一)

vue ssr从认识到构建一个工程项目(一)

vue ssr 入门

前言

近期需要接手一个 vue ssr 项目,由于本人之前没有写过 ssr,只是稍微了解了点。所以跟着官网学了下,并整理出了这篇学习笔记。方便自己以后对 vue ssr 知识的回顾。好记性不如烂笔头。

介绍

相信大家在看到这篇文章之前,都知道 ssr 是什么了。SSR,英文全称叫 Server(服务) side(端) rendering (渲染)哈哈 ☺

那么究竟什么是服务器端渲染?

Vue.js 是构建客户端应用程序的框架。默认情况下,可以在浏览器中输出 Vue 组件,进行生成 DOM 和操作 DOM。然而,也可以将同一个组件渲染为服务器端的 HTML 字符串,将它们直接发送到浏览器,最后将这些静态标记”激活”为客户端上完全可交互的应用程序。

服务器渲染的 Vue.js 应用程序也可以被认为是”同构”或”通用”,因为应用程序的大部分代码都可以在服务器客户端上运行。

如果你问我为什么使用 ssr 呢?(具体可参考官网)

  • 有利于 seo。
  • 更快的内容到达时间 (time-to-content),特别是对于缓慢的网络情况或运行缓慢的设备。大体可以理解为渲染出页面时间,csr 比 ssr 多了个 js 下载时间。因为 ssr 一开始加载下来就渲染出来了,然后在下载激活 html 的 js。csr 是下载完在渲染。

正文

基本用法

ssr 主要依靠两个包vue-server-renderervue(两个版本必须匹配)

安装: npm install vue vue-server-renderer --save

入门配置

ssr 最简易配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// server.js
const server = require('express')();
const Vue = require('vue');
const renderer = require('vue-server-renderer').createRenderer();

server.get('*', (req, res) => {
const context = {
url: req.url
};
const app = new Vue({
template: `<div>${context.url}</div>`
});
renderer.renderToString(app, (err, html) => {
if (err) {
res.status(500).end('Internal Server Error');
return;
}
res.end(`
<!DOCTYPE html>
<html lang="en">
<head><title>Hello</title></head>
<body>${html}</body>
</html>
`);
});
});

server.listen(8080);

node server.js 浏览器输入 localhost:8080 访问该 ssr 页面

这时候你可以看到,无论你输入什么路径,页面文本都会显示出你的路径

clipboard.png

ssr 使用模板

当你在渲染 Vue 应用程序时,renderer 只从应用程序生成 HTML 标记 (markup)。在这个示例中,我们必须用一个额外的 HTML 页面包裹容器,来包裹生成的 HTML 标记。纯客户端渲染的时候,会有一个模板,会插入你打包后的一些文件等。那么 ssr 会不会也有这种模板呢?当然会有。

  • 首先在根目录下新建一个index.template.html文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <title>Hello</title>
    </head>
    <body>
    <!--vue-ssr-outlet-->
    </body>
    </html>

    注意了 –跟 vue 或者 outlet 跟–之间不能用空格。注释 – 这里将是应用程序 HTML 标记注入的地方。

  • 接下来,修改下刚才的 server.js 文件后如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    const server = require('express')();
    const Vue = require('vue');
    const renderer = require('vue-server-renderer').createRenderer({
    template: require('fs').readFileSync('./index.template.html', 'utf-8')
    });
    server.get('*', (req, res) => {
    const context = {
    url: req.url
    };
    const app = new Vue({
    template: `<div>${context.url}</div>`
    });
    renderer.renderToString(app, (err, html) => {
    if (err) {
    res.status(500).end('Internal Server Error');
    return;
    }
    res.end(html);
    });
    });

    server.listen(8080);

    就是在 createRenderer 中多加一个参数 template(读取模板文件),并传递给 createRenderer 方法

    模板还支持插值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <html>
    <head>
    <!-- 使用双花括号(double-mustache)进行 HTML 转义插值(HTML-escaped interpolation) -->
    <title>{{ title }}</title>

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

    我们可以通过传入一个”渲染上下文对象”,作为 renderToString 函数的第二个参数,来提供插值数据:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    const context = {
    title: 'hello',
    meta: `
    <meta ...>
    <meta ...>
    `
    };

    renderer.renderToString(app, context, (err, html) => {
    // 页面 title 将会是 "Hello"
    // meta 标签也会注入
    });
编写通用代码

我们以往的纯浏览器渲染都是把 js 下载到本地执行的。上述代码你会发现都是用的同一个 Vue 构造函数,但是想对该构造函数做特殊处理时,就会对其他用户造成污染。因此,我们不应该直接创建一个应用程序实例,而是应该暴露一个可以重复执行的工厂函数,为每个请求创建新的应用程序实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 修改原先代码如下
-const Vue = require('vue');
+const createApp = require('./app.js')

- const app = new Vue({
- template: `<div>${context.url}</div>`
- })
+ const { app } = createApp(context)

// 新增app.js
const Vue = require('vue');

module.exports = function createApp(context) {
const app = new Vue({
template: `<div>${context.url}</div>`
})
return { app }
}

这样,每次访问该服务器的时候,都会生成一个新的 vue 实例。同样的规则也适用于 router、store 和 event bus 实例。你不应该直接从模块导出并将其导入到应用程序中,而是需要在 createApp 中创建一个新的实例,并从根 Vue 实例注入。

参考

Vue SSR 指南

vue 服务端渲染 ssr

带你五步学会 Vue SSR

#

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×