影响LCP的四个因素以下:css
浏览器获取文档的时间越长,用户看到页面的时间也会越长。较快的服务器响应时间,能够直接改善每个页面加载相关的指标,包括LCP。html
可使用 TTFB(Time to First Byte)
来测试服务器响应时间,你能够经过如下手段来优化 TTFB
这个指标。vue
你是否在服务器上运行一些昂贵的查询,占用了服务器必定的时间?或者服务器上作了一些复杂的操做,致使页面内容返回延后?分析和提高服务端代码的效率能够直接改善浏览器从服务端获取数据的时间。react
比起仅仅是提供静态页面而言,不少服务端的web框架都会动态建立页面。换句话说,比起直接返回一个现存的html文件,这些框架会执行一些逻辑来建立页面。这就取决于数据库查询时间,或者UI框架建立组件的时间(好比: React)。大部分web框架都有提供性能指导,开发者能够根据指导来提高处理速度。webpack
CDN全称Content Delivery Network,是一个分布在不一样地域的服务器集群。若是浏览器去请求数据,CDN会选择就近的一个服务器给你返回,避免请求产生太长网络路径,甚至跨国。git
若是你的html是静态的,每一次请求都不会变,能够服务端缓存下来,不用每次从新建立页面。经过缓存一份生成好的html到硬盘,服务端缓存能够有效的下降TTFB,最小化资源的使用。github
service worker能够实现这样一个功能,优先使用缓存页面,若是页面有更新,会将新页面缓存下来,下次启动则使用新缓存。web
下图是使用service worker的一个对比:数据库
发往第三方服务的请求也会影响LCP,特别是当页面关键内容依赖它们的时候。使用 rel="preconnect"
告知浏览器你的资源链接须要尽量地快。api
<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域名
在浏览器渲染任何内容以前,须要解析html,并生成dom树。html解析器会被任何样式文件 <link rel="stylesheet">
以及同步脚本 <script src="main.js">
阻塞并暂停解析。
这个不只影响FCP,也影响了LCP。延迟加载非关键的js和css能够加速页面的主内容的加载。
有如下三种方法:
移除css中没必要要的字符、注释和空格等,通常打包工具都会自带相应的插件。
使用开发者工具中的 Coverage
能够找到页面未使用的css。
优化方案:
rel="preload"
和 onload
异步加载对于初次渲染无用的css将关键路径的css直接放在 <head>
中内联引用:
这样能够避免一次服务器请求,让css阻塞时间更短。
若是你没法手动添加内联样式,可使用第三方库:
有如下三种方案:
主要有如下几种元素会影响LCP:
<img>
元素<svg>
中的 <image>
元素<video>
元素(若是定义了封面图,会影响LCP)url()
背景图的元素有如下几种方式能够保证这些文件尽快的加载:
大部分网站的最大元素都是图片,若是能加速这些图片的加载,能有效改善LCP。参考如下步骤:
有时候,在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
: 设备内存能够直接使用 workbox 的第三方库更方便的缓存资源,这是谷歌提供的一个工具库。
不少网站如今都使用客户端渲染。一些框架像 angluar, react,vue等,能够方便的建立spa的单页面应用,部分替代了服务器的功能。
若是你构建的应用是以上这种方式,须要注意若是你的bundle的js文件过大,会影响LCP。若是不作优化,用户可能长时间没法看到页面,也没法交互,直到js所有下载执行完。有如下几个优化项:
与减小js阻塞时间同样。
这样可让内容在服务端渲染好,而后返回给浏览器,以此来减小LCP。但这种方式存在一些隐患:
TTI(Time to Interactive)
预渲染是一个独立的技术,主要是为了解决服务端渲染的代码复杂度。经过启动一个无头浏览器,在构建的时候就将每一个路由页面渲染好并建立对应的html文件,这些文件也能够和对应的js bundles一块儿使用。
预渲染的方式,不能改善TTI,但对TTFB会比服务端渲染要更好些。
开发者工具已经能够针对实验数据进行这些指标的测试:
本文只是对LCP的优化作了简单而又比较全的介绍,后面的文章会针对个别项进行单独的介绍。