前后端分离多年,为何服务端渲染(SSR)重回风口浪尖?

前后端分离多年,为何服务端渲染(SSR)重回风口浪尖?

什么是服务端渲染?

咱们先搞明白个事儿,啥叫服务端渲染?服务端渲染的全称是 Server-Side Rendering,简称SSR。

简单说,就是在服务器上把网页生成好,整个的HTML页面生成出来,生成出的页面已经包含了所有必要的数据和结构信息,然后直接发给浏览器进行展现。

这和现在流行的前后端分离设计有很大的区别,在前后端分离中,浏览器首先加载到的是一个基本的框架或者说是空壳页面,随后前端通过异步请求后端API获取到数据,然后再动态构建HTML,最后再让浏览器把页面逐渐展现出来。

Web的发展历程

要深入理解服务端渲染为何又成为热点,我们需要回顾Web的发展历史。

早期Web开发(1990年代至2000年代初):在Web的早期,除了静态页面外,大多数网页的HTML是通过服务端渲染的。ASP、JSP、PHP等脚本语言盛行,它们通常将业务逻辑和HTML模板结合在一起,以处理请求并生成完整的HTML页面返回给客户端。在这个阶段,前后端技术混合使用,开发者往往需要同时具备前端和后端的技能。

AJAX的崛起(2005年左右):Ajax技术的发展和jQuery库的普及使得网页能够动态加载数据,实现局部内容的更新,无需刷新整个页面。这一变化增强了前端的交互能力。尽管如此,服务器端渲染仍是主流,前后端职责分离尚未明显。

前端框架的诞生(2009年以后):随着AngularJS、Ember.js等前端框架的诞生,前端工程师能够创建更复杂的单页应用(SPA)。这些应用通过API获取数据,并在客户端渲染页面,显著提升了用户体验。

现代前端框架推动的前后端分离(2013年至今):React、Vue.js等现代前端框架凭借组件化和虚拟DOM等特性,极大地提升了开发效率和用户体验。同时,RESTful API的设计原则被广泛采纳,使后端更专注于提供稳定且高效的数据接口,前端则专责用户界面和交互逻辑。这种模式下,前后端的职责变得更加明确,代码重用和项目可维护性都有所提升。

那么,既然前端正在向着更加独立自主的方向发展,为何服务端渲染(SSR)又重新受到关注呢?原因主要在于单页应用(SPA)面临的两大挑战:

  1. SEO不友好:搜索引擎的爬虫可能无法正确地抓取和解析动态加载的内容,对于内部管理系统这没啥影响,但是网络上还有很多站点需要搜索引擎的流量支持。
  2. 首屏加载时间长:用户必须等待整个JavaScript应用下载并执行完成后,才能看到页面内容,这可能会损失用户体验,特别是在弱网环境下。这为啥成为了一个问题了呢?或许是因为前端应用越来越复杂,体积越来越大,而网络传输速度和前端渲染的速度跟不上这种发展。

为了克服这些挑战,同时保留SPA的优势,现代前端框架引入了服务端渲染功能。这样,前后端可以在某些情况下协同完成渲染任务。这种模式有效地平衡了首屏加载速度、SEO优化和维持SPA的交互体验。

值得注意的是,虽然从技术上看仍然是服务端渲染,但当前驱动这件事的角色实际已转变为前端工程师。在前后端分离这一架构革新之后,前端开发技术得到了迅猛发展,如今前端已经具备充分的能力来高效处理诸如SEO优化、页面加载性能提升等问题,这些与用户体验息息相关的交互问题正是前端的应有工作。

Vue中使用SSR

为了方便理解前端驱动的服务端渲染,这里我们举两个例子。

简单例子

先让我们看一个使用原生Node.js和Vue 3进行SSR的简单例子。

需要安装几个依赖包:

npm init -y
npm install vue@2.7.16 vue-server-renderer@2.7.16 express@4.18.2 --save

然后我们创建一个 server.js 的文件,内容如下:

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

// 创建一个Vue实例
const app = new Vue({
  data: {
    message: 'Hello Vue SSR!'
  },
  template: `<div>{
  { message }}</div>`
});

server.get('*', (req, res) => {
  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 Vue SSR</title></head>
        <body>${html}</body>
      </html>
    `);
  });
});

// 监听8080端口
server.listen(8080, () => {
  console.log('Server running at http://localhost:8080/');
});

在这个例子中,我们首先导入了vue和express,以及vue-server-renderer。然后,我们创建了一个简单的Vue实例,并定义了一个基本的模板。在server.get回调中,我们使用renderToString方法将Vue实例渲染为字符串形式的HTML。

使用 node server.js 启动后,我们可以访问http://localhost:8080/,就会看到 "Hello Vue SSR!" 的消息。

Nuxt.js的例子

上边的例子非常基础,只是为了演示如何使用Vue进行服务器端渲染。在生产环境中,我们需要考虑很多其他因素,比如路由、状态管理、API交互、构建配置、安全性等。对于复杂的应用程序,需要使用像Nuxt这样的高级框架,专注于编写业务逻辑,基础的东西让框架搞定。

首先通过npx(随Node.js一起安装的包执行器)创建一个nuxt项目,命令中的 ssr-nuxt-demo 是项目的名称。

npx nuxi@latest init ssr-nuxt-demo

这个命令会在当前目录中创建一个名为ssr-nuxt-demo的文件夹,在这个文件夹下自动创建项目的基本结构。

然后我们在项目中创建一个pages文件夹,编写一个index.vue文件,Nuxt会自动为该文件创建路由。

文件内容如下:

<template>
  <div>
    <h1>{
  { message }}</h1>
    <button @click="changeMessage">Change Message</button>
  </div>
</template>

<script lang="ts">
  export default {
    data() {
      return {
        message: 'Hello Nuxt.js SSR!'
      }
    },
    methods: {
      changeMessage() {
        this.message = 'Hello from the client side!';
      }
    }
  }
</script>
  

运行 npm run dev,然后在浏览器中访问 http://localhost:3000:

你将看到初始的消息:Hello Nuxt.js SSR!,这是服务端渲染出来的。点击"Change Message"按钮,消息将更改为"Hello from the client side!",这是浏览器中Vue进行的处理。

在这个例子中我们其实展示了一种同构能力,也就是说前后端公用一套代码,我们的组件既能在前端使用,也能在后端使用。也就是我们上文提到的前端驱动服务端渲染的意思。

当然这还是一个简单的例子,不过已经可以让我们体会到Nuxt的强大能力,有兴趣的同学可以去好好体验下Nuxt的强大能力。


以上就是本文的主要内容。

服务端渲染的轮回,似乎让我们看到了某种宿命,不过历史总是在曲折螺旋中上升的,或许某一天我们真的不再需要服务端渲染,这可能是因为通信能力的大幅提升,又或者是流量的某种异变。

关注萤火架构,加速技术提升!

相关推荐

  1. 服务渲染SSR

    2024-01-23 06:08:06       33 阅读
  2. vue之服务渲染(SSR)

    2024-01-23 06:08:06       56 阅读
  3. vue什么是服务渲染(SSR)

    2024-01-23 06:08:06       14 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-23 06:08:06       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-23 06:08:06       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-23 06:08:06       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-23 06:08:06       20 阅读

热门阅读

  1. TS-React:useRef 使用

    2024-01-23 06:08:06       30 阅读
  2. Mongodb 控制查询返回字段

    2024-01-23 06:08:06       34 阅读
  3. RPC教程 4.超时处理机制

    2024-01-23 06:08:06       27 阅读
  4. Redis通过dump.rdb恢复数据

    2024-01-23 06:08:06       34 阅读
  5. MySQL数据备份

    2024-01-23 06:08:06       32 阅读
  6. 使用docker以容器方式安装redis

    2024-01-23 06:08:06       30 阅读
  7. 【PostgreSQL】创建枚举类型和修改枚举值

    2024-01-23 06:08:06       35 阅读
  8. 使用github作为docker镜像存储仓库

    2024-01-23 06:08:06       34 阅读