SSR(Server-Side Rendering)并非什么新奇的概念,先后端分层以前很长的一段时间里都是以服务端渲染为主(JSP、PHP),在服务端生成完整的 HTML 页面
(摘自前端渲染模式的探索)php
也就是说,历经 SSR 到 CSR 的大变革以后,现在又从 CSR 出发去探索 SSR 的可能性……彷佛兜兜转转又回到了起点,在这之间发生了什么?现在的 SSR 与当年的 JSP、PHP 又有什么区别?css
回到论坛、博客、聊天室仍旧火热的年代,行业最佳实践是基于 JSP、PHP、ASP/ASP.NET 的动态网站html
以 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 插件)nginx
这一时期网页内容彻底由服务端渲染,客户端(浏览器)接收到的是融合了服务数据的 HTML,以及少许内联的(表单)交互逻辑和样式规则,支撑着早期大量动态网站的正是这种纯 SSR 模式git
但随着技术实践的深刻,这种模式逐渐暴露出了一些问题:github
面对这些问题,两个思路逐渐变得清晰起来,动静分离与先后端分层,前者解决性能和机器成本的问题,后者解决开发/维护的问题后端
为了充分利用 Web 服务器的静态资源处理优点,同时减轻应用服务器的负担,将资源分为两类:浏览器
两种资源分开部署,把静态资源部署至 Web 服务器或 CDN,应用服务器只部署动态资源。如此这般,静态资源响应更快了(浏览器缓存、CDN 加速),应用服务器压力更小了,皆大欢喜缓存
然而,视图逻辑却被咱们漏掉了,HTML 算做静态资源仍是动态资源?
先后端分层就是为了回答这个问题
视图逻辑的特殊之处在于:
也就是说,HTML 视图结构的建立和维护工做,能够由服务端完成,也能够在客户端完成,都依赖服务数据。但与服务端相比,客户端环境有一些优点:
所以,视图逻辑划分到了客户端(即 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 结构维护等工做,有效提升了前端的生产效率。但一些问题也随之而来:
这些问题的根源在于目前的组件渲染流程是同步阻塞的,对首屏性能提出了挑战:
CSR 虽然利用了用户设备的计算资源,但同时也受其性能、网络环境等不可控因素的制约。因而,你们又从新将目光汇集到了 SSR
SSR 模式下,首屏内容在服务端生成,客户端收到响应 HTML 后可以直接呈现内容,而无需等到组件树渲染完毕
虽然核心思想都是在服务端完成页面渲染工做,但现在的 SSR 与先前大不相同,体如今:
也就是说,现在的 SSR 是为了解决前端层的问题,结合 CSR 优化内容加载体验,是在 CSR 多年积淀之上的扩展,与现有的前端技术生态保持着良好的相容性。而当年的 SSR 更多地是为了实现功能,解决温饱问题
再看当年 SSR 面临的几个问题:
引入 SSR 以后这些问题卷土重来,但这些年的技术发展为解决这些问题提供了新的思路:
其中,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 又焕发出了新的活力
关注「前端向后」微信公众号,你将收获一系列「用心原创」的高质量技术文章,主题包括但不限于前端、Node.js以及服务端技术
本文首发于 ayqy.net ,原文连接:http://www.ayqy.net/blog/dife...