SSR 与当年的 JSP、PHP 有什么区别?

Wesley13
• 阅读 978

SSR 与当年的 JSP、PHP 有什么区别?

关注「前端向后」微信公众号,你将收获一系列「用 💖 原创」的高质量技术文章,主题包括但不限于前端、Node.js以及服务端技术

写在前面

SSR(Server-Side Rendering)并不是什么新奇的概念,前后端分层之前很长的一段时间里都是以服务端渲染为主(JSP、PHP),在服务端生成完整的 HTML 页面

(摘自《前端渲染模式的探索》

也就是说,历经 SSR 到 CSR 的大变革之后,如今又从 CSR 出发去探索 SSR 的可能性……似乎兜兜转转又回到了起点,在这之间发生了什么?如今的 SSR 与当年的 JSP、PHP 又有什么区别?

一.SSR 大行其道

回到论坛、博客、聊天室仍旧火热的年代,行业最佳实践是基于 JSP、PHP、ASP/ASP.NET 的动态网站

以 PHP 为例:

<?php if ( count( $_POST ) ): ?><?php include WTG_INCPATH . '/wechat_item_template.php' ?><div style="...">  <div id="wechat-post" class="wechat-post" style="...">    <div class="item" id="item-list">    <?php        $order = 1;        foreach ( $_POST['posts'] as $wechat_item_id ) {        echo generate_item_list( $wechat_item_id, $order );            $order++;        }    ?>    </div>    <?php    $order = 1;    foreach ( $_POST['posts'] as $wechat_item_id ) {    echo generate_item_html( $wechat_item_id, $order );    $order++;    }    ?>    <fieldset style="...">      <section style="...">        <p style="...">如果心中仍有疑问,请查看原文并留下评论噢。(<span style="font-size:0.8em; font-weight:600">特别要紧的问题,可以直接微信联系 ayqywx</span> )</p>      </section>    </fieldset></div><script>    function refineStyle () {        var post = document.getElementById('wechat-post');        // ul ol li        var uls = post.getElementsByTagName('ul');        for (var i = uls.length - 1; i >= 0; i--) {            uls[i].style.cssText = 'padding: 0; margin-left: 1.8em; margin-bottom: 1em; margin-top: -1em; list-style-type: disc;';            uls[i].removeAttribute('class');        };    }    document.addEventListener('DOMContentLoaded', function() {        refineStyle();    });  </script></div><?php endif ?>

(摘自ayqy/wechat_subscribers,一款用来自动生成微信公众平台图文消息的 WordPress 插件)

这一时期网页内容完全由服务端渲染,客户端(浏览器)接收到的是融合了服务数据的 HTML,以及少量内联的(表单)交互逻辑和样式规则,支撑着早期大量动态网站的正是这种纯 SSR 模式

但随着技术实践的深入,这种模式逐渐暴露出了一些问题:

  • 性能差:每一个请求过来都要重新执行一遍数据逻辑和视图逻辑,动态生成 HTML,即便其中很大一部分内容是相同的

  • 机器成本高:Tomcat/Apache 等应用服务器的并发处理能力远不及nginx之类的 Web 服务器,因此需要部署更多的机器

  • 开发/维护难:前后端代码掺杂在一起,人员协作是个问题,并且修改维护要十分谨慎(标签结构容易被破坏)

面对这些问题,两个思路逐渐变得清晰起来,动静分离前后端分层,前者解决性能和机器成本的问题,后者解决开发/维护的问题

二.动静分离

为了充分利用 Web 服务器的静态资源处理优势,同时减轻应用服务器的负担,将资源分为两类:

  • 静态资源:图片、CSS、JS 等公用的,与具体用户无关的资源

  • 动态资源:应用逻辑、数据操作等与具体用户密切相关的资源

两种资源分开部署,把静态资源部署至 Web 服务器或 CDN,应用服务器只部署动态资源。如此这般,静态资源响应更快了(浏览器缓存、CDN 加速),应用服务器压力更小了,皆大欢喜

然而,视图逻辑却被我们漏掉了,HTML 算作静态资源还是动态资源?

前后端分层就是为了回答这个问题

三.前后端分层

视图逻辑的特殊之处在于:

  • 与数据密切相关

  • 服务端与客户端均可承载视图逻辑

也就是说,HTML 视图结构的创建和维护工作,可以由服务端完成,也可以在客户端完成,都依赖服务数据。但与服务端相比,客户端环境有一些优势:

  • 无需刷新(重新请求页面)即可更新视图

  • 免费的计算资源

因此,视图逻辑划分到了客户端(即 CSR),以数据接口为界,分成前后端两层

  • 后端:提供数据及数据操作支持

  • 前端:负责数据的呈现和交互功能

自此,前后端各司其职,前端致力于用户体验的提升,后端专注业务领域,并行迭代,(不涉及接口变化时)互不影响

四.CSR 如日中天

前后端分层之后,进入了 CSR 的黄金时代,探索出了功能插件、UI 库、框架、组件等多种代码复用方案,最终形成了繁荣的组件生态

组件化的开发方式之下,纯 CSR 模式日益盛行:

<!DOCTYPE html><html><head>    <title>My Awesome Web App</title>    <meta charset="utf-8"></head><body>    <div id="app"></div>    <script src="bundle.js"></script></body></html>

这种模式下,几乎所有的页面内容都由客户端动态渲染而来,包括创建视图、请求数据、融合数据与模版、交互功能在内的所有工作,都交由一套数据驱动的组件渲染机制来全权管理,而不必再关注组件之下的 DOM 结构维护等工作,有效提高了前端的生产效率。但一些问题也随之而来:

  • 在组件树首次渲染完之前,页面上无法展示任何内容,包括 loading

  • 数据请求必须等到所属组件开始渲染才能发出去

这些问题的根源在于目前的组件渲染流程是同步阻塞的,对首屏性能提出了挑战:

  • 低端设备上 JS 执行效率低,白屏时间长

  • 弱网环境下数据返回慢,loading 时间长

CSR 虽然利用了用户设备的计算资源,但同时也受其性能、网络环境等不可控因素的制约。于是,大家又重新将目光聚集到了 SSR

五.SSR 东山再起

SSR 模式下,首屏内容在服务端生成,客户端收到响应 HTML 后能够直接呈现内容,而无需等到组件树渲染完毕

虽然核心思想都是在服务端完成页面渲染工作,但如今的 SSR 与先前大不相同,体现在:

  • 出发点:为了更快、更稳定地呈现出首屏内容

  • 成熟度:建立在前端成熟的组件体系、模块生态之上,基于 Node.js 的同构方案成为最佳实践

  • 独立性:仍然保持着前后端分层,不与业务领域的应用服务强耦合

也就是说,如今的 SSR 是为了解决前端层的问题,结合 CSR 优化内容加载体验,是在 CSR 多年积淀之上的扩展,与现有的前端技术生态保持着良好的相容性。而当年的 SSR 更多地是为了实现功能,解决温饱问题

再看当年 SSR 面临的几个问题:

  • 性能差:每一个请求过来都要重新执行一遍数据逻辑和视图逻辑,动态生成 HTML,即便其中很大一部分内容是相同的

  • 机器成本高:Tomcat/Apache 等应用服务器的并发处理能力远不及nginx之类的 Web 服务器,因此需要部署更多的机器

  • 开发/维护难:前后端代码掺杂在一起,人员协作是个问题,并且修改维护要十分谨慎(标签结构容易被破坏)

引入 SSR 之后这些问题卷土重来,但这些年的技术发展为解决这些问题提供了新的思路:

  • 实时渲染的性能问题:动静分离的思路仍然适用,例如Static Generation

  • 服务器资源成本问题:云计算的发展有望大幅降低机器成本,例如Node FaaS

  • SSR 部分与 CSR 部分的开发/维护问题:同构为解决开发/维护难题提供了一种新思路(之前的思路是前后端分层,但这一次分不开了),维护同一份代码,跑在不同的运行环境输出不同形式的目标产物

其中,Static Generation(也叫 SSG,Static Site Generation)是指在编译时生成静态 HTML(可部署至 CDN),避免实时渲染的性能开销:

Static Generation (Recommended): The HTML is generated at build time and will be reused on each request.

但并非所有页面都能在编译时静态生成,一种可行的实践方案是将 SSR 与 Static Generation 结合起来,只对内容依赖个性化数据、或者频繁更新的页面走 SSR,其余场景都走 Static Generation

You should ask yourself: “Can I pre-render this page ahead of a user’s request?” If the answer is yes, then you should choose Static Generation.

至此,沉寂多年的 SSR 又焕发出了新的活力

参考资料

  • What is the point of SSR these days?

  • Two forms of Pre-rendering

联系我      

如果心中仍有疑问,请查看原文并留下评论噢。(特别要紧的问题,可以直接微信联系 ayqywx )

本文分享自微信公众号 - 前端向后(backward-fe)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
2年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
2年前
SSR 它到底香不香?细数 SSR 的利与弊
!(https://oscimg.oschina.net/oscnet/bb66c06f97894954beed164a1278b62f.png)关注「前端向后」微信公众号,你将收获一系列「用心原创」的高质量技术文章,主题包括但不限于前端、Node.js以及服务端技术一.SSR简介!(https
Stella981 Stella981
2年前
FaaS 给前端带来了什么?
!(https://oscimg.oschina.net/oscnet/11e21dc76b205d94eeaa59b5a9e975034b5.jpg)关注「前端向后」微信公众号,你将收获一系列「用心原创」的高质量技术文章,主题包括但不限于前端、Node.js以及服务端技术一.Serverless与FaaS
Stella981 Stella981
2年前
KaliTools说明书+BurpSuit实战指南+SQL注入知识库+国外渗透报告
!(https://oscimg.oschina.net/oscnet/d1c876a571bb41a7942dd9752f68632e.gif"15254461546.gif")0X00KaliLinux Tools中文说明书!(https://oscimg.oschina.net/oscnet/
Wesley13 Wesley13
2年前
MySQL总结(十一)子查询
!(https://oscimg.oschina.net/oscnet/upa344f41e81d3568e3310b5da00c57ced8ea.png)子查询1\.什么是子查询需求:查询开发部中有哪些员工selectfromemp;通
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
4个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这