服务端渲染不是服务端完全渲染,其本身的目的也不是为了让服务器完全承担渲染任务,它也需要生成和打包,也需要热更新支持,并不是pug那种形式的
渊源
刚开始接触Node.js和网页的时候,接手了一个Node.js的项目,一个完整的信息管理系统,从数据库到请求路由再到网页,都是基于服务器框架express,页面是用pug(当时叫jade)写的,express内部支持pug模板,可以直接渲染成html,其本身就是采用缩进区分层级的html,还没有MVC和MVVM的概念,常用的数据驱动视图在那项目中根本不存在,每个页面的导航栏菜单栏都是复制粘贴的。
这种有别于提供静态网页文件夹让人访问的方式就是最早认识到的服务端渲染,服务器做了点操作将某种模板渲染成html去响应请求。
后来接触到了Vue,深刻体会到了前后端完全分离带来的开发上的便利,利用它也完成了各种大大小小的项目,但是这其中一直有一些别扭却又说不出来。首先是构建方式,使用Vue的CLI工具写好网页后,可以通过打包命令生成一系列静态文件,再去搭一个静态服务器,只要不考虑HTTP请求,这个网站就算搭好了,这在当时的我看来是非常low的一种方式,毕竟之前的那个Node.js项目的开发者后来去了阿里,是个技术大牛,带着这种尊敬我一直认为服务端完全渲染才是一种最优的使用手法,这也是我不断尝试服务端渲染的动力源泉之一;再一个别扭的地方就在于访问速度,当辛辛苦苦写好网站部署上去后,兴致勃勃去其他人电脑上试着访问时,总是需要等上个一两秒甚至更长,除非有缓存,要不然初次访问所花的时间有时候真的长得离谱,其实这也是前后端完全分离导致的后果之一,一方面需要传输的资源太多,另一方面浏览器自身的渲染也需要花点时间,不过由于做的项目基本上都是在局域网内小打小闹,要么就是访问的人数不够多也没人觉得这问题忍不了,本着《能用就行》的上级原则,也没在这方面追究太多。
不过人总有闲下来的时候,但闲时又爱给自己找事做,就瞎看,之前曾试着参透vue-ssr,结果卡在了webpack上面,还玩了vuepress,后来也没留下什么有价值的东西;最近把一直想学的typescript学了个大概,用强类型重构了一个js服务端代码;也看了下vite,希望哪一天能拿来和webpack做个对比;看来看去又看到了vue-ssr,这回倒是基本上看懂了,可是也颠覆了我以往的认知,才算是对这么一个过程有了个较为完整的认知。
服务端渲染的目的
矛盾对立统一,这是服务端渲染这个问题成为问题的根本原因。刀耕火种的年代,超文本标记语言(html)也就是静态网页就是一张纸,谁要给谁看一下就够了;这张纸越来越大,大家想看的内容越来越多,因此构建这张纸的内容慢慢由服务器自动完成,aspx、jsp、php……这类动态网页就是此时的产物;接着随着浏览器能力越来越强,JavaScript大放异彩,能够独立完成动态内容的渲染,并且速度也不慢,效果还很好,所以人们就开始将服务器的渲染任务分离出来,交给浏览器来做,自己告诉它如何渲染就行了,此时的网页又变回了html,服务器的压力也小了不少;但是问题又出现了,所有的内容都是来到浏览器才开始渲染,那搜索引擎要怎么办啊,它的爬虫走到一个地方发现这里不再门户大开,里面住几口人需要往里走个几十米才知道,那还了得,自己不得累死,所以干脆不走,你不欢迎我我就不来了,爬虫不来可把主人着急坏了,自己辛辛苦苦部署的网站要是没人知道那可怎么办,生意就做不了咯,这就是纯html渲染的动态网页面临的问题,一方面要走好几十米,也就是访问稍微慢点,另一方面就是人家搜索引擎都不爱理你了。于是乎能不能想一种办法,既能保证自己的网页足够酷炫内容足够动态丰富,又能保证人家访问快搜索引擎也能直达,哦对,最好是服务器压力也要小一点——这就是服务端渲染现阶段在做的事。
结论就是,现在的服务端渲染并不是完完全全地渲染出一个静态网页然后再发给浏览器,而是把渲染好一部分的网页内容作为静态网页发给浏览器,同时发送客户端渲染的要求,浏览器收到静态内容和渲染要求后,再进行二次的渲染。这样有啥好处呢?首先搜索引擎一下子就能看到自己想看的东西,登记好门牌号就走了,你家里母猪一胎生几个和我没关系;再者访客一下子就看到你们家大门酷炫,你主人慢慢出来我边欣赏沿途风景,也不失为一件美事,这难得两全其美的事情,现在的服务端渲染做到了。
故事的背后是我本人认知的颠覆,不能算是破灭,勉强说是升华。一直以来认为的服务端大包特包的想法本以为是新颖的,却不想是更过时的,服务端渲染也不是那种直接把一整个Vue CLI工程变成一个静态文件发给浏览器的过程。
原本以为有了服务端渲染我就可以只写一个服务器代码,完了.vue文件只是其中的一部分,但后来仔细看了文档才发现,即便是服务端渲染,要用webpack还是跑不掉打包的过程,如上图所示,无非就是打包成客户端代码和服务端代码罢了,那既然如此,前后端完全分离还是《能用就行》。
留个教程,万一以后用到了或许能帮点。
还有个概念区别于服务端渲染(Server Side Rendering),就是预渲染(Prerendering),预渲染是在构建服务端的时候就把要呈现给用户的内容先渲染好了,一些首页导航页之类的,用户请求的时候直接发静态html就够了,服务端渲染是用户请求哪个页面的时候我还需要小小地渲染一次再发给用户,二者有所联系又有所区别:
预渲染:用户请求 => 静态页面(预渲染后的) => 用户
服务端渲染:用户请求 => 渲染 => 静态页面 => 用户