影响 LCP 的四个因素如下:
- 较慢的服务器响应工夫
- 渲染阻塞的 js 和 css
- 较慢的资源加载工夫
- 客户端渲染
较慢的服务器响应工夫
浏览器获取文档的工夫越长,用户看到页面的工夫也会越长。较快的服务器响应工夫,能够间接改善每一个页面加载相干的指标,包含 LCP。
能够应用 TTFB(Time to First Byte)
来测试服务器响应工夫,你能够通过以下伎俩来优化 TTFB
这个指标。
- 优化服务器
- 应用 CDN
- 缓存资源
- html 页面优先应用缓存
- 提前建设第三方连贯
优化服务器
你是否在服务器上运行一些低廉的查问,占用了服务器肯定的工夫?或者服务器上做了一些简单的操作,导致页面内容返回延后?剖析和晋升服务端代码的效率能够间接改善浏览器从服务端获取数据的工夫。
比起仅仅是提供动态页面而言,很多服务端的 web 框架都会动态创建页面。换句话说,比起间接返回一个现存的 html 文件,这些框架会执行一些逻辑来创立页面。这就取决于数据库查问工夫,或者 UI 框架创立组件的工夫(比方: React)。大部分 web 框架都有提供性能领导,开发者能够依据领导来晋升处理速度。
应用 CDN
CDN 全称 Content Delivery Network,是一个散布在不同地区的服务器集群。如果浏览器去申请数据,CDN 会抉择就近的一个服务器给你返回,防止申请产生太长网络门路,甚至跨国。
缓存资源
如果你的 html 是动态的,每一次申请都不会变,能够服务端缓存下来,不必每次从新创立页面。通过缓存一份生成好的 html 到硬盘,服务端缓存能够无效的升高 TTFB,最小化资源的应用。
- 配置反向代理,在应用服务器之前配置一个缓存服务器,专门提供缓存内容。
- 配置和治理云服务商提供的缓存个性
- 应用 CDN 来提供内容缓存,这样用户能够更近的获取到内容
html 页面优先应用缓存
service worker 能够实现这样一个性能,优先应用缓存页面,如果页面有更新,会将新页面缓存下来,下次启动则应用新缓存。
下图是应用 service worker 的一个比照:
提前建设第三方连贯
发往第三方服务的申请也会影响 LCP,特地是当页面要害内容依赖它们的时候。应用 rel="preconnect"
告知浏览器你的资源连贯须要尽可能地快。
<link rel="preconnect" href="https://example.com">
也能够应用 dns-prefetch
让 dns 解析更快。
<link rel="dns-prefetch" href="https://example.com">
思考到浏览器兼容性,dns-prefetch
能够作为 preconnect
的一个 fallback。
<head>
<link rel="preconnect" href="https://example.com">
<link rel="dns-prefetch" href="https://example.com">
</head>
preconnect 个别只配置一个,dns-prefetch 能够配置多个,所以个别把最要害的资源配置成 preconnect,比方 js 或者 css 所在的 cdn 域名
渲染阻塞的 js 和 css
在浏览器渲染任何内容之前,须要解析 html,并生成 dom 树。html 解析器会被任何款式文件 <link rel="stylesheet">
以及同步脚本 <script src="main.js">
阻塞并暂停解析。
这个不仅影响 FCP,也影响了 LCP。提早加载非关键的 js 和 css 能够减速页面的主内容的加载。
缩小 css 阻塞工夫
有以下三种办法:
- 最小化 css
- 延后加载非关键的 css
- 内联要害 css
最小化 css
移除 css 中不必要的字符、正文和空格等,个别打包工具都会自带相应的插件。
延后加载非关键的 css
应用开发者工具中的 Coverage
能够找到页面未应用的 css。
优化计划:
- 移除无用的 css,并将它们移到须要的页面
- 用
rel="preload"
和onload
异步加载对于首次渲染无用的 css
内联要害 css
将要害门路的 css 间接放在 <head>
中内联援用:
这样能够防止一次服务器申请,让 css 阻塞工夫更短。
如果你无奈手动增加内联款式,能够应用第三方库:
- Critical, CriticalCSS, 和 Penthouse 能够提取并内联 css。
- Critters 是一个 webpack 插件,能够帮你内联要害 css,其余 css 则懒加载。
缩小 js 阻塞工夫
有以下三种计划:
- 最小化并压缩 js 文件
- 延后未应用的 js
- 尽量减少未应用的 polyfills
缩小资源加载工夫
次要有以下几种元素会影响 LCP:
<img>
元素<svg>
中的<image>
元素<video>
元素(如果定义了封面图,会影响 LCP)- 带
url()
背景图的元素 - 块级元素带有文本节点或者内联文本子元素
有以下几种形式能够保障这些文件尽快的加载:
- 优化和压缩图片
- 预加载重要资源
- 压缩文本文件
- 自适应服务,如:依据网络条件加载不同资源(例如:4g、3g、2g)
- 用 service worker 缓存资源
优化和压缩图片
大部分网站的最大元素都是图片,如果能减速这些图片的加载,能无效改善 LCP。参考以下步骤:
- 思考是否必须应用图片,如果不是必须,移除
- 压缩图片(用 imagemin)
- 转换成新格局(webp)
- 应用响应式图片
- 应用图片 CDN
预加载重要资源
有时候,在 css 或者 js 中申明或者应用的一个重要资源可能比你预期的要晚获取,比方字体文件。
如果你明确的晓得某个资源须要进步优先级,能够应用 <link rel="preload">
。
<link rel="preload" as="script" href="script.js">
<link rel="preload" as="style" href="style.css">
<link rel="preload" as="image" href="img.png">
<link rel="preload" as="video" href="vid.webm" type="video/webm">
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
Chrome73 版本之后,预加载同时反对响应式:
<link
rel="preload"
as="image"
href="wolf.jpg"
imagesrcset="wolf_400px.jpg 400w, wolf_800px.jpg 800w, wolf_1600px.jpg 1600w"
imagesizes="50vw"
>
压缩文本文件
应用 Gzip
或者 Brotli
,gzip 反对度较好,brotli 的压缩比更高,但只有更新的浏览器才反对。
自适应服务
当加载页面的主内容的时候,能够依据用户设施和网络条件来加载不同的资源。要实现这些,能够应用 Network Information, Device Memory, 和 HardwareConcurrency 的 api。
if (navigator.connection && navigator.connection.effectiveType) {if (navigator.connection.effectiveType === '4g') {// Load video} else {// Load image}
}
以下是一些有用的属性:
navigator.connection.effectiveType
: 网络类型,如 4G 等navigator.connection.saveData
: data-saver 是否开启navigator.hardwareConcurrency
: cpu 核数navigator.deviceMemory
: 设施内存
用 service worker 缓存资源
能够间接应用 workbox 的第三方库更不便的缓存资源,这是谷歌提供的一个工具库。
客户端渲染
很多网站当初都应用客户端渲染。一些框架像 angluar,react,vue 等,能够不便的创立 spa 的单页面利用,局部代替了服务器的性能。
如果你构建的利用是以上这种形式,须要留神如果你的 bundle 的 js 文件过大,会影响 LCP。如果不做优化,用户可能长时间无奈看到页面,也无奈交互,直到 js 全副下载执行完。有以下几个优化项:
- 缩小要害 js 的大小
- 应用服务端渲染
- 应用预渲染
缩小要害 js 的大小
与缩小 js 阻塞工夫一样。
应用服务端渲染
这样能够让内容在服务端渲染好,而后返回给浏览器,以此来缩小 LCP。但这种形式存在一些隐患:
- 代码复杂性太高,服务端和客户端用的是同一套 js
- 服务端去执行 js,并渲染 html,会减少 TTFB,相比于仅仅提供动态 html 而言
- 服务端渲染的页面看上去仿佛能够交互,但实际上还是要期待 js 执行实现能力交互。简略地说,会减少
TTI(Time to Interactive)
应用预渲染
预渲染是一个独立的技术,次要是为了解决服务端渲染的代码复杂度。通过启动一个无头浏览器,在构建的时候就将每个路由页面渲染好并创立对应的 html 文件,这些文件也能够和对应的 js bundles 一起应用。
预渲染的形式,不能改善 TTI,但对 TTFB 会比服务端渲染要更好些。
开发者工具
开发者工具曾经能够针对试验数据进行这些指标的测试:
- lighthouse
- performance 中的 timeline
总结
本文只是对 LCP 的优化做了简略而又比拟全的介绍,前面的文章会针对个别项进行独自的介绍。
参考
https://web.dev/optimize-lcp/