1 / 21
文档名称:

【后端教程】深入浅出动态化SSR服务(一):开发工具篇.pdf

格式:pdf   大小:2,572KB   页数:21页
下载后只包含 1 个 PDF 格式的文档,没有任何的图纸或源代码,查看文件列表

如果您已付费下载过本站文档,您可以点这里二次下载

分享

预览

【后端教程】深入浅出动态化SSR服务(一):开发工具篇.pdf

上传人:小屁孩 2024/3/13 文件大小:2.51 MB

下载得到文件列表

【后端教程】深入浅出动态化SSR服务(一):开发工具篇.pdf

相关文档

文档介绍

文档介绍:该【【后端教程】深入浅出动态化SSR服务(一):开发工具篇 】是由【小屁孩】上传分享,文档一共【21】页,该文档可以免费在线阅读,需要了解更多关于【【后端教程】深入浅出动态化SSR服务(一):开发工具篇 】的内容,可以使用淘豆网的站内搜索功能,选择自己适合的文档,以下文字是截取该文章内的部分文字,如需要获得完整电子版,请下载此文档到您的设备,方便您编辑和打印。:..海纳百川,有容乃大;壁立千仞,无欲则刚。——林则徐【后端教程】深?浅出动态化SSR服务(?):开发?具篇简述在前端还未系统化之时的?耕?种时代,已经有?常多的?成页?的?具,其可视化的?式极?的赋能了?技术?员,加快了业务的迭代速度。如今,随着前端技术的发展和复杂化,我们看到越来越多以组件为基础的页?级可视化?成?具已经出现在了各?领域。依靠Vue/React等UI组件框架和逐渐易?化的Webpack等编译?具的出现,编写?套符合??业务需求的前端可视化页??成?具并不复杂。但?部分的页?可视化系统?都以完全纯前端思维来打造,对其论述也仅仅是?体的做法和原理剖析,并没有以前端?程化的?度来阐述其中的困难与细节。在《深?浅出动态化SSR服务》系列?章中,我们将以较为深?的前端?程化?度来讲述如何打造?款动态化且?持SSR的页?可视化系统。希望?家能以此为参考,更深?的思考前端?程化的实践,并能在业务当中有相关的提升。本系列?章分为三个部分:?具篇:当前篇我们会较为深?和系统地讲述sis的编写过程,其中涉及到技术选型考量,编译前端相关的知识。同时我们会适当讲述不直接采?VueCLI等?具链的原因及其相关的不?点,更多的内容在《SSR服务篇》中我们还会通过测试结果进?更深?分析和讲述。:在这?篇中我们会探讨当前SSR服务性能和稳定性相关的问题,在压?测试?具以及Node相关Profile帮助下优化我们的SSR服务,达到单机服务?稳定性、?性能、动态化的要求。:在这?篇中我们会讲述此页?可视化系统的架构层?的?些思考和实践,从更全局和整体的?度来探讨如何保证系统的?稳定和?性能化要求。在此,我?常感谢百度的FEX团队产出的,其中?常多关于前端?程化的思考都被融?到了sis以及sis-ssr中。同时我也?常感谢与我亦师亦友的从全民直播?今对我整体技术?向的指引和多维度?法论的培养。项?背景如今市?上的页?可视化系统主要以纯前端技术为主,并没有对结果页?进?SSR同构。究其原因可以总结为:纯前端技术的整体系统实现较为容易,对于其产出结果只需要由CDN来进?加速,即可完成抵抗单页??流量的需求。我们可以看到?前市?上类似的运营/营销产品可视化系统?体都是如此。但是SSR同构服务的引?是有其积极意义的,其核?的两点在于:.?屏渲染的加速对于很多站点??,其在SEO上的需求与?型?商的系统有很?的不同:有?常多站点的产品页?仍然需要Google等搜索引擎进?收录。这点我们可以从开放的?件看到:?复制代码User-agent:GooglebotCrawl-delay:1Allow:/vp/products/Allow:/vm/products/Disallow:/*.css$Disallow:/*.js${1}在这?可能有部分读者会问:“Google不是可以对SPA页?进?收录么?”,其实不然,我们在Google的相关解释中可以找到这样?句话:Note:thatasofnow,,当我们的页?如果存在异步请求然后再进?页?渲染的话,Google仍然是?法进?有效收录的。那么基于Headless的预渲染服务(Prerendering)?会如何呢?由于Headless需要启动完整的浏览器核?进?渲染,因此对于服务端性能是极?的消耗(尽管可以创造Headless的对象池进?重?,但渲染时性能仍然有较?的服务器端消耗)。针对较少的营销页?还可以,但是在需要整站SSR这个场景下,这并不能发挥很好的作?。其次,特别是对于电商类产品??,根据Amazon的页?加载延迟与收?关系的实践数据(每增加100ms?站加载延迟将导致收?下降1%),我们需要?常强?的?持进??屏渲染的加速,降低内容到达时间(time-to-content),保证更好的?户体验和更?的?户留存。谋事在人,成事在天!——《增广贤文》:..志不强者智不达,言不信者行不果。——墨翟与此同时,我们也应该?持?常灵活的页?可视化搭建平台来应付?量的?常化运营需求,并且也应该具有开放的能?和通?性,能很好的?撑公司其他团队的业务。在此背景下,我们稍加总结就能清晰的得到这套系统需要达成的?标,即:组件化及可视化能够进?SSR服务的渲染动态化,测试及发布不涉及核?的SSR渲染服务?够灵活,其他团队能很好的接?及使?能够保障服务安全,并做到业务隔离技术选型对于SSR服务??,存在两种思路体系可以选择::性能。但是对于现代的前端开发来说,难以地很好的利?NPM?态,对开发不是很友好。?以Vue/React等现代UI框架的VirtualDOM的思路,能够很好的利??态,但是缺点也是相当明显的,即:由于编译阶段会产??常多的VirtualDOM对象,因此在渲染性能和内存占?相?HandleBars等字符串渲染引擎的思路??并不占优。当然,在我们技术选型时,我们?般?先以开发友好为准则进?,毕竟效率即是?切。因此Vue/React的?案是我们理所当然会去选择的。但是,Vue/React等现代UI框架的所有出发点总归是以纯前端为主,后端渲染为辅的思路在做?持,因此其所包含的?具链(VueCLI等)?持并不能很好的满?我们??的需求,举个例?:团队A和团队B互不?涉的分别基于此系统开发两个项?C1与C2,此时,C1和C2项?都引?相同版本的诸如Vue、Lodash等公共依赖。现将C1与C2进?相关的同构打包,在不做编译?具调整的情况下,会产出D1和D1两个发布包。我们可以看到,在这个例?之下,D1和D2必定会包含相同的公共依赖。这对于开放且动态化的SSR服务??是极度不友好的,因为代码包体越?,?关代码越多,那么服务本地初始化的IO、CPU和内存占?成本势必会随之增加,这点我们在之后的《SSR服务篇》可以更深?地分析得到。其次,对于浏览器端的??,因为静态资源的加载时间被增加了,也会增加更多的?户操作响应时间。考虑这样?个场景:D1发布结果包含了100个组件,但是对于某??成页???,只需要对2个组件进?重复渲染。在这个场景中,不管是服务端还是浏览器端,我们都需要浪费?量的IO、CPU和内存在剩下的98个组件代码之中。当然,在这些场景??,类似Webpack之类的编译?具仍然可以通过开发者标注DynamicLoad的?式来进?按需加载,但这也造成了?常?的开发负担,我们希望整个过程是编译?具?动完成的。因此,直接使?Vue/React等现代UI框架的现有?具链是完全?法满?我们的系统要求的。我们需要对现有?具链进?替代或改进。总??之,最后我们确定的技术选型为:VueElementUI(可视化后台所需)改进的编译?具(sis)需要注意的是,整个系统设计上实际与UI库/框架是?关的,但我建议我们仍然需要在开发及?产期间固定你的技术选型,以此来避免因为?技术选型造成的项?不可维护及混乱,可以把这个看做是?个内部强制的约定。当然接下来的内容我们都会以Vue来进?讨论,如果有通?渲染服务的需求,可以在此基础上进?参考。同时对于页?可视化系统来说,开发应该只是关注于组件的开发,?较少考虑外部系统的逻辑,因此我们?般采?如下的项??录结构:忍一句,息一怒,饶一着,退一步。——《增广贤文》:..丹青不知老将至,贫贱于我如浮云。——杜甫在这个基础上,ponents?录,这是我们编译的?标?录。?其他?件主要是?作本地开发时所?,在最终的结果中并不引?。资源的加载分析在上?我们已经分析过,直接使?VueCLI等?具链并不能很好的满?当前系统的需求,我们需要更灵活的按需加载的编译?持,并且希望这个?持是不需要开发?涉的。反观现有的编译?具??,其更多是在部署之前进?相关的代码静态分析并整体打包。如果我们需要更灵活的按需加载,那么唯?的?式是在运?时能够获得当前页?所需要的组件代码然后整合后运?,如图:从图中的逻辑我们可以看到,当页?ponentA组件时,ponentA及其依赖的加载地址从?返回,然后由浏览器动态的完成整个加载,即可达成我们的要求。ponentB的代码,从?减少了加载和代码运?的耗时。那么我们如何拿到这个依赖关系呢?实际上对于现代的编译?具??,在进?编译时期就已经产出了对应的依赖关系了。我们只需要对其进??些加?即可满?我们的需求。在编写sis的过程中,我会选择了来充当这???,其原因在于:百学须先立志。——朱熹:..一寸光阴一寸金,寸金难买寸光阴。——《增广贤文》Parcel遵循0配置的原则,开箱即?,使?简单Parcel有?常灵活的编译相关的接?,很容易进?编译?具的?次开发Parcel默认编译即采?多核编译及产出编译Cache,编译速度极快Parcel相较于Webpack??,在轻、重度使?上都会更胜?筹。其中最主要的原因是我?较喜欢的Parcel的代码即配置?不是Webpack的配置优先的原则。当然你也可以使?Webpack拿到相关的信息进??次加?,其做法并?太?差异。我们拿?,代码如下:使?Parcel拿到相关的资源依赖关系?分简单,其代码如下:一寸光阴一寸金,寸金难买寸光阴。——《增广贤文》:..忍一句,息一怒,饶一着,退一步。——《增广贤文》其中assets是?个Bundler对象,其结构经过必要简化仅保留我们关?的数据后,?致如下(如需要更详细和准确的结构信息,请参考Parcel?档):老当益壮,宁移白首之心;穷且益坚,不坠青云之志。——唐·王勃:..良辰美景奈何天,便赏心乐事谁家院。则为你如花美眷,似水流年。——《汤显祖》现在我们已经拿到了对应的依赖关系,接下来需要的?作就是将此树形结构的依赖转换成我们所期望的样?:丹青不知老将至,贫贱于我如浮云。——杜甫:..先天下之忧而忧,后天下之乐而乐。——范仲淹实际上,对于sis??,其处理过程包含5个阶段,其分别是:百学须先立志。——朱熹:..古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。——:将Parcel的依赖数据JSON化,?:分析对应的依赖结果,展平整个依赖数据,并且更改对应?::对依赖结果进?合并分析优化,:输出对应的代码及依赖关系JSON在这?我们仅介绍5个阶段中的4个,?不对耦合具体业务需求的checker进?介绍。同时我们也主要以介绍思路为主,?简化了?部分的实现,实际上sis处理了?常多繁琐的CornerCase来保证编译的正确性。简化资源结构?先,为了调试的简便性,我们先将Parcel嵌套的Bundler对象简化为JSON数据,其代码如下:人之为学,不日进则日退,独学无友,则孤陋而难成;久处一方,则****染而不自觉。——《顾炎武》:..先天下之忧而忧,后天下之乐而乐。——范仲淹经过此函数的处理,我们将Parcel的Bundler对象嵌套简化成了JSON数据,其结果为:需要注意的是,这?步并不是必须的,如果为了编译时的性能,我们可以直接针对嵌套的Bundler对象进?后续处理。志不强者智不达,言不信者行不果。——墨翟:..丹青不知老将至,贫贱于我如浮云。——杜甫展平资源结构为什么需要将树形结构进?展平?其中的原因很简单的,就是为了后续更容易分析。在之后的optimize阶段我们需要?量的在依赖对象中进?跳转和改写,对树形结构展平,性能会更好,同时更容易达成这??标。将树形结构进?展平的代码很容易,代码如下:以铜为镜,可以正衣冠;以古为镜,可以知兴替;以人为镜,可以明得失。——《旧唐书·魏征列传》:..丹青不知老将至,贫贱于我如浮云。——杜甫此处getVersion函数作?是获取到当前依赖的版本号,其根据??件中的version字段获得。?md5函数是将对应的generated字段进?,然后返回?个7位长度的字符串。通过此函数我们可以将对应的树形结构成功进?展平,其结果如下:百川东到海,何时复西归?少壮不尽力,老大徒伤悲。——汉乐府《长歌行》:..吾日三省乎吾身。为人谋而不忠乎?与朋友交而不信乎?传不****乎?——《论语》海纳百川,有容乃大;壁立千仞,无欲则刚。——林则徐:..大丈夫处世,不能立功建业,几与草木同腐乎?——《罗贯中》?切准备就绪,我们可以进?sis最有乐趣的optimize阶段了!依赖的合并优化回顾我们上?的讲述,为了保证可视化系统按需加载,我们依靠Parcel输出了依赖的JSON。从?例上我们可以看到,,那么我们只需要扫描整个对象,、lodash、Buffer等代码的访问路径就?了。这看起来相当完美,但在实际应?中,这仍然远远不够。我们知道对于浏览器来说,其静态资源的并发请求是存在限制的,在?常开发中我们并不会有这么简单的依赖关系。假如我们将ElementUI引?到A组件中然后编译,我们会发现,整个JSON?件有230多项依赖信息,即使我们在A组件中仅仅添加??个ElementUI的Button组件,其所需要动态加载的?件数量就?达80多个!这显然不是我们想要的结果。针对这个问题我们会很?然地想到合并,现在的问题便会转化为:“我们如何知道哪些模块需要被合并呢?”。假设我们有?个较为复杂的依赖关系,如图所?:其中包含循环引?(G-F-E-G)以及?引?(E-E),那么我们怎么确定该合并哪些模块呢?当然,可能有读者会说:“你这个图错了,实际开发中不可能存在循环引?和?引?的!”。但事实上这在静态分析中是经常会发?的事情。例如,当我们针对上?的简单?例使?Parcel编译后我们会发现,Buffer模块竟然?引?了??!究其原因是因为Parcel为了统?Browser和Node端的代码?添加了polyfill代码。在编译时Parcel发现lodash引?的Buffer库中有这么?代码时:就帮我们引?了Buffer的polyfill模块,从?造成了?引?。??于循环引?,当我们编写了类似的如下代码:百川东到海,何时复西归?少壮不尽力,老大徒伤悲。——汉乐府《长歌行》:..天行健,君子以自强不息。地势坤,君子以厚德载物。——《易经》不难发现,此中存在循环依赖为:C-B-A-C,但当我们使?Node执?此代码后会发现其能很正确的进?执?并输出:勿以恶小而为之,勿以善小而不为。——刘备:..万两黄金容易得,知心一个也难求。——《曹雪芹》从静态分析的?度来说,类似的代码在我们的依赖分析中很容易就会形成?引?与循环引?。针对以上问题,我们?先需要破坏依赖表中的?引?和循环引?(?于为什么这样做能够仍然保证正确的运?,就留给读者??思考了)。其代码如下:穷则独善其身,达则兼善天下。——《孟子》:..古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。——苏轼执?后,我们就进?步得到了如下的依赖关系:根据上图稍加分析我们可以知道,在这?的依赖关系中,F节点实际上可以与G节点合并?成G+F节点,完成?次合并。其合并的条件为F的?度为1,更简单的说法是,F的?亲节点唯?。因此我们可以得到第?次合并的结果:谋事在人,成事在天!——《增广贤文》:..我尽一杯,与君发三愿:一愿世清平,二愿身强健,三愿临老头,数与君相见。——《白居易》按照此规律我们依次进?合并,其过程如下:+F节点与C节点合并(G+F节点?度为1)+F+C节点与E节点合并(E节点?度为1)+F+C+D节点与E节点合并,合并结束。通过这个算法,我们可以将引?数为1的模块尽可能合并,以此减少静态资源加载所需的请求数。最终我们的JSON将会形成如下的形式:老当益壮,宁移白首之心;穷且益坚,不坠青云之志。——唐·王勃:..天行健,君子以自强不息。地势坤,君子以厚德载物。——《易经》人不知而不愠,不亦君子乎?——《论语》:..忍一句,息一怒,饶一着,退一步。——《增广贤文》其中我们对于每个合并的单节点新增了pkg字段,同时也形成了?个__pkg0节点记录了所有引?的模块。我们再次对相同的ElementUI项?进?测试,发现其依赖项从230项减少到了51项,?部分模块都被正确的合并了。但与此同时我们也发现还有少部分模块因为被多个组件公?,从?被独?划分出来。当然此类?件也有很多显著的特点,例如:?件体积不?(?部分集中在1K以下),并且?部分都是?常基础的功能代码实现(如merge/filter/map等逻辑处理)。针对这些??件,我们仍然可以在分析过程中再次进?合并。但在实际的sis实现中并没有这么做,?bo服务帮助我们完成了这部分功能,相关内容我们在《架构篇》会讲述。给资源加上模块系统Parcel提供给我们的数据中,其generated包含了已经过babel等编译过的具体代码,其结构?致如下:针对这些转移的代码,我们需要给其加上AMD的相关模块外层代码,例如:同时,我们可以??编写?个40?的AMD实现来完成模块的定义执?(当然你也可以使?开源的实现),其?体实现如下:人人好公,则天下太平;人人营私,则天下大乱。——刘鹗:..人之为学,不日进则日退,独学无友,则孤陋而难成;久处一方,则****染而不自觉。——《顾炎武》?此,所有模块内容的分析和改写?作就已完成,我们只需要根据JSON依赖表将各项代码输出到?件就完成了整个开发?具的?作。与此同时,JSON依赖表也应被同时输出,供我们之后的服务端和浏览器端进?运?时分析并提供加载依据。更多功能sis作为?个开发?具,除了进?最终编译功能外,还应该增加?些?便开发的功能,如图:百学须先立志。——朱熹:..谋事在人,成事在天!——《增广贤文》这些功能除了加快初始化项?的创建外,还沉淀了?些项?的最佳实践以便帮助新?能够更快的融?到项?开发之中。总结与期待在本篇中,我们详细讲述了项?的背景及对应的?标,并分析了如何依靠依赖表的?式优化对应的加载性能以及达到SSR?标中的动态化。当然整个过程我们主要是以讲述思想为主,抛开了?常多繁琐复杂的相关?作细节。服务推荐丈夫志四方,有事先悬弧,焉能钧三江,终年守菰蒲。——《顾炎武》