前言应用架构体系下优化相关的演讲总结。演讲介绍了以下优化方法:预渲染同构渲染流式渲染渐进式注水(很精彩)应用架构体系当我们讨论“应用架构”时,可以理解为通过以下几个部分组合起来构建一个网站。组件模型组件模型。渲染和加载渲染和加载。路由和转换路由和转换。数据/状态管理数据和状态管理。性能指标在分析页面渲染性能之前,我们先看看下面几个比较重要的指标,方便理解:webpage在屏幕上使用的中间,渲染与进入页面导航之前在屏幕上的渲染有什么不同。FCP:FirstContentfulPaint,首次渲染内容是浏览器渲染DOM中的第一段内容时,也是第一次向用户反馈页面正在加载。TTI:Timetointeractive第一次交互的时间,此时用户才可以真正触发DOM元素的事件,与页面进行交互。FID:首次输入延迟衡量的是从用户首次与您的站点交互(即,当他们单击链接、点击按钮或使用自定义JavaScript驱动的控件时)到浏览器实际能够响应的时间对于这种互动。TTFB:TimetoFirstByte,顾名思义,是指从客户端开始与服务器交互到服务器开始向客户端浏览器传输数据的时间(包括DNS、socket连接和请求响应时间)。反映服务器响应速度的重要指标。如果您不熟悉这些指标也没关系。在接下来的内容中,将结合实际用例对这些指标进行分析。渲染开销渲染的成本客户端渲染客户端渲染需要从服务器获取HTML、CSS和JavaScript的成本。以一个CSR(client-siderendering)网站为例,客户端渲染网站依赖框架库(bundle)、应用程序(app)进行初始渲染,假设它有1MB的JavaScriptBundle代码,那么只需当加载并执行这一大段代码时,用户就可以看到页面了。其结构大致如下:分析其流程:用户输入URL进入网站,拉取HTML资源。script标签加载的bundle在HTML资源中找到,再次发起拉取bundle的请求。此时性能统计指标中的FP就完成了。在这个阶段,页面基本上是没有意义的。当然,你也可以放置一些静态的骨架屏或者加载提示,来友好的提醒用户。下载并执行JavaScript包后,页面实际上呈现了有意义的内容。相应的FCP就完成了。当框架为DOM节点添加各种事件绑定后,用户才真正可以与页面进行交互,这也是对应TTI完成的。缺点是在整个JavaScript依赖项执行之前,用户看不到任何有意义的东西。服务端同构渲染SSRwithHydration正是基于上述客户端渲染的缺点和用户对更丰富的CSR应用交互的需求,所以结合了SSR和CSR的性能、SEO、数据获取优势的“同构渲染”出生于,简单来说就是:第一次请求,服务端利用框架提供的服务端渲染能力,直接就地请求数据,生成内容完整的html页面。用户无需等待框架的js加载即可查看。到内容。页面渲染完成后,利用框架提供的Hydration(注水)能力,丰富服务端返回的“干”HTML注册事件等。有了各种事件后,就可以像传统的CSR一样丰富多彩客户互动。在同构应用中,只要返回HTML页面,用户就可以看到丰富多彩的页面:加载JavaScript后,用户可以与内容进行交互(如点击放大、跳转到页面等)...)代码对比一个典型的CSRReact应用代码如下:而SSR的代码需要服务端的配合,服务端首先通过ReactDOMServer.renderToString将组件序列化为服务端的html字符串,并返回ittofrontend:前端通过hydrate注水,让功能交互完成:Vue的SSR同理:同构的缺陷至此,同构应用完善了吗?当然不是。普通的同构应用其实只是提高了FCP,即用户看到内容的速度,但还是要等到框架代码下载完毕,注入hydrate,完成一系列流程后才能使用真正的互动。而对于FID的指标,也就是FirstInputDelay,由于SSR快速渲染内容,更容易让用户误以为页面已经处于交互状态。Event”这个时间变得更长。因此,同构应用很可能成为一把“双刃剑”。下面我们来讨论一些选项。Pre-rendering预渲染。对于不经常变化的内容,使用预渲染是一种好办法,在构建代码时通过框架能力生成静态HTML页面,而不是像同构应用一样在用户请求页面时重新生成,这样几乎可以立即返回页面,当然也有很大的局限性:只适用于静态页面,需要预渲染的url需要提前列出StreamingrenderingStreamingstreamingrendering允许服务器将大块的内容分段发送,这样客户端就不需要接收整个HTML,但在收到第一部分时开始渲染,这大大缩短了TTFB时间的第一个字节。在React中,可以通过renderToNodeStream使用流式渲染:ProgressiveHydration我们知道水化过程需要遍历整个React节点树来添加事件,页面大的时候时间肯定很长,我们只能“water-fill”"关键部分,例如视图中可见的部分,以便可以首先与该部分进行交互?想象一下它的特点:组件级渐进式注水。服务器仍然呈现整个页面。页面可以根据优先级拆分“引导”组件。用动图直观感受一下普通注水(左)和渐进式注水(右)的区别:可以看到用户第一次交互的时间大大提前了。让我们只谈论它而不假装这样做。我们来看看使用React完成这个功能的代码。首先,我们需要准备一个组件Hydrator,实现组件进入view范围时的注水。先看应用的整体结构:letload=()=>import('./stream');letHydrator=ClientHydrator;if(typeofwindow==='undefined'){Hydrator=ServerHydrator;load=()=>require('./stream');}exportdefaultfunctionApp(){return(
