awesome-interview/book3/topic-white-screen-optimiza...

21 lines
35 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en" dir="ltr" class="docs-wrapper docs-doc-page docs-version-current plugin-docs plugin-id-default docs-doc-id-book3/topic-white-screen-optimization">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="generator" content="Docusaurus v2.0.0-beta.18">
<link rel="search" type="application/opensearchdescription+xml" title="HZFE - 剑指前端 Offer" href="/awesome-interview/opensearch.xml">
<link rel="preconnect" href="https://hm.baidu.com">
<script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?c7cd0fd77ac518cc6ef46461cdc9524b";var c=document.getElementsByTagName("script")[0];c.parentNode.insertBefore(e,c)}()</script>
<script src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js" async data-ad-client="ca-pub-9889934432771967"></script>
<script src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-9889934432771967" async crossorigin="anonymous"></script><title data-rh="true">如何减少白屏的时间 | HZFE - 剑指前端 Offer</title><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://febook.hzfe.org/awesome-interview/book3/topic-white-screen-optimization"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="如何减少白屏的时间 | HZFE - 剑指前端 Offer"><meta data-rh="true" name="description" content="回答关键点"><meta data-rh="true" property="og:description" content="回答关键点"><link data-rh="true" rel="icon" href="/awesome-interview/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://febook.hzfe.org/awesome-interview/book3/topic-white-screen-optimization"><link data-rh="true" rel="alternate" href="https://febook.hzfe.org/awesome-interview/book3/topic-white-screen-optimization" hreflang="en"><link data-rh="true" rel="alternate" href="https://febook.hzfe.org/awesome-interview/book3/topic-white-screen-optimization" hreflang="x-default"><link data-rh="true" rel="preconnect" href="https://PED5MQGL7T-dsn.algolia.net" crossorigin="anonymous"><link rel="stylesheet" href="/awesome-interview/assets/css/styles.62902d4b.css">
<link rel="preload" href="/awesome-interview/assets/js/runtime~main.16895322.js" as="script">
<link rel="preload" href="/awesome-interview/assets/js/main.a6349f88.js" as="script">
</head>
<body class="navigation-with-keyboard">
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}()</script><div id="__docusaurus">
<div role="region"><a href="#" class="skipToContent_ZgBM">Skip to main content</a></div><nav class="navbar navbar--fixed-top navbarHideable_ObN2"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Navigation bar toggle" class="navbar__toggle clean-btn" type="button" tabindex="0"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/awesome-interview/"><div class="navbar__logo"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_W2Cr themedImage--light_TfLj"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_W2Cr themedImage--dark_oUvU"></div><b class="navbar__title">剑指前端 Offer</b></a></div><div class="navbar__items navbar__items--right"><a href="https://github.com/hzfe/awesome-interview" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">GitHub<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_I5OW"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a><div class="searchBox_qEbK"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"></span></button></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div class="main-wrapper"><div class="docPage_P2Lg"><button aria-label="Scroll back to top" class="clean-btn theme-back-to-top-button backToTopButton_RiI4" type="button"></button><aside class="theme-doc-sidebar-container docSidebarContainer_rKC_"><div class="sidebar_RiAD sidebarWithHideableNavbar_d0QC"><a tabindex="-1" class="sidebarLogo_YUvz" href="/awesome-interview/"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_W2Cr themedImage--light_TfLj"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_W2Cr themedImage--dark_oUvU"><b>剑指前端 Offer</b></a><nav class="menu thin-scrollbar menu_izAj"><ul class="theme-doc-sidebar-menu menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/awesome-interview/about">关于我们</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/awesome-interview/">前言</a></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="menu__link menu__link--sublist menu__link--sublist-caret" aria-expanded="false" href="/awesome-interview/book1/browser-cross-origin">模拟题一</a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="menu__link menu__link--sublist menu__link--sublist-caret" aria-expanded="false" href="/awesome-interview/book2/browser-render-mechanism">模拟题二</a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item"><div class="menu__list-item-collapsible"><a class="menu__link menu__link--sublist menu__link--sublist-caret menu__link--active" aria-expanded="true" href="/awesome-interview/book3/browser-event-loop">模拟题三</a></div><ul style="display:block;overflow:visible;height:auto" class="menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/browser-event-loop">浏览器:浏览器事件循环</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/browser-memory-leaks">浏览器:如何定位内存泄露</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/engineer-webpack-loader">工程化:谈下 webpack loader 的机制</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/frame-react-hooks">框架React Hooks 实现原理</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/frame-diff">框架:常见框架的 Diff 算法</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/js-async">基础JavaScript 异步编程</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/js-ts-interface-type">基础TypeScript 中的 Interface 和 Type Alias</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/css-mobile-adaptive">样式:移动端自适应的常见手段</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/network-http-1-2">网络HTTP2 和 HTTP1.1 的对比</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/coding-arr-to-tree">编码:将列表还原为树状结构</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/awesome-interview/book3/algorithm-binary-tree-k">算法:二叉搜索树的第 k 个结点</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link menu__link--active" aria-current="page" tabindex="0" href="/awesome-interview/book3/topic-white-screen-optimization">综合:如何减少白屏的时间</a></li></ul></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="menu__link menu__link--sublist menu__link--sublist-caret" aria-expanded="false" href="/awesome-interview/book4/browser-router">模拟题四</a></div></li></ul></nav><button type="button" title="Collapse sidebar" aria-label="Collapse sidebar" class="button button--secondary button--outline collapseSidebarButton_FykI"><svg width="20" height="20" aria-hidden="true" class="collapseSidebarButtonIcon_DTRl"><g fill="#7a7a7a"><path d="M9.992 10.023c0 .2-.062.399-.172.547l-4.996 7.492a.982.982 0 01-.828.454H1c-.55 0-1-.453-1-1 0-.2.059-.403.168-.551l4.629-6.942L.168 3.078A.939.939 0 010 2.528c0-.548.45-.997 1-.997h2.996c.352 0 .649.18.828.45L9.82 9.472c.11.148.172.347.172.55zm0 0"></path><path d="M19.98 10.023c0 .2-.058.399-.168.547l-4.996 7.492a.987.987 0 01-.828.454h-3c-.547 0-.996-.453-.996-1 0-.2.059-.403.168-.551l4.625-6.942-4.625-6.945a.939.939 0 01-.168-.55 1 1 0 01.996-.997h3c.348 0 .649.18.828.45l4.996 7.492c.11.148.168.347.168.55zm0 0"></path></g></svg></button></div></aside><main class="docMainContainer_TCnq"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_DM6M"><div class="docItemContainer_vinB"><article><nav class="theme-doc-breadcrumbs breadcrumbsContainer_Xlws" aria-label="breadcrumbs"><ul class="breadcrumbs" itemscope="" itemtype="https://schema.org/BreadcrumbList"><li class="breadcrumbs__item"><a class="breadcrumbs__link" href="/awesome-interview/">🏠</a></li><li itemscope="" itemprop="itemListElement" itemtype="https://schema.org/ListItem" class="breadcrumbs__item"><span class="breadcrumbs__link" itemprop="item name">模拟题三</span><meta itemprop="position" content="1"></li><li itemscope="" itemprop="itemListElement" itemtype="https://schema.org/ListItem" class="breadcrumbs__item breadcrumbs__item--active"><span class="breadcrumbs__link" itemprop="item name">综合:如何减少白屏的时间</span><meta itemprop="position" content="2"></li></ul></nav><div class="tocCollapsible_jdIR theme-doc-toc-mobile tocMobile_TmEX"><button type="button" class="clean-btn tocCollapsibleButton_Fzxq">On this page</button></div><div class="theme-doc-markdown markdown"><h1>如何减少白屏的时间</h1><h2 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="回答关键点">回答关键点<a class="hash-link" href="#回答关键点" title="Direct link to heading"></a></h2><p><code>资源优化</code> <code>预加载</code> <code>服务端渲染</code> <code>性能监控指标</code> <code>HTTP/2</code></p><p>前端性能优化是前端开发中一个重要环节,它包括很多内容,其中页面的白屏时间是用户最初接触到的部分,白屏时间过长会显著影响用户的留存率和转换率。</p><p>我们以一个 APP 内嵌 Webview 打开页面作为例子,来分析页面打开过程以及可优化的方向:</p><ol start="0"><li>前置条件<ul><li>性能监控指标</li></ul></li><li>APP 内点击打开页面</li><li>DNS 解析<ul><li>预解析</li><li>域名收敛</li></ul></li><li>TCP 连接<ul><li>预连接</li></ul></li><li>发送并响应请求<ul><li>HTTP/2</li></ul></li><li>浏览器解析页面<ul><li>服务端渲染</li></ul></li><li>加载资源并渲染页面<ul><li>骨架屏</li><li>资源优化</li><li>资源预加载</li></ul></li><li>请求接口,获取数据并渲染<ul><li>接口预加载</li><li>接口合并</li></ul></li></ol><h2 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="知识点深入">知识点深入<a class="hash-link" href="#知识点深入" title="Direct link to heading"></a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="1-前端性能监控指标">1. 前端性能监控指标<a class="hash-link" href="#1-前端性能监控指标" title="Direct link to heading"></a></h3><p>性能优化的前置条件是性能有测量标准并可以被监控。常用的性能监控指标有以下几块。</p><p>Navigation Timing API</p><ul><li>responseStart - fetchStart收到首字节的耗时</li><li>domContentLoadedEventEnd - fetchStartHTML 加载完成耗时</li><li>loadEventStart - fetchStart页面完全加载耗时</li><li>domainLookupEnd - domainLookupStartDNS 解析耗时</li><li>connectEnd - connectStartTCP 连接耗时</li><li>responseStart - requestStartTime to First ByteTTFB</li><li>responseEnd - responseStart数据传输耗时</li><li>domInteractive - responseEndDOM 解析耗时</li><li>loadEventStart - domContentLoadedEventEnd资源加载耗时页面中同步加载的资源)</li></ul><p>Lighthouse Performance</p><ul><li>FPFirst Paint首次绘制</li><li>FCPFirst Contentful Paint首次内容绘制</li><li>FMPFirst Meaningful Paint首次有效绘制</li><li>LCPLargest Contentful Paint最大可见元素绘制</li><li>TTITime to Interactive可交互时间</li><li>TTFBTime to First Byte浏览器接收第一个字节的时间</li></ul><p>除了上面之外UC 内核也有一套性能监控指标:</p><ul><li>T0Blink 收到 HTTP Head 的时间。</li><li>T1首屏有内容显示的时间。</li><li>T2首屏全部显示出来的时间。</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="2-dns-解析优化">2. DNS 解析优化<a class="hash-link" href="#2-dns-解析优化" title="Direct link to heading"></a></h3><p>DNS 解析优化是性能优化重要的一环DNS 的作用是根据域名获取对应的 IP 地址,获取之后后续的 HTTP 流程才能进行下去。</p><p>DNS 解析是一个开销较大的过程,一次 DNS 解析通常需要耗费几十到上百毫秒,而在移动端网络或其他弱网环境下 DNS 解析延迟会更加严重,对 DNS 解析优化则可以减少这一步骤的耗时。</p><h4 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="21-dns-预解析">2.1 DNS 预解析<a class="hash-link" href="#21-dns-预解析" title="Direct link to heading"></a></h4><p>我们可以通过 DNS 预解析的方式提前获取 IP 地址,以缩短后续请求的响应时间。</p><p>前端可以通过 <code>dns-prefetch</code> 预解析,具体方式如下:</p><div class="codeBlockContainer_I0IT language-html theme-code-block"><div class="codeBlockContent_wNvx" style="color:#393A34;background-color:#f6f8fa"><pre tabindex="0" class="prism-code language-html codeBlock_jd64 thin-scrollbar"><code class="codeBlockLines_mRuA"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">link</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">rel</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">dns-prefetch</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">href</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">https://hzfe.org/</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" title="Copy" class="copyButton_eDfN clean-btn"><span class="copyButtonIcons_W9eQ" aria-hidden="true"><svg class="copyButtonIcon_XEyF" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_i9w9" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="22-域名收敛">2.2 域名收敛<a class="hash-link" href="#22-域名收敛" title="Direct link to heading"></a></h4><p>域名收敛的目的是减少页面中域名的数量,从而减少所需的 DNS 解析次数,最终减少页面的 DNS 解析过程的耗时,加快页面加载速度。</p><h3 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="3-tcp-连接优化">3. TCP 连接优化<a class="hash-link" href="#3-tcp-连接优化" title="Direct link to heading"></a></h3><p>前端可以通过 <code>preconnect</code> 在请求发送前预先执行一些操作,这些操作包括 DNS 解析TCP 握手 和 TLS 协商。具体方式如下:</p><div class="codeBlockContainer_I0IT language-html theme-code-block"><div class="codeBlockContent_wNvx" style="color:#393A34;background-color:#f6f8fa"><pre tabindex="0" class="prism-code language-html codeBlock_jd64 thin-scrollbar"><code class="codeBlockLines_mRuA"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">link</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">href</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">https://hzfe.org</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">rel</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">preconnect</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" title="Copy" class="copyButton_eDfN clean-btn"><span class="copyButtonIcons_W9eQ" aria-hidden="true"><svg class="copyButtonIcon_XEyF" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_i9w9" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="4-请求优化">4. 请求优化<a class="hash-link" href="#4-请求优化" title="Direct link to heading"></a></h3><p>通过使用 HTTP/2 协议,可以依赖 HTTP/2 的多路复用、首部压缩、二进制分帧和服务端推送等特性,从而加快整体请求的响应速度,加快页面的渲染展示。</p><h3 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="5-页面解析优化">5. 页面解析优化<a class="hash-link" href="#5-页面解析优化" title="Direct link to heading"></a></h3><p>浏览器获取 HTML 文件后,需要对 HTML 解析,然后才能开始渲染页面,这个过程中页面也是处于白屏状态。通过对这一过程进行优化可以加快页面的渲染展示。</p><h4 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="51-服务端渲染server-side-rendering">5.1 服务端渲染Server-Side Rendering<a class="hash-link" href="#51-服务端渲染server-side-rendering" title="Direct link to heading"></a></h4><p>目前流行的前后端分离的开发模式,由于前端需要等待 JS 文件和接口加载完成之后才能渲染页面,导致白屏时间变长。服务端渲染是指在服务端将页面的渲染逻辑处理好,然后将处理好的 HTML 直接返回给前端展示。这样即可减少页面白屏的时间。</p><h4 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="52-预渲染">5.2 预渲染<a class="hash-link" href="#52-预渲染" title="Direct link to heading"></a></h4><p>除了服务端渲染之外,还可以在前端打包时使用 prerender-spa-plugin 之类的插件进行简单的预渲染,减少页面白屏的时间。</p><h3 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="6-资源加载优化和页面渲染优化">6. 资源加载优化和页面渲染优化<a class="hash-link" href="#6-资源加载优化和页面渲染优化" title="Direct link to heading"></a></h3><p>浏览器解析 HTML 的同时会加载相关的资源,通过对资源的加载过程进行优化也可以减少页面的白屏时间。</p><h4 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="61-骨架屏">6.1 骨架屏<a class="hash-link" href="#61-骨架屏" title="Direct link to heading"></a></h4><p>骨架屏是在需要等待加载内容的位置提供一些图形组合占位,提前给用户描述页面的基础结构,等待数据加载完成之后,再替换成实际的内容。</p><p>骨架屏可以在数据加载前,提前渲染页面,缩短白屏时间,提升用户体验。</p><h4 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="62-静态资源优化">6.2 静态资源优化<a class="hash-link" href="#62-静态资源优化" title="Direct link to heading"></a></h4><p>静态资源的优化主要分为两个方向:减小资源大小,加快资源加载速度。</p><p><strong>减小资源大小</strong></p><ul><li>Gzip 压缩文件</li><li>JS 文件拆分,动态加载</li></ul><p><strong>加快资源加载速度</strong></p><ul><li>CDNContent Delivery Network</li><li>HTTP/2</li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="63-资源预加载">6.3 资源预加载<a class="hash-link" href="#63-资源预加载" title="Direct link to heading"></a></h4><p><strong>prefetch</strong></p><p>前端可以使用 prefetch 来指定提前获取之后需要使用到的资源,浏览器将会在空闲的时候加载资源,例如:</p><div class="codeBlockContainer_I0IT language-html theme-code-block"><div class="codeBlockContent_wNvx" style="color:#393A34;background-color:#f6f8fa"><pre tabindex="0" class="prism-code language-html codeBlock_jd64 thin-scrollbar"><code class="codeBlockLines_mRuA"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">link</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">rel</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">prefetch</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">href</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">https://hzfe.org/index.js</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">as</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">script</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" title="Copy" class="copyButton_eDfN clean-btn"><span class="copyButtonIcons_W9eQ" aria-hidden="true"><svg class="copyButtonIcon_XEyF" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_i9w9" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div><p><strong>preload</strong></p><p>前端可以使用 preload 来指定提前获取之后需要使用到的资源,浏览器将会立即加载对应资源,在解析到对应资源时即可立即执行,例如:</p><div class="codeBlockContainer_I0IT language-html theme-code-block"><div class="codeBlockContent_wNvx" style="color:#393A34;background-color:#f6f8fa"><pre tabindex="0" class="prism-code language-html codeBlock_jd64 thin-scrollbar"><code class="codeBlockLines_mRuA"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34">&lt;</span><span class="token tag" style="color:#00009f">link</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">rel</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">preload</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">href</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">https://hzfe.org/index.js</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag attr-name" style="color:#00a4db">as</span><span class="token tag attr-value punctuation attr-equals" style="color:#393A34">=</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag attr-value" style="color:#e3116c">script</span><span class="token tag attr-value punctuation" style="color:#393A34">&quot;</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/&gt;</span><br></span></code></pre><button type="button" aria-label="Copy code to clipboard" title="Copy" class="copyButton_eDfN clean-btn"><span class="copyButtonIcons_W9eQ" aria-hidden="true"><svg class="copyButtonIcon_XEyF" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_i9w9" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div><p><strong>quicklink</strong></p><p>quicklink 是 Google 开源的预加载库quicklink 会判断链接进入视口之后在闲时预加载。quicklink 实际上加速的是次级页面。</p><h3 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="7-接口请求优化">7. 接口请求优化<a class="hash-link" href="#7-接口请求优化" title="Direct link to heading"></a></h3><p>浏览器在加载完 HTML 和资源之后,一般需要请求接口获取数据之后才会完整渲染页面,对接口请求进行优化也可加快页面的展示。</p><p><strong>接口合并</strong></p><p>过多的接口请求会影响页面初始化时的渲染过程,可以通过增加一层中间层合并部分请求,达到加速页面展示的目的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="扩展阅读">扩展阅读<a class="hash-link" href="#扩展阅读" title="Direct link to heading"></a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="1-native-相关优化">1. Native 相关优化<a class="hash-link" href="#1-native-相关优化" title="Direct link to heading"></a></h3><p><strong>WebView 容器预加载</strong></p><p>内嵌在 APP 内的网页白屏时间实际还依赖 APP 的 WebView 初始化时间,所以通过对 APP 的 WebView 容器进行优化也可以减少页面的白屏时间,例如预热 WebView即在 APP 打开之后的某一时间点,预先加载一个或多个 WebView 容器,在用户点击打开网页时直接使用预热好的 WebView。</p><p><strong>DNS 优化</strong></p><p>APP 可以在打开之后预解析网页所需的一些域名,在打开网页时即可直接使用 DNS 缓存。</p><p><strong>资源预加载</strong></p><p>APP 可以将网页中所需的资源预加载到本地,在网页请求资源时直接拦截并返回本地文件,即可加快网页加载速度,减少白屏时间。</p><p><strong>接口预加载</strong></p><p>APP 可以通过配置文件获取网页需要提前发起请求的接口,在用户进入页面时同步发起请求,即可在页面载入完成之后直接使用,减少白屏时间。</p><h2 class="anchor anchorWithHideOnScrollNavbar_R0VQ" id="参考资料">参考资料<a class="hash-link" href="#参考资料" title="Direct link to heading"></a></h2><ol><li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigation_timing_API" target="_blank" rel="noopener noreferrer">Navigation Timeing API</a></li></ol></div></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Docs pages navigation"><div class="pagination-nav__item"><a class="pagination-nav__link" href="/awesome-interview/book3/algorithm-binary-tree-k"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">算法:二叉搜索树的第 k 个结点</div></a></div><div class="pagination-nav__item pagination-nav__item--next"><a class="pagination-nav__link" href="/awesome-interview/book4/browser-router"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">浏览器:前端路由实现</div></a></div></nav></div></div><div class="col col--3"><div class="tableOfContents_cNA8 thin-scrollbar theme-doc-toc-desktop"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#回答关键点" class="table-of-contents__link toc-highlight">回答关键点</a></li><li><a href="#知识点深入" class="table-of-contents__link toc-highlight">知识点深入</a><ul><li><a href="#1-前端性能监控指标" class="table-of-contents__link toc-highlight">1. 前端性能监控指标</a></li><li><a href="#2-dns-解析优化" class="table-of-contents__link toc-highlight">2. DNS 解析优化</a><ul><li><a href="#21-dns-预解析" class="table-of-contents__link toc-highlight">2.1 DNS 预解析</a></li><li><a href="#22-域名收敛" class="table-of-contents__link toc-highlight">2.2 域名收敛</a></li></ul></li><li><a href="#3-tcp-连接优化" class="table-of-contents__link toc-highlight">3. TCP 连接优化</a></li><li><a href="#4-请求优化" class="table-of-contents__link toc-highlight">4. 请求优化</a></li><li><a href="#5-页面解析优化" class="table-of-contents__link toc-highlight">5. 页面解析优化</a><ul><li><a href="#51-服务端渲染server-side-rendering" class="table-of-contents__link toc-highlight">5.1 服务端渲染Server-Side Rendering</a></li><li><a href="#52-预渲染" class="table-of-contents__link toc-highlight">5.2 预渲染</a></li></ul></li><li><a href="#6-资源加载优化和页面渲染优化" class="table-of-contents__link toc-highlight">6. 资源加载优化和页面渲染优化</a><ul><li><a href="#61-骨架屏" class="table-of-contents__link toc-highlight">6.1 骨架屏</a></li><li><a href="#62-静态资源优化" class="table-of-contents__link toc-highlight">6.2 静态资源优化</a></li><li><a href="#63-资源预加载" class="table-of-contents__link toc-highlight">6.3 资源预加载</a></li></ul></li><li><a href="#7-接口请求优化" class="table-of-contents__link toc-highlight">7. 接口请求优化</a></li></ul></li><li><a href="#扩展阅读" class="table-of-contents__link toc-highlight">扩展阅读</a><ul><li><a href="#1-native-相关优化" class="table-of-contents__link toc-highlight">1. Native 相关优化</a></li></ul></li><li><a href="#参考资料" class="table-of-contents__link toc-highlight">参考资料</a></li></ul></div></div></div><div class="row"><div class="col"><div class="react-utterences"><div>Loading script...</div></div></div><div class="col col--3"></div></div></div></main></div></div></div>
<script src="/awesome-interview/assets/js/runtime~main.16895322.js"></script>
<script src="/awesome-interview/assets/js/main.a6349f88.js"></script>
</body>
</html>