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

news2024/11/20 8:23:35

前后端分离多年,为何服务端渲染(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的强大能力。


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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1402123.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入解析 JavaScript 中的 F.prototype

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;《爱蹦跶的大A阿》 &#x1f525;当前正在更新专栏&#xff1a;《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​ ​ ✨ 前言 JavaScript作为一门原型继承语言,函数的prototype属性在其中发挥着重…

基于CanvasLabel的Leaflet矢量数据免切片属性标注实践

目录 前言 一、Leaflet.CanvasLabel 1、开源地址 2、设置参数说明 二、组件集成 1、新建html文件 2、声明样式 3、定义矢量文本渲染器 4、定义地图 5、添加矢量数据 6、最终效果 总结 前言 在一般的业务场景中&#xff0c;针对小量的矢量数据&#xff0c;比如POI兴…

快速统计文件和文件夹大小

windows上没有方便统计各个层级文件夹文件大小的工具&#xff0c;于是自己做了一个 源码 https://gitee.com/chen227/calc-tree-space

imgaug库图像增强指南(32):塑造【雪景】效果的视觉魔法

引言 在深度学习和计算机视觉的世界里&#xff0c;数据是模型训练的基石&#xff0c;其质量与数量直接影响着模型的性能。然而&#xff0c;获取大量高质量的标注数据往往需要耗费大量的时间和资源。正因如此&#xff0c;数据增强技术应运而生&#xff0c;成为了解决这一问题的…

【项目日记(三)】内存池的整体框架设计

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:项目日记-高并发内存池⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你做项目   &#x1f51d;&#x1f51d; 开发环境: Visual Studio 2022 项目日…

python-分享篇-一箭穿心

一箭穿心&#x1f498; 代码 from turtle import * color(black,red) pensize(5) begin_fill() penup() goto(50,50) pendown() right(45) goto(100,0) left(90) fd(120) circle(50,225) penup() goto(0,0) pendown() left(135) fd(120) circle(50,225) seth(90) circle(50,2…

unity 单例模式(实例详解)

文章目录 在Unity中&#xff0c;单例模式是一种常用的编程设计模式&#xff0c;用于确保在整个应用程序生命周期中&#xff0c;只有一个类的实例存在。这样可以保证数据的全局唯一性和共享性&#xff0c;例如游戏场景中的资源管理器、游戏控制器、事件管理器等。 以下是一个简单…

WorkPlus Meet私有化视频会议软件-构建安全高效的内网会议体验

在企业内部&#xff0c;高效的会议协作是推动团队协同和工作效率的关键。而内网会议系统成为了构建安全高效的内部会议体验的必要工具。作为一家领先的内网会议系统&#xff0c;WorkPlus Meet以其卓越的性能和智能化的功能&#xff0c;助力企业实现高效安全的内部会议体验。 为…

python实现图片式PDF转可搜索word文档[OCR](已打包exe文件)

目录 1、介绍 1.1、痛点 1.2、程序介绍 2、安装方式 2.1、&#x1f53a;必要环节 2.2、脚本安装 2.2.1、不太推荐的方式 2.2.2、节约内存的方式 2.3、⭐完整版安装 3、使用 3.1、最终文件目录 3.2、主程序 3.2.1、绝对路径 3.2.2、是否为书籍 3.2.3、⭐截取区域 …

Threejs实现立体3D园区解决方案及代码

一、实现方案 单独贴代码可能容易混乱&#xff0c;所以这里只讲实现思路&#xff0c;代码放在最后汇总了下。 想要实现一个简单的工业园区、主要包含的内容是一个大楼、左右两片停车位、四条道路以及多个可在道路上随机移动的车辆、遇到停车位时随机选择是否要停车&#xff0…

内存地址解码3至8 线解码器(74LS138)

3 至 8 线解码器 &#xff08;74LS138&#xff09;1 内存地址解码 处理器通常可以寻址比单个内存芯片覆盖的内存空间大得多 的内存空间。 为了将存储设备拼接到处理器的地址空间中&#xff0c;解码是必要的。 例如&#xff0c;8088 发出 20 位 地址&#xff0c;总共有 1MB 的…

stable diffuison的安装和使用

stable diffuison的安装和使用 简单介绍 Stable Diffusion是一个深度学习文本到图像的生成模型&#xff0c;它可以根据文本描述生成详细的图像。这个模型主要应用于文本生成图像的场景中&#xff0c;通过给定的文本提示词&#xff0c;模型会输出一张与提示词相匹配的图片。 S…

【spring】代码生成器

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;spring ⛺️稳中求进&#xff0c;晒太阳 代码生成器&#xff08;本质IO流&#xff09; 在mybatis的逆向工程生成model和mapper接口和xml文件后&#xff0c;还需要反复的写Service的接口和…

(2)(2.1) Andruav Android Cellular(二)

文章目录 前言 5 Andruav Web Client 6 Andruav Telemetry 7 Andruav高级功能 8 将Andruav与SITL配合使用 9 FAQ 10 术语表 前言 Andruav 是一个基于安卓的互联系统&#xff0c;它将安卓手机作为公司计算机&#xff0c;为你的无人机和遥控车增添先进功能。 5 Andruav W…

提升网站关键词排名的工具

随着互联网的蓬勃发展&#xff0c;网站的关键词排名成为衡量网站流量和曝光度的重要指标。在这个竞争激烈的数字时代&#xff0c;站在搜索引擎结果的前列变得至关重要。为了实现这一目标&#xff0c;合理利用关键词排名优化工具是必不可少的。本文将重点介绍147SEO软件&#xf…

RT Thread Stdio生成STM32L431RCT6无法启动问题

一、问题现象 使用RT thread Stdio生成STM32L431RCT6工程后&#xff0c;编译下载完成后系统无法启动&#xff0c;无法仿真debug&#xff1b; 二、问题原因 如果当前使用的芯片支持包版本为0.2.3&#xff0c;可能是这个版本问题&#xff0c;目前测试0.2.3存在问题&#xff0c…

ESP32 MicroPython 小车红外自动寻迹与避障⑭

ESP32 MicroPython 小车红外自动寻迹与避障⑭ 1、小车超声波避障2、 小车红外自动寻迹3、 小车摄像头自动寻迹 1、小车超声波避障 实验目的 使用舵机水平扫描和超声波测距功能&#xff0c;实现小车自动避障行走 实验内容 小车控制舵机转动到中间位置&#xff0c;读取前方距离。…

26、江科大stm32视频学习笔记——W25Q64简介

一、电路图 1、软件模拟的SPI&#xff1a;线可以任意接 2、硬件模拟的SPI&#xff1a;要按以下方式连接 3、本次软件模拟和硬件模拟使用同一个电路图&#xff0c;方便切换 CS&#xff08;片选&#xff09;&#xff1a;PA4 DO&#xff08;从…

适合初学者的 机器学习 资料合集(可快速下载)

AI时代已经来临&#xff0c;机器学习成为了当今的热潮。但是&#xff0c;很多人在面对机器学习时却不知道如何开始学习。 今天&#xff0c;我为大家推荐几个适合初学者的机器学习开源项目&#xff0c;帮助大家更好地了解和掌握机器学习的知识。这些项目都是开源的&#xff0c;…

分享flask_socketio配置时遇到的一些问题

flask_socketio 1.前言 flask_socketio应用启动后&#xff0c;在控制台中&#xff0c;存在着flask_socketio这些烦人的log 一堆的get和post几秒一个让我什么都看不清&#xff0c;因此想要关掉log 结果没想到&#xff0c;找了很多办法半天去不掉flask_socketio的log 试过了…