本文是 Rendering on the Web: Performance Implications of Application Architecture (Google I/O ’19)[1] 这篇谷歌工程师带来的现代应用架构体系下的优化相关演讲的总结,演讲介绍了以下优化手段:
当我们讨论「应用架构」的时候,可以理解为通过以下几个部分组合来构建网站。
Component model
组件模型。Rendering and loading
渲染和加载。Routing and transitions
路由和过渡。Data/state management
数据、状态的管理。image
在分析页面渲染性能之前,先了解一下几个比较重要的指标,方便下文理解:
FP
: First Paint,是 Paint Timing API 的一部分,是页面导航与浏览器将该网页的第一个像素渲染到屏幕上所用的中间时,渲染是任何与输入网页导航前的屏幕上的内容不同的内容。FCP
: First Contentful Paint,首次有内容的渲染是当浏览器渲染 DOM 第一块内容,第一次回馈用户页面正在载入。TTI
: Time to interactive 第一次可交互时间,此时用户可以真正的触发 DOM 元素的事件,和页面进行交互。FID
: First Input Delay 第一输入延迟测量用户首次与您的站点交互时的时间(即,当他们单击链接,点击按钮或使用自定义的 JavaScript 驱动控件时)到浏览器实际能够的时间回应这种互动。TTFB
: Time to First Byte 首字节时间,顾名思义,是指从客户端开始和服务端交互到服务端开始向客户端浏览器传输数据的时间(包括 DNS、socket 连接和请求响应时间),是能够反映服务端响应速度的重要指标。如果你还不太熟悉这些指标也没关系,接下来的内容中,会结合实际用例分析这些指标。
从服务端获取 HTML、CSS、JavaScript 都是需要成本的,以一个 CSR(客户端渲染)的网站为例,客户端渲染的网站依赖框架库(bundle)、应用程序(app)来进行初始化渲染,假设它有 1MB 的 JavaScript Bundle 代码,那么只有当这一大段的代码加载并执行完成以后,用户才能看到页面。
它的结构一般如下:
分析一下它的流程:
2 . HTML 资源中发现 script 标签加载的 bundle 再一次发起请求拉取 bundle。此时也是性能统计指标中的 FP
完成。
在这个阶段,页面基本上是没什么意义的,当然你也可以放置一些静态的骨架屏或者加载提示,来友好的提示用户。
3 . JavaScript bundle 下载并执行完毕,此时页面才真正渲染出有意义的内容。对应 FCP
完成。
当框架对 DOM 节点添加各类事件绑定后,用户才真正可以和页面交互,此时也对应 TTI
完成。
它的缺点在于,直到整个 JavaScript 依赖执行完成之前,用户都看不到什么有意义的内容。
基于以上客户端渲染的缺点以及用户对于 CSR 应用交互更加丰富的需求,于是诞生了集 SSR 和 CSR 的性能、SEO、数据获取的优点与一身的「同构渲染」,简单点说,就是:
在同构应用中,只要 HTML 页面返回,用户就可以看到丰富多彩的页面:
而 JavaScript 加载完毕后,用户就可以和这些内容进行交互(比如点击放大、跳转页面等等……)
典型的 CSR React 应用的代码是这样的:
而 SSR 的代码则需要服务端的配合,
先由服务端通过 ReactDOMServer.renderToString
在服务端把组件给序列化成 html 字符串,返回给前端:
前端通过 hydrate
注水,使得功能交互变的完整:
Vue 的 SSR 也是同理:
至此看来,难道同构应用就是完美的吗?当然不是,其实普通的同构应用只是提升了 FCP 也就是用户看到内容的速度,但是却还是要等到框架代码下载完成,hydrate
注水完毕等一系列过程执行完毕以后才能真正的可交互。
并且对于 FID
也就是 First Input Delay 第一输入延迟这个指标来说,由于 SSR 快速渲染出内容,更容易让用户误以为页面已经是可交互状态,反而会使「用户第一次点击 - 浏览器响应事件」 这个时间变得更久。
因此,同构应用很可能变成一把「双刃剑」。
下面我们来讨论一些方案。
对于不经常发生变化的内容来说,使用预渲染是一种很好的办法,它在代码构建时就通过框架能力生成好静态的 HTML 页面,而不是像同构应用那样在用户请求页面时再生成,这让它可以几乎立刻返回页面。
当然它也有很大的限制:
流式渲染可以让服务端对大块的内容分片发送,使得客户端不需要完整的接收到 HTML,而是接受到第一部分时就开始渲染,这大大提升了 TTFB
首字节时间。
在 React 中,可以通过 renderToNodeStream
来使用流式渲染:
我们知道 hydrate
的过程需要遍历整颗 React 节点树来添加事件,这在页面很大的情况下耗费的时间一定是很长的,我们能否先只对关键的部分,比如视图中可见的部分,进行「注水」,让这部分先一步可以进行交互?
想象一下它的特点:
通过一张动图来直观的感受一下普通注水(左)和渐进式注水(右)的区别:
可以看到用户第一次可以交互的时间大大的提前了。
光说不做假把式,我们看看用 React 完成这个功能的代码,首先我们需要准备一个组件 Hydrator
用来实现当某个组件进入视图范围以后再进行注水。
首先来看看应用的整体结构:
let load = () => import('./stream');
let Hydrator = ClientHydrator;
if (typeof window === 'undefined') {
Hydrator = ServerHydrator;
load = () => require('./stream');
}
export default function App() {
return (
<div id="app">
<Header />
<Intro />
<Hydrator load={load} />
</div>
);
}
根据客户端和服务端的环境区分使用不同的 Hydrator
,在服务端就直接返回普通的 html 文本:
function interopDefault(mod) {
return (mod && mod.default) || mod;
}
export function ServerHydrator({ load, ...props }) {
const Child = interopDefault(load());
return (
<section>
<Child {...props} />
</section>
);
}
而客户端,则需要实现渐进式注水的关键部分:
export class Hydrator extends React.Component {
render() {
return (
<section
ref={c => (this.root = c)}
dangerouslySetInnerHTML={{ __html: '' }}
suppressHydrationWarning
/>
);
}
}
首先 render 部分,利用 dangerouslySetInnerHTML
来使得这部分初始化为空的 html 文本,并且由于 server 端肯定还是和往常一样全量渲染内容,而客户端由于初始化需要先不做任何处理,会导致 React 内部对于服务端内容和客户端内容的「一致性检测」失败。
而利用 dangerouslySetInnerHTML
的特性,会让 React 不再进一步 hydrate
遍历 children
而是直接沿用服务端渲染返回的 HTML,保证在注水前渲染的样式也是 OK 的。
再利用 suppressHydrationWarning
取消 React 对于内容一致性检测失败的警告。
export class Hydrator extends React.Component {
componentDidMount() {
new IntersectionObserver(async ([entry], obs) => {
if (!entry.isIntersecting) return;
obs.unobserve(this.root);
const { load, ...props } = this.props;
const Child = interopDefault(await load());
ReactDOM.hydrate(<Child {...props} />, this.root);
}).observe(this.root);
}
render() {
return (
<section
ref={c => (this.root = c)}
dangerouslySetInnerHTML={{ __html: '' }}
suppressHydrationWarning
/>
);
}
}
接下来,组件在客户端初始化的时候,利用 IntersectionObserver
监控组件元素是否进入视图,一旦进入视图了,才会动态的去 import
组件,并且利用 ReactDOM.hydrate
来真正的进行注水。
此时不光注水是动态化的,包括组件代码的下载都会在组件进入视图时才发生,真正做到了「按需加载」。
动图中紫色动画出现,就说明渐进式 hydrate
完成了。
对比一下全量注水和渐进式注水的性能会发现首次可交互的时间被大大提前了:
当然,我们了解原理就发现,不光可以通过监听组件进入视图来 hydrate
,甚至可以通过 hover
、click
等时机来触发,根据业务需求的不同而灵活调整吧。
可以访问图片中的网址获取你喜欢的框架在这方面的相关文章:
本文通过总结了 Rendering on the Web: Performance Implications of Application Architecture (Google I/O ’19)[2] 这段 Google 团队的精彩演讲,来介绍了现代应用架构体系中的优化手段,包括:
在不同的业务场景下选择对应的优化手段,是一名优秀的前端工程师必备的技能,相信看完这篇文章的你一定有所收获。
参考资料
[1]Rendering on the Web: Performance Implications of Application Architecture (Google I/O ’19): https://www.youtube.com/watch?v=k-A2VfuUROg&feature=youtu.be&t=1036
[2]Rendering on the Web: Performance Implications of Application Architecture (Google I/O ’19): https://www.youtube.com/watch?v=k-A2VfuUROg&feature=youtu.be&t=1036
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/qsrwU6bPTVK6JY-czvXhgQ
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。