Vue服务端渲染SSR原理实战学习笔记

  • 原创
  • 作者:程序员三丰
  • 发布时间:2023-07-02 09:08
  • 浏览量:1060
到底是什么Vue SSR,本文带你一探究竟。

什么是 SSR

首先,Vue.js 是一个用于构建客户端应用的框架。默认情况下 Vue 组件的职责实在客户端浏览器中生成和操作 DOM。

然而,Vue 也支持将组件在服务端直接渲染成 HTML 字符串,并作为服务端响应返回给浏览器,最后在浏览器端将静态的 HTML“激活”为能够交互的客户端应用。————》这种服务端渲染技术就是 SSR。

为什么要用 SSR

优势:

  • 更快的首屏加载,原因有二:
    • 服务端渲染的 HTML 无需等到所有的 Javascript 都下载并执行完成之后才显示;
    • 服务端更快的数据库连接(数据接口相关请求).
  • 更好的 SEO,因为搜索引擎爬虫可以直接看到完全渲染的页面。
  • 统一的心智模型,理解引用 Vue 官方的介绍:

    你可以使用相同的语言以及相同的声明式、面向组件的心智模型来开发整个应用,而不需要在后端模板系统和前端框架之间来回切换。

限制和劣势:

  • 开发中的限制:
    • 浏览器端特定的代码只能在某些生命周期钩子中使用;
    • 一些外部库可能需要特殊处理才能在服务端渲染的应用中运行。
  • 更多的与构建配置和部署相关的要求。
    • 服务端渲染的应用需要一个能让 Node.js 服务器运行的环境,不像完全静态的 SPA 那样可以部署在任意的静态文件服务器上。
  • 更高的服务端渲染
    • 在 Node.js 中渲染一个完整的应用要比仅仅托管静态文件更加占用 CPU 资源。

SSR vs SSG

SSG:静态站点生成,也被称为预渲染,是另一种流行的构建快速网站的技术。

SSR 与 SSG 相同之处:

  • 都带来了优秀的首屏加载性能。

SSR 与 SSG 区别:

  • SSG 比 SSR 应用的花销更小,也更容易部署,因为 SSG 输出的是静态 HTML 和资源文件,且 SSG 仅可以用于消费静态数据的页面。

基础教程

服务端渲染一个应用

  • 第一步 创建一个新文件夹 vue-ssr,并在该文件夹下执行npm init -y生成 package.json,编辑 package.json 文件添加一行"type": "module",修改后的 package.json 文件内容如下:
    {
      "name": "vue-ssr",
      "version": "1.0.0",
      "type": "module",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "dependencies": {
        "express": "^4.18.2",
        "vue": "^3.3.4"
      }
    }
    
  • 第二步 安装依赖包
    • 安装 vue npm install vue
    • 安装 express npm install express
  • 第三步 创建 server.js 文件,并写入如下代码:

    import express from "express";
    import { createSSRApp } from "vue";
    // 导入Vue的服务端渲染API
    import { renderToString } from "vue/server-renderer";
    
    const server = express();
    
    server.get("/", (req, res) => {
      const app = createSSRApp({
        data: () => ({ count: 1 }),
        template: `<button @click="count++">{{ count }}</button>`,
      });
    
      renderToString(app).then((html) => {
        res.send(`    <!DOCTYPE html>
        <html>
          <head>
            <title>Vue SSR Example</title>
          </head>
          <body>
            <div id="app">${html}</div>
          </body>
        </html>
      `);
      });
    });
    
    server.listen(3000, () => {
      console.log("Server Started....");
    });
    

    Vue 的服务端渲染 API renderToString() 接受一个 Vue 应用实例作为参数,返回一个 Promise,当 Promise resolve 时返回应用渲染的 HTML。

  • 第四步 运行 node server.js 启动服务,浏览器访问 http://localhost:3000 ,就可以看到页面中按钮了。

客户端激活

什么是客户端激活呢?
细心的同学可能已发现,上文运行服务端代码后,点击浏览器中的按钮数字并没有自增改变。这是因为这段 HTML 代码在客户端是完全静态的,并没有在浏览器中加载 Vue。
那么为了使客户端的应用可交互,Vue 需要执行一个激活步骤。

在激活过程中,Vue 会创建一个于服务端完全相同的应用实例,然后将每个组件与它应该控制的 DOM 节点相匹配,并添加 DOM 事件监听器。

由于实现激活需要重新组织代码结构(下文的代码结构部分会详解),所以此处先展示一个激活的代码片段:

// 该文件运行在浏览器中
import { createSSRApp } from "vue";

const app = createSSRApp({
  // ...和服务端完全一致的应用实例
});

/**
 * 在客户端挂载一个 SSR 应用时,会假定 HTML 是预渲染的,然后执行激活过程,而不是挂载新的 DOM 节点
 */
app.mount("#app");

注意 在激活模式下挂载应用,应该使用createSSRApp() 而不是createApp()

完整 SSR 代码结构

通用代码 app.js

通用代码只是指在客户端和服务端可复用的代码及其依赖项,我们可以把这些拆分到一个或多个独立的文件中。本例中代码逻辑简单,拆分一个 app.js 文件即可:

// app.js
import { createSSRApp } from "vue";

export function createApp() {
  return createSSRApp({
    data: () => ({ count: 1 }),
    template: `<button @click="count++">{{ count }}</button>`,
  });
}

客户端入口文件 client.js

// client.js
import { createApp } from "./app.js";

createApp().mount("#app");

服务端入口文件 server.js
运行服务端文件后,为了在浏览器中加载客户端文件,还需要在 server.js 文件中做以下修改:

  • 增加一行 server.use(express.static('.')) 来托管客户端文件。
  • <script type="module" src="./client.js"></script> 添加到 HTML 外壳以加载客户端入口文件。
  • 通过在 HTML 外壳文件中添加 Import Map 以支持在浏览器中使用 import * from 'vue'

修改后的 server.js 完整代码如下:

import express from "express";
import { renderToString } from "vue/server-renderer";
import { createApp } from "./app.js";

const server = express();

server.get("/", (req, res) => {
  const app = createApp();

  renderToString(app).then((html) => {
    res.send(`
    <!DOCTYPE html>
    <html>
      <head>
        <title>Vue SSR Example</title>
        <script type="importmap">
        {
          "imports": {
            "vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
          }
        }
        </script>
        <script type="module" src="/client.js"></script>
      </head>
      <body>
        <div id="app">${html}</div>
      </body>
    </html>
    `);
  });
});

server.use(express.static("."));

server.listen(3000, () => {
  console.log("Server Started....");
});

此时我们一开始创建的文件夹下的代码结构如下:

vue-ssr
|-- app.js
|-- client.js
|-- server.js
|-- package.json
|-- package-lock.json
|-- node_modules

最后重新运行 node server.js,再访问 http://localhost:3000 页面,点击按钮数字就会自增改变了。

通用解决方案

由于实现一套完整的 SSR 技术构建会非常复杂,因此建议和推荐大家在通过上面实例教程了解到 SSR 原理之后,选择一些成熟的 SSR 解决方案,以提高工作效率。下面推荐几个 Vue 生态中的 SSR 解决方案。

Nuxt 是一个构建于 Vue 生态系统之上的全栈框架,它为编写 Vue SSR 应用提供了丝滑的开发体验。更棒的是,你还可以把它当作一个静态站点生成器来用!我们强烈建议你试一试。

Quasar 是一个基于 Vue 的完整解决方案,它可以让你用同一套代码库构建不同目标的应用,如 SPA、SSR、PWA、移动端应用、桌面端应用以及浏览器插件。除此之外,它还提供了一整套 Material Design 风格的组件库。

  • Vite SSR

    Vite 提供了内置的 Vue 服务端渲染支持,但它在设计上是偏底层的。如果你想要直接使用 Vite,可以看看 vite-plugin-ssr,一个帮你抽象掉许多复杂细节的社区插件。

声明:本文为原创文章,51blog.xyz和作者拥有版权,如需转载,请注明来源于51blog.xyz并保留原文链接:https://www.51blog.xyz/article/45

文章归档

强烈推荐的PHP全栈开发后台管理系统
buildadmin logo
Thinkphp8 Vue3 Element PLus TypeScript Vite Pinia

🔥BuildAdmin是一个永久免费开源,无需授权即可商业使用,且使用了流行技术栈快速创建商业级后台管理系统。

推荐文章

热门标签

PHP ThinkPHP ThinkPHP5.1 Go Mysql Mysql5.7 Redis Linux CentOS7 Git HTML CSS CSS3 Javascript JQuery Vue LayUI VMware Uniapp 微信小程序 docker wiki Confluence7 学习笔记 uView ES6 Ant Design Pro of Vue React ThinkPHP6.0 chrome 扩展 翻译工具 Nuxt SSR 服务端渲染 scrollreveal.js ThinkPHP8.0 Mac webman 跨域CORS vscode GitHub ECharts Canvas vue3 three.js 微信支付 PHP全栈开发 Python AI 人工智能 AI辅助 工作经验 实战笔记