loading-sequence

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Optimize your loading sequence

优化资源加载顺序

In every successful web page load, some critical components and resources become available at just the right time to give you a smooth loading experience. This ensures users perceive the performance of the application to be excellent. This excellent user experience should generally also translate to passing the Core Web Vitals.
在每个成功的网页加载过程中,一些关键组件和资源会在恰到好处的时机加载完成,为用户带来流畅的加载体验。这能确保用户感知到应用的卓越性能,而这种出色的用户体验通常也意味着通过Core Web Vitals指标检测。

When to Use

适用场景

  • Use this when optimizing page load performance for Core Web Vitals
  • This is helpful when you need to coordinate the loading of 1P JS, 3P JS, CSS, fonts, and images
  • Use this when third-party scripts are impacting your loading performance
  • 当你需要针对Core Web Vitals优化页面加载性能时使用
  • 当你需要协调第一方(1P)JS、第三方(3P)JS、CSS、字体和图片的加载时,该方法会很有帮助
  • 当第三方脚本影响你的加载性能时使用

Instructions

操作指南

  • Inline critical CSS and font CSS; use preconnect for external fonts
  • Sequence resources so FCP fires before LCP, and LCP fires before FID
  • Start fetching first-party JS before ATF images on the network
  • Use
    async
    or
    defer
    attributes for non-critical scripts
  • Lazy-load below-the-fold images and non-essential third-party resources
  • 内联关键CSS和字体CSS;对外部字体使用preconnect
  • 对资源进行排序,确保FCP在LCP之前触发,LCP在FID之前触发
  • 在网络上优先获取第一方JS,而非首屏(ATF)图片
  • 为非关键脚本使用
    async
    defer
    属性
  • 懒加载首屏以下的图片和非必要的第三方资源

Details

详细说明

Key metrics such as First Content Paint, Largest Contentful Paint, First Input Delay, etc used to measure performance are directly dependent on the loading sequence of critical resources. For example, the page cannot have its LCP if a critical resource like the hero image is not loaded. This article talks about the relationship between the loading sequence of resources and web vitals. Our objective is to provide clear guidance on how to optimize the loading sequence for better web vitals.
Before we establish an ideal loading sequence, let us first try to understand why it is so difficult to get the loading sequence right.
用于衡量性能的关键指标,如First Content Paint(FCP)Largest Contentful Paint(LCP)First Input Delay(FID)等,直接取决于关键资源的加载顺序。例如,如果像首屏主图这样的关键资源未加载,页面就无法触发LCP。本文探讨了资源加载顺序与Web Vitals之间的关系,旨在提供清晰的指导,帮助你优化加载顺序以获得更好的Web Vitals指标。
在确立理想的加载顺序之前,我们先来了解为什么正确的加载顺序如此难以实现。

Why is optimal loading difficult to achieve?

为何难以实现最优加载?

We have had the unique opportunity to work on performance analysis for many of our partner's websites. We identified multiple similar issues that plagued the efficient loading of pages across different partner sites.
There is often a critical gap between developers' expectations and how the browser prioritizes resources on the page. This often results in sub-optimal performance scores. We analyzed further to discover what caused this gap and the following points summarise the essence of our analysis.
Sub-optimal sequencing
Web Vitals optimization requires not only a good understanding of what each metrics stands for but also the order in which they occur and how they relate to different critical resources. FCP occurs before LCP which occurs before FID. As such, resources required for achieving FCP should be prioritized over those required by LCP followed by those required by FID.
Resources are often not sequenced and pipelined in the correct order. This may be because developers are not aware of the dependency of metrics on resource loads. As a result, relevant resources are sometimes not available at the right time for the corresponding metric to trigger.
Examples:
a) By the time FCP fires, the hero image should be available for firing LCP. b) By the time LCP fires, the JavaScript (JS) should be downloaded, parsed and ready (or already executing) to unblock interaction (FID).
Network/CPU Utilization
Resources are also not pipelined appropriately to ensure full CPU and Network utilization. This results in "Dead Time" on the CPU when the process is network bound and vice versa.
A great example of this is scripts that may be downloaded concurrently or sequentially. As the bandwidth gets divided during concurrent download, the total time for downloading all scripts is the same for both sequential and concurrent downloads. If you download scripts concurrently, the CPU is underutilized during the download. However, if you download the scripts sequentially, the CPU can start processing the first one as soon as it is downloaded. This results in better CPU and Network utilization.
Third-Party (3P) Products
3P libraries are often required to add common features and functionality to the website. Third parties include ads, analytics, social widgets, live chat, and other embeds that power a website. A third party library comes with its own JavaScript, images, fonts etc.
3P products don't usually have an incentive to optimize for and support the consumer site's loading performance. They could have a heavy JavaScript execution cost that delays interactivity, or gets in the way of other critical resources being downloaded.
Developers who include 3P products may tend to focus more on the value they add in terms of features rather than performance implications. As a result, 3P resources are sometimes added haphazardly, without full consideration in terms of how it fits into the overall loading sequence. This makes them hard to control and schedule.
Platform Quirks
Browsers may differ in how they prioritize requests and implement hints. Optimization is easier if you have a deep knowledge of the platform and its quirks. Behavior particular to a specific browser makes it difficult to achieve the desired loading sequence consistently.
An example of this is the preload bug on the chromium platform. The Preload (
<link rel=preload>
) instruction can be used to tell the browser to download key resources as soon as possible. It should only be used when you are sure that the resource will be used on the current page. The bug in Chromium causes it to behave such that requests issued via
<link rel=preload>
always start before other requests seen by the preload scanner even if those have higher priority. Issues such as these put a wrench in optimization plans.
HTTP2 Prioritization
The protocol itself does not provide many options or knobs for adjusting the order and priority of resources. Even if better prioritization primitives were to be made available, there are underlying problems with HTTP2 prioritization that make optimal sequencing difficult. Mainly, we cannot predict in what order servers or CDN's will prioritize requests for individual resources. Some CDN's re-prioritize requests while others implement partial, flawed, or no prioritization.
Resource level optimization
Effective sequencing needs that the resources that are being sequenced to be served optimally so that they will load quickly. Critical CSS should be inlined, Images should be sized correctly and JS should be code-split and delivered incrementally.
The framework itself is lacking constructs that allow code-splitting and serve JS and data incrementally. Users must rely on one of the following to split large chunks of 1P JS:
  1. Modern React (Suspense / Concurrent mode / Data Fetching) - This is still available for experimentation only
  2. Lazy loading using dynamic imports - This is not intuitive and developers need to manually identify the boundaries along which to split the code.
When code-splitting, developers need to achieve just the right granularity of chunks because of a granularity vs performance trade-off.
Higher granularity is desirable because it:
  1. Minimizes JS needed for individual route and on subsequent user interactions
  2. Allows for caching of common dependencies. This ensures that a change in the library doesn't require re-fetching of the entire bundle.
At the same time too much granularity when code-splitting can be bad because too many small chunks lower compression rates for individual chunks and affect browser performance.
Resource optimization also requires the elimination of dead or unused code. Unnecessary or obsolete JS may be often shipped to modern browsers which negatively affects performance. JS transpiled to ES5 and bundled with polyfills is unnecessary for modern browsers. Libraries and npm packages are often not published in ES module format. This makes it hard for bundlers to tree shake and optimize.
As you might have noticed, these issues are not limited to a particular set of resources or platforms. To work around these problems, one requires an understanding of the entire tech stack and how different resources can be coalesced to achieve optimal metrics.
我们有幸为众多合作伙伴的网站进行性能分析,发现不同合作伙伴的网站在页面高效加载方面存在多个相似问题。
开发者的预期与浏览器对页面资源的优先级处理之间往往存在明显差距,这通常会导致性能得分不理想。我们进一步分析了造成这种差距的原因,以下几点总结了分析的核心内容。
加载顺序不合理
优化Web Vitals不仅需要理解每个指标的含义,还要了解它们的触发顺序以及与不同关键资源的关联。FCP先于LCP触发,LCP先于FID触发。因此,实现FCP所需的资源应优先于LCP所需的资源,其次是FID所需的资源。
资源的排序和流水线处理往往不正确,这可能是因为开发者不了解指标对资源加载的依赖性。结果,相关资源有时无法在正确的时间就绪,导致对应的指标无法触发。
示例
a) 当FCP触发时,首屏主图应已就绪,以便触发LCP。 b) 当LCP触发时,JavaScript(JS)应已下载、解析完成并就绪(或已在执行),以解除交互阻塞(FID)。
网络/CPU利用率
资源的流水线处理也不够合理,无法充分利用CPU和网络资源。这会导致CPU处于“空闲时间”(当进程受网络限制时),反之亦然。
一个很好的例子是脚本的并发下载或顺序下载。在并发下载时,带宽会被分配,因此所有脚本的总下载时间与顺序下载相同。如果并发下载脚本,下载过程中CPU会未得到充分利用;而如果顺序下载脚本,CPU可以在第一个脚本下载完成后立即开始处理,从而实现更好的CPU和网络利用率。
第三方(3P)产品
网站通常需要第三方库来添加常见功能,第三方包括广告、分析工具、社交组件、在线聊天和其他嵌入内容。第三方库会自带JavaScript、图片、字体等资源。
第三方产品通常没有动力去优化和支持客户网站的加载性能。它们可能会带来沉重的JavaScript执行开销,延迟交互性,或者阻碍其他关键资源的下载。
集成第三方产品的开发者往往更关注它们带来的功能价值,而非性能影响。因此,第三方资源有时会被随意添加,未充分考虑它们在整体加载顺序中的位置,这使得它们难以控制和调度。
平台特性差异
不同浏览器在请求优先级处理和提示实现上可能存在差异。如果你深入了解平台及其特性,优化会更容易。特定浏览器的独特行为使得难以持续实现理想的加载顺序。
例如,Chromium平台上的preload bugPreload
<link rel=preload>
)指令可用于告知浏览器尽快下载关键资源,仅当你确定当前页面会使用该资源时才应使用它。Chromium中的这个bug导致通过
<link rel=preload>
发出的请求总是先于预加载扫描器发现的其他请求,即使这些请求优先级更高。这类问题会打乱优化计划。
HTTP2优先级
协议本身并没有提供太多调整资源顺序和优先级的选项或机制。即使有更好的优先级原语可用,HTTP2优先级存在的问题也使得实现最优顺序变得困难。主要问题在于,我们无法预测服务器或CDN会如何对单个资源的请求进行优先级排序。有些CDN会重新调整请求优先级,而另一些则只实现了部分、有缺陷的优先级处理,甚至完全不处理。
资源级优化
有效的排序要求被排序的资源能够被最优地提供,以便快速加载。关键CSS应内联,图片应调整到合适尺寸,JS应进行代码分割并增量交付。
框架本身缺乏支持代码分割以及增量交付JS和数据的结构。用户必须依赖以下方式之一来分割大型第一方JS:
  1. 现代React(Suspense / Concurrent模式 / 数据获取)——目前仍处于实验阶段
  2. 使用动态导入进行懒加载——这不够直观,开发者需要手动确定代码分割的边界
进行代码分割时,开发者需要实现恰到好处的代码块粒度,因为粒度与性能之间存在权衡。
更高的粒度是可取的,因为:
  1. 最小化单个路由和后续用户交互所需的JS
  2. 允许缓存公共依赖项,确保库的变更无需重新获取整个代码包
但同时,代码分割的粒度过细也不好,因为太多小代码块会降低单个代码块的压缩率,并影响浏览器性能。
资源优化还需要消除无用代码。不必要或过时的JS经常被发送到现代浏览器,这会对性能产生负面影响。针对ES5转译并捆绑了polyfills的JS对现代浏览器来说是不必要的。库和npm包通常不以ES模块格式发布,这使得打包工具难以进行tree shake和优化。
正如你所注意到的,这些问题并不局限于特定的资源集或平台。要解决这些问题,需要了解整个技术栈,以及如何整合不同资源以实现最优指标。

More on Resources - Relations, Constraints, and Priorities

更多关于资源的内容——关系、约束和优先级

In the previous section, we gave a few examples of how certain resources are required for a specific event like FCP or LCP to fire. Let us try to understand all such dependencies first before we discuss a way to work with them. Following is a resource-wise list of recommendations, constraints, and gotchas that need to be considered before we define an ideal sequence.
Critical CSS
Critical CSS refers to the minimum CSS required for FCP. It is better to inline such CSS within HTML rather than import it from another CSS file. Only the CSS required for the route should be downloaded at any given time and all critical CSS should be split accordingly.
If inlining is not possible, critical CSS should be preloaded and served from the same origin as the document. Avoid serving critical CSS from multiple domains or direct use of 3rd party critical CSS like Google Fonts. Your own server could serve as a proxy for 3rd party critical CSS instead.
Delay in fetching CSS or incorrect order of fetching CSS could impact FCP and LCP. To avoid this, non-inlined CSS should be prioritized and ordered above 1P JS and ATF images on the network.
Too much inlined CSS can cause HTML bloating and long style parsing times on the main thread. This can hurt the FCP. As such identifying what is critical and code-splitting are essential.
Inlined CSS cannot be cached. One workaround for this is to have a duplicate request for the CSS that can be cached. Note however, that this can result in multiple full-page layouts which could impact FID.
Fonts
Like critical CSS, the CSS for critical fonts should also be inlined. If inlining is not possible the script should be loaded with a preconnect specified. Delay in fetching fonts, e.g., google fonts or fonts from a different domain can affect FCP. Preconnect tells the browser to set up connections to these resources earlier.
Inlining fonts can bloat the HTML significantly and delay initiating other critical resource fetches. Font fallback may be used to unblock FCP and make the text available. However, using font fallback can affect CLS due to jumping fonts. It can also affect FID due to a potentially large style and layout task on the main thread when the real font arrives.
Above the Fold (ATF) Images
This refers to images that are initially visible to the user on page load because they are within the viewport. A special case for ATF images is the hero image for the page. All ATF images should be sized. Unsized images hurt the CLS metric because of the layout shift that occurs when they are fully rendered. Placeholders for ATF images should be rendered by the server.
Delayed hero image or blank placeholders would result in a late LCP. Moreover, LCP will re-trigger, if the placeholder size does not match with the intrinsic size of the actual hero image and the image is not overlaid on replacement. Ideally, there should be no impact on FCP due to ATF images but in practice, an image can fire FCP.
Below the Fold (BTF) Images
These are images that are not immediately visible to the user on page load. As such they are ideal candidates for lazy loading. This ensures that they do not contend with 1P JS or important 3P needed on the page. If BTF images were to be loaded before 1P JS or important 3P resources, FID would get delayed.
1P JavaScript
1P JS impacts the interaction readiness of the application. It can get delayed on the network behind images & 3P JS and on the main thread behind 3P JS. As such it should start loading before ATF images on the network and execute before 3P JS on the main thread. 1P JS does not block FCP and LCP in pages that are rendered on the server-side.
3P JavaScript
3P sync script in HTML head could block CSS & font parsing and therefore FCP. Sync script in the head also blocks HTML body parsing. 3P script execution on the main thread can delay 1P script execution and push out hydration and FID. As such, better control is required for loading 3P scripts.
These recommendations and constraints would generally apply irrespective of the tech stack and browser. Note, how something that is a recommendation can also become a constraint. For example, inlining fonts and CSS is great, but too much of it can cause bloating. The trick is to find a balance between 'Too little Too late' and 'Too much Too soon'.
Following are the key takeaways from Chrome's resource priority table:
  • CSS and Fonts are loaded with the highest priority. This should help us prioritize critical CSS and fonts.
  • Scripts get different priorities based on where they are in the document and whether they are async, defer, or blocking. Blocking scripts requested before the first image (or an image early in the document) are given higher priority over blocking scripts requested after the first image is fetched. Async/defer/injected scripts, regardless of where they are in the document, have the lowest priority. Thus we can prioritize different scripts by using the appropriate attributes for async and defer.
  • Images that are visible and in the viewport have a higher priority (Net: Medium) than those that are not in the viewport (Net: Lowest). This helps us prioritize ATF images over BTF images.
Let us now see how all of the above details can be put together to define an optimal loading sequence.
在上一节中,我们举了几个例子说明某些资源是如何触发FCP或LCP等特定事件的。在讨论如何处理这些依赖关系之前,我们先来了解所有此类依赖关系。以下是按资源类型列出的建议、约束和注意事项,在定义理想顺序之前需要考虑这些内容。
关键CSS
关键CSS是指实现FCP所需的最小CSS。最好将此类CSS内联到HTML中,而非从另一个CSS文件导入。任何时候都只应下载当前路由所需的CSS,并且所有关键CSS都应相应地分割。
如果无法内联,关键CSS应预加载并从与文档相同的源提供。避免从多个域提供关键CSS,或直接使用第三方关键CSS(如Google Fonts)。你可以使用自己的服务器作为第三方关键CSS的代理。
CSS获取延迟或获取顺序错误可能会影响FCP和LCP。为避免这种情况,非内联CSS应在网络上优先于第一方JS和首屏图片获取。
过多的内联CSS会导致HTML膨胀,并在主线程上增加样式解析时间,这会损害FCP。因此,识别关键内容并进行代码分割至关重要。
内联CSS无法被缓存。解决此问题的一种方法是对CSS发起重复请求以便缓存,但这可能会导致多次全页面布局,从而影响FID。
字体
与关键CSS一样,关键字体的CSS也应内联。如果无法内联,应使用preconnect加载脚本。字体获取延迟(例如Google Fonts或来自其他域的字体)会影响FCP。preconnect告知浏览器提前建立与这些资源的连接。
内联字体会显著膨胀HTML,延迟其他关键资源的获取启动。可以使用字体回退来解除FCP阻塞,使文本可用。然而,使用字体回退可能会因字体跳动而影响CLS,当实际字体加载时,主线程上的样式和布局任务可能会很大,从而影响FID。
首屏(ATF)图片
指页面加载时用户最初可见的图片,因为它们在视口内。首屏图片的一个特殊情况是页面的首屏主图。所有首屏图片都应调整尺寸。未调整尺寸的图片会因完全渲染时的布局偏移而损害CLS指标。首屏图片的占位符应由服务器渲染。
首屏主图延迟加载或空白占位符会导致LCP触发延迟。此外,如果占位符尺寸与实际首屏主图的固有尺寸不匹配,且图片未覆盖占位符,LCP会重新触发。理想情况下,首屏图片不应影响FCP,但实际上图片可能会触发FCP。
首屏以下(BTF)图片
指页面加载时用户无法立即看到的图片。因此,它们是懒加载的理想候选者。这确保它们不会与第一方JS或页面上重要的第三方资源竞争。如果首屏以下图片在第一方JS或重要第三方资源之前加载,FID会被延迟。
第一方JavaScript
第一方JS影响应用的交互就绪状态。它可能在网络上被图片和第三方JS延迟,在主线程上被第三方JS延迟。因此,它应在网络上优先于首屏图片开始加载,并在主线程上优先于第三方JS执行。在服务器端渲染的页面中,第一方JS不会阻塞FCP和LCP。
第三方JavaScript
HTML头部的第三方同步脚本可能会阻塞CSS和字体解析,从而阻塞FCP。头部的同步脚本还会阻塞HTML主体解析。主线程上的第三方脚本执行会延迟第一方脚本执行,推迟 hydration 和FID。因此,需要更好地控制第三方脚本的加载。
这些建议和约束通常适用于所有技术栈和浏览器。请注意,某些建议也可能成为约束。例如,内联字体和CSS很好,但过多会导致膨胀。关键在于找到“太少太晚”和“太多太早”之间的平衡。
以下是Chrome资源优先级表的关键要点:
  • CSS和字体以最高优先级加载,这有助于我们优先处理关键CSS和字体。
  • 脚本的优先级取决于它们在文档中的位置以及是否为async、defer或阻塞脚本。在第一张图片(或文档中较早的图片)之前请求的阻塞脚本,优先级高于在第一张图片获取之后请求的阻塞脚本。无论在文档中的哪个位置,async/defer/注入的脚本优先级最低。因此,我们可以通过为脚本使用适当的async和defer属性来区分优先级。
  • 可见且在视口内的图片优先级(网络:中等)高于不在视口内的图片(网络:最低)。这有助于我们优先处理首屏图片而非首屏以下图片。
现在,我们来看看如何将上述所有细节整合起来,定义一个最优的加载顺序。

What is the Ideal Loading Sequence

理想的加载顺序是什么?

With that background, we can now propose a loading sequence that should optimize the loading of both 1P and 3P resources. The proposed sequence uses Next.js Server Side Rendering (SSR) as a reference for optimization.
有了这些背景知识,我们现在可以提出一个优化第一方和第三方资源加载的顺序。建议的顺序以Next.js服务器端渲染(SSR)作为优化参考。

Current State

当前状态

Based on our experience, the following is the typical loading sequence we have observed for a Next.js SSR application before optimization.
ResourceState
CSSCSS is preloaded before JS but is not inlined
JavaScript1P JS is preloaded. 3P JS is not managed and can still be render-blocking anywhere in the document.
FontsFonts are neither inlined nor do they use preconnect. Fonts are loaded via external stylesheets which delays the loading. Fonts may or may not be display blocking.
ImagesHero images are not prioritized. Both ATF and BTF images are not optimized.
根据我们的经验,以下是Next.js SSR应用优化前的典型加载顺序:
资源状态
CSSCSS在JS之前预加载,但未内联
JavaScript第一方JS已预加载。第三方JS未被管理,仍可能在文档中的任何位置阻塞渲染
字体字体既未内联也未使用preconnect。字体通过外部样式表加载,导致加载延迟。字体可能会阻塞显示,也可能不会
图片首屏主图未被优先处理。首屏和首屏以下图片均未优化

Proposed Sequence without 3P

不含第三方资源的建议顺序

Following is a loading sequence that takes into account all of the constraints discussed previously. Let us first tackle a sequence without 3P. We will then see how 3P resources can be interleaved in this sequence. Note that, we have considered Google Fonts as 1P here.
# (Main Thread)Event# (Network)Request
1Parse the HTML1Small inline 1P scripts
2Execute small inline 1P scripts2Inlined critical CSS (Preload if external)
3Inlined critical Fonts (Preconnect if external)
3Parse FCP resources (critical CSS, font)4LCP Image (Preconnect if external)
FCP5Fonts (triggered from inline font-css, Preconnect)
4Render LCP resources (Hero image, text)6Non-critical (async) CSS
7First-party JS for interactivity
8Above the fold images (preconnect)
LCP9Below the fold images
5Render important ATF images
Visually Complete
6Parse Non-critical (async) CSS
7Execute 1P JS and hydrate10Lazy-loaded JS chunks
FID
While some parts of this sequence may be intuitive, the following points will help to justify it further.
  1. We recommend avoiding preload as much as possible because it forces manual preload on every preceding resource and also causes manual curation of ordering. Preload should be especially avoided on fonts, as it is tricky to detect critical fonts.
  2. Font-CSS should be ideally inlined. Fonts from another origin should be fetched using preconnect.
  3. Preconnect is recommended for all resources from another origin. This will ensure that a connection is established in advance for downloading these resources.
  4. Non-critical CSS should be fetched before user interaction begins (FID). This would avoid styling problems due to subsequent rendering of such CSS.
  5. Start fetching first-party JS before ATF images on the network. It will take some time to download and parse the JS.
  6. Parsing of the HTML on the main thread and download of ATF images can continue in parallel while 1P JS is parsed.
以下是考虑了之前讨论的所有约束的加载顺序。我们先处理不含第三方资源的顺序,然后再看看如何将第三方资源插入到这个顺序中。请注意,我们在此将Google Fonts视为第一方资源。
#(主线程)事件#(网络)请求
1解析HTML1小型内联第一方脚本
2执行小型内联第一方脚本2内联关键CSS(如果是外部资源则预加载)
3内联关键字体(如果是外部资源则使用preconnect)
3解析FCP资源(关键CSS、字体)4LCP图片(如果是外部资源则使用preconnect)
FCP5字体(由内联字体CSS触发,使用preconnect)
4渲染LCP资源(首屏主图、文本)6非关键(async)CSS
7用于交互的第一方JS
8首屏图片(使用preconnect)
LCP9首屏以下图片
5渲染重要的首屏图片
视觉完成
6解析非关键(async)CSS
7执行第一方JS并进行hydration10懒加载JS代码块
FID
虽然这个顺序的某些部分可能很直观,但以下几点有助于进一步证明其合理性:
  1. 我们建议尽可能避免使用preload,因为它需要手动预加载每个前置资源,还需要手动管理顺序。尤其应避免对字体使用preload,因为检测关键字体很棘手。
  2. 字体CSS应理想地内联。来自其他源的字体应使用preconnect获取。
  3. 建议对所有来自其他源的资源使用preconnect,这将确保提前建立连接以下载这些资源。
  4. 非关键CSS应在用户交互开始(FID)之前获取,这将避免因后续渲染此类CSS而导致的样式问题。
  5. 在网络上优先开始获取第一方JS,而非首屏图片。JS的下载和解析需要一些时间。
  6. 主线程上的HTML解析和首屏图片的下载可以在第一方JS解析的同时并行进行。

Proposed Sequence with 3P

包含第三方资源的建议顺序

Finally, we can propose a sequence for all key resources that are commonly loaded in a modern web application. Following is what the sequence for events on the main browser thread and network fetch requests will look like with 3P resources in the picture.
#Main Thread EventNetwork Request
1Parse the HTMLFCP blocking 3P resources
2
3Small inline 1P scripts
4Execute small inline 1P scriptsInlined critical CSS (Preload if external)
5Parse FCP blocking 3P resourcesInlined critical Fonts (Preconnect if external)
6Parse FCP resources (critical CSS, font)3P personalized ATF image required for LCP
7FCPLCP Image (Preconnect if external)
8Render 3P personalized ATF image required for LCPFonts (triggered from inline font-css, Preconnect)
9Non-critical (async) CSS
10Render LCP resources (Hero image, text)3P that must execute before first user interaction
11First-party JS for interactivity
12LCP
13Render important ATF imagesDefault 3P JS
14Parse Non-critical (async) CSS
15Execute 3P required for first user interactionBelow the fold images
16Execute 1P JS and hydrateLazy-loaded JS chunks
FIDLess important 3P JS
The main concern here is how do you ensure that 3P scripts are downloaded optimally and in the required sequence.
Since the script request goes to another domain, preconnect is recommended for the following 3P requests:
  • #1 - FCP blocking 3P resources
  • #5 - 3P personalized ATF image required for LCP
  • #9 - 3P that must execute before first user interaction
  • #12 - Default 3P JS
To achieve the desired sequence, we recommend using the ScriptLoader component for Next. This component is designed to "optimize the critical rendering path and ensure external scripts don't become a bottleneck to optimal page load." The feature most relevant to our discussion is Loading Priorities. This allows us to schedule the scripts at different milestones to support different use cases. Following are the loading priority values available:
After-Interactive: Loads the specific 3P script after the next hydration. This can be used to load Tag-managers, Ads, or Analytics scripts that we want to execute as early as possible but after 1P scripts.
Before-Interactive: Loads the specific 3P script before hydration. It can be used in cases where we want the 3P script to execute before the 1P script. Eg., polyfill.io, bot detection, security and authentication, user consent management (GDPR), etc.
Lazy-Onload: Prioritize all other resources over the specified 3P script and lazy load the script. It can be used for CRM components like Google Feedback or Social Network specific scripts like those used for share buttons, comments, etc.
Thus, preconnect, script attributes and ScriptLoader for Next.js together can help us get the desired sequence for all our scripts.
最后,我们可以为现代Web应用中常见的所有关键资源提出一个加载顺序。以下是包含第三方资源时,浏览器主线程事件和网络请求的顺序:
#主线程事件网络请求
1解析HTML阻塞FCP的第三方资源
2
3小型内联第一方脚本
4执行小型内联第一方脚本内联关键CSS(如果是外部资源则预加载)
5解析阻塞FCP的第三方资源内联关键字体(如果是外部资源则使用preconnect)
6解析FCP资源(关键CSS、字体)LCP所需的第三方个性化首屏图片
7FCPLCP图片(如果是外部资源则使用preconnect)
8渲染LCP所需的第三方个性化首屏图片字体(由内联字体CSS触发,使用preconnect)
9非关键(async)CSS
10渲染LCP资源(首屏主图、文本)必须在首次用户交互前执行的第三方资源
11用于交互的第一方JS
12LCP
13渲染重要的首屏图片默认第三方JS
14解析非关键(async)CSS
15执行首次用户交互所需的第三方资源首屏以下图片
16执行第一方JS并进行hydration懒加载JS代码块
FID次要第三方JS
这里主要关注的是如何确保第三方脚本被最优地下载并按所需顺序执行。
由于脚本请求发送到其他域,建议对以下第三方请求使用preconnect:
  • #1 - 阻塞FCP的第三方资源
  • #5 - LCP所需的第三方个性化首屏图片
  • #9 - 必须在首次用户交互前执行的第三方资源
  • #12 - 默认第三方JS
为了实现所需的顺序,我们建议使用Next.js的ScriptLoader组件。该组件旨在“优化关键渲染路径,确保外部脚本不会成为页面最优加载的瓶颈。”与我们讨论最相关的功能是加载优先级,它允许我们在不同的里程碑调度脚本以支持不同的用例。以下是可用的加载优先级值:
After-Interactive:在下次hydration后加载特定的第三方脚本。可用于加载标签管理器、广告或分析脚本,这些脚本我们希望尽早执行,但在第一方脚本之后。
Before-Interactive:在hydration之前加载特定的第三方脚本。可用于希望第三方脚本在第一方脚本之前执行的情况,例如polyfill.io、机器人检测、安全与认证、用户同意管理(GDPR)等。
Lazy-Onload:优先加载所有其他资源,延迟加载指定的第三方脚本。可用于CRM组件(如Google Feedback)或社交网络特定脚本(如分享按钮、评论等使用的脚本)。
因此,preconnect、脚本属性和Next.js的ScriptLoader一起可以帮助我们为所有脚本实现所需的顺序。

Conclusion

结论

The responsibility of optimizing apps falls on the shoulders of the creators of the platforms used as well as the developers who use it. Common issues need to be addressed. We aim to make sequencing easier from the inside out. A tried and tested set of recommendations for different use cases and initiatives like the Script Loader help to achieve this for the React-Next.js stack. The next step would be to ensure that new apps conform to the recommendations above.
优化应用的责任落在平台创建者和使用平台的开发者肩上。需要解决常见问题。我们旨在从内到外简化加载顺序的优化。针对不同用例经过验证的建议集以及Script Loader等工具,有助于在React-Next.js技术栈上实现这一目标。下一步是确保新应用符合上述建议。

Source

来源