-
Notifications
You must be signed in to change notification settings - Fork 176
/
Copy pathtopic-white-screen-optimization.html
22 lines (22 loc) · 36.5 KB
/
topic-white-screen-optimization.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!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="generator" content="Docusaurus v2.3.1">
<title data-rh="true">如何减少白屏的时间 | HZFE - 剑指前端 Offer</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><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="search" type="application/opensearchdescription+xml" title="HZFE - 剑指前端 Offer" href="/awesome-interview/opensearch.xml">
<link rel="apple-touch-icon" href="/awesome-interview/img/badge.png">
<link rel="manifest" href="/awesome-interview/manifest.json">
<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><link rel="stylesheet" href="/awesome-interview/assets/css/styles.0f62048e.css">
<link rel="preload" href="/awesome-interview/assets/js/runtime~main.a75952d5.js" as="script">
<link rel="preload" href="/awesome-interview/assets/js/main.a5e14537.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" aria-label="Skip to main content"><a class="skipToContent_fXgn" href="#docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="navbar navbar--fixed-top navbarHideable_m1mJ"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><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_ToTc themedImage--light_HNdA"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_ToTc themedImage--dark_i4oU"></div><b class="navbar__title text--truncate">剑指前端 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_nPIU"><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_ZlJk"><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 id="docusaurus_skipToContent_fallback" class="main-wrapper mainWrapper_z2l0 docsWrapper_BCFX"><button aria-label="Scroll back to top" class="clean-btn theme-back-to-top-button backToTopButton_sjWU" type="button"></button><div class="docPage__5DB"><aside class="theme-doc-sidebar-container docSidebarContainer_b6E3"><div class="sidebarViewport_Xe31"><div class="sidebar_njMd sidebarWithHideableNavbar_wUlq"><a tabindex="-1" class="sidebarLogo_isFc" href="/awesome-interview/"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_ToTc themedImage--light_HNdA"><img src="/awesome-interview/img/badge.svg" alt="HZFE" class="themedImage_ToTc themedImage--dark_i4oU"><b>剑指前端 Offer</b></a><nav aria-label="Docs sidebar" class="menu thin-scrollbar menu_SIkG"><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_PEFL"><svg width="20" height="20" aria-hidden="true" class="collapseSidebarButtonIcon_kv0_"><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></div></aside><main class="docMainContainer_gTbr"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_VOVn"><div class="docItemContainer_Djhp"><article><nav class="theme-doc-breadcrumbs breadcrumbsContainer_Z_bl" aria-label="Breadcrumbs"><ul class="breadcrumbs" itemscope="" itemtype="https://schema.org/BreadcrumbList"><li class="breadcrumbs__item"><a aria-label="Home page" class="breadcrumbs__link" href="/awesome-interview/"><svg viewBox="0 0 24 24" class="breadcrumbHomeIcon_YNFT"><path d="M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z" fill="currentColor"></path></svg></a></li><li class="breadcrumbs__item"><span class="breadcrumbs__link">模拟题三</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="name">综合:如何减少白屏的时间</span><meta itemprop="position" content="2"></li></ul></nav><div class="tocCollapsible_ETCw theme-doc-toc-mobile tocMobile_ITEo"><button type="button" class="clean-btn tocCollapsibleButton_TO0P">On this page</button></div><div class="theme-doc-markdown markdown"><h1>如何减少白屏的时间</h1><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="回答关键点">回答关键点<a href="#回答关键点" class="hash-link" aria-label="Direct link to 回答关键点" title="Direct link to 回答关键点"></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_WYt5" id="知识点深入">知识点深入<a href="#知识点深入" class="hash-link" aria-label="Direct link to 知识点深入" title="Direct link to 知识点深入"></a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="1-前端性能监控指标">1. 前端性能监控指标<a href="#1-前端性能监控指标" class="hash-link" aria-label="Direct link to 1. 前端性能监控指标" title="Direct link to 1. 前端性能监控指标"></a></h3><p>性能优化的前置条件是性能有测量标准并可以被监控。常用的性能监控指标有以下几块。</p><p>Navigation Timing API:</p><ul><li>responseStart - fetchStart:收到首字节的耗时</li><li>domContentLoadedEventEnd - fetchStart:HTML 加载完成耗时</li><li>loadEventStart - fetchStart:页面完全加载耗时</li><li>domainLookupEnd - domainLookupStart:DNS 解析耗时</li><li>connectEnd - connectStart:TCP 连接耗时</li><li>responseStart - requestStart:Time to First Byte(TTFB)</li><li>responseEnd - responseStart:数据传输耗时</li><li>domInteractive - responseEnd:DOM 解析耗时</li><li>loadEventStart - domContentLoadedEventEnd:资源加载耗时(页面中同步加载的资源)</li></ul><p>Lighthouse Performance:</p><ul><li>FP(First Paint):首次绘制</li><li>FCP(First Contentful Paint):首次内容绘制</li><li>FMP(First Meaningful Paint):首次有效绘制</li><li>LCP(Largest Contentful Paint):最大可见元素绘制</li><li>TTI(Time to Interactive):可交互时间</li><li>TTFB(Time to First Byte):浏览器接收第一个字节的时间</li></ul><p>除了上面之外,UC 内核也有一套性能监控指标:</p><ul><li>T0:Blink 收到 HTTP Head 的时间。</li><li>T1:首屏有内容显示的时间。</li><li>T2:首屏全部显示出来的时间。</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="2-dns-解析优化">2. DNS 解析优化<a href="#2-dns-解析优化" class="hash-link" aria-label="Direct link to 2. DNS 解析优化" title="Direct link to 2. DNS 解析优化"></a></h3><p>DNS 解析优化是性能优化重要的一环,DNS 的作用是根据域名获取对应的 IP 地址,获取之后后续的 HTTP 流程才能进行下去。</p><p>DNS 解析是一个开销较大的过程,一次 DNS 解析通常需要耗费几十到上百毫秒,而在移动端网络或其他弱网环境下 DNS 解析延迟会更加严重,对 DNS 解析优化则可以减少这一步骤的耗时。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="21-dns-预解析">2.1 DNS 预解析<a href="#21-dns-预解析" class="hash-link" aria-label="Direct link to 2.1 DNS 预解析" title="Direct link to 2.1 DNS 预解析"></a></h4><p>我们可以通过 DNS 预解析的方式提前获取 IP 地址,以缩短后续请求的响应时间。</p><p>前端可以通过 <code>dns-prefetch</code> 预解析,具体方式如下:</p><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34"><</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">"</span><span class="token tag attr-value" style="color:#e3116c">dns-prefetch</span><span class="token tag attr-value punctuation" style="color:#393A34">"</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">"</span><span class="token tag attr-value" style="color:#e3116c">https://hzfe.org/</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" 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_LjdS" 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></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="22-域名收敛">2.2 域名收敛<a href="#22-域名收敛" class="hash-link" aria-label="Direct link to 2.2 域名收敛" title="Direct link to 2.2 域名收敛"></a></h4><p>域名收敛的目的是减少页面中域名的数量,从而减少所需的 DNS 解析次数,最终减少页面的 DNS 解析过程的耗时,加快页面加载速度。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="3-tcp-连接优化">3. TCP 连接优化<a href="#3-tcp-连接优化" class="hash-link" aria-label="Direct link to 3. TCP 连接优化" title="Direct link to 3. TCP 连接优化"></a></h3><p>前端可以通过 <code>preconnect</code> 在请求发送前预先执行一些操作,这些操作包括 DNS 解析,TCP 握手 和 TLS 协商。具体方式如下:</p><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34"><</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">"</span><span class="token tag attr-value" style="color:#e3116c">https://hzfe.org</span><span class="token tag attr-value punctuation" style="color:#393A34">"</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">"</span><span class="token tag attr-value" style="color:#e3116c">preconnect</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" 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_LjdS" 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></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="4-请求优化">4. 请求优化<a href="#4-请求优化" class="hash-link" aria-label="Direct link to 4. 请求优化" title="Direct link to 4. 请求优化"></a></h3><p>通过使用 HTTP/2 协议,可以依赖 HTTP/2 的多路复用、首部压缩、二进制分帧和服务端推送等特性,从而加快整体请求的响应速度,加快页面的渲染展示。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="5-页面解析优化">5. 页面解析优化<a href="#5-页面解析优化" class="hash-link" aria-label="Direct link to 5. 页面解析优化" title="Direct link to 5. 页面解析优化"></a></h3><p>浏览器获取 HTML 文件后,需要对 HTML 解析,然后才能开始渲染页面,这个过程中页面也是处于白屏状态。通过对这一过程进行优化可以加快页面的渲染展示。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="51-服务端渲染server-side-rendering">5.1 服务端渲染(Server-Side Rendering)<a href="#51-服务端渲染server-side-rendering" class="hash-link" aria-label="Direct link to 5.1 服务端渲染(Server-Side Rendering)" title="Direct link to 5.1 服务端渲染(Server-Side Rendering)"></a></h4><p>目前流行的前后端分离的开发模式,由于前端需要等待 JS 文件和接口加载完成之后才能渲染页面,导致白屏时间变长。服务端渲染是指在服务端将页面的渲染逻辑处理好,然后将处理好的 HTML 直接返回给前端展示。这样即可减少页面白屏的时间。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="52-预渲染">5.2 预渲染<a href="#52-预渲染" class="hash-link" aria-label="Direct link to 5.2 预渲染" title="Direct link to 5.2 预渲染"></a></h4><p>除了服务端渲染之外,还可以在前端打包时使用 prerender-spa-plugin 之类的插件进行简单的预渲染,减少页面白屏的时间。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="6-资源加载优化和页面渲染优化">6. 资源加载优化和页面渲染优化<a href="#6-资源加载优化和页面渲染优化" class="hash-link" aria-label="Direct link to 6. 资源加载优化和页面渲染优化" title="Direct link to 6. 资源加载优化和页面渲染优化"></a></h3><p>浏览器解析 HTML 的同时会加载相关的资源,通过对资源的加载过程进行优化也可以减少页面的白屏时间。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="61-骨架屏">6.1 骨架屏<a href="#61-骨架屏" class="hash-link" aria-label="Direct link to 6.1 骨架屏" title="Direct link to 6.1 骨架屏"></a></h4><p>骨架屏是在需要等待加载内容的位置提供一些图形组合占位,提前给用户描述页面的基础结构,等待数据加载完成之后,再替换成实际的内容。</p><p>骨架屏可以在数据加载前,提前渲染页面,缩短白屏时间,提升用户体验。</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="62-静态资源优化">6.2 静态资源优化<a href="#62-静态资源优化" class="hash-link" aria-label="Direct link to 6.2 静态资源优化" title="Direct link to 6.2 静态资源优化"></a></h4><p>静态资源的优化主要分为两个方向:减小资源大小,加快资源加载速度。</p><p><strong>减小资源大小</strong></p><ul><li>Gzip 压缩文件</li><li>JS 文件拆分,动态加载</li></ul><p><strong>加快资源加载速度</strong></p><ul><li>CDN(Content Delivery Network)</li><li>HTTP/2</li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="63-资源预加载">6.3 资源预加载<a href="#63-资源预加载" class="hash-link" aria-label="Direct link to 6.3 资源预加载" title="Direct link to 6.3 资源预加载"></a></h4><p><strong>prefetch</strong></p><p>前端可以使用 prefetch 来指定提前获取之后需要使用到的资源,浏览器将会在空闲的时候加载资源,例如:</p><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34"><</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">"</span><span class="token tag attr-value" style="color:#e3116c">prefetch</span><span class="token tag attr-value punctuation" style="color:#393A34">"</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">"</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">"</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">"</span><span class="token tag attr-value" style="color:#e3116c">script</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" 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_LjdS" 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></div><p><strong>preload</strong></p><p>前端可以使用 preload 来指定提前获取之后需要使用到的资源,浏览器将会立即加载对应资源,在解析到对应资源时即可立即执行,例如:</p><div class="language-html codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-html codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token tag punctuation" style="color:#393A34"><</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">"</span><span class="token tag attr-value" style="color:#e3116c">preload</span><span class="token tag attr-value punctuation" style="color:#393A34">"</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">"</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">"</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">"</span><span class="token tag attr-value" style="color:#e3116c">script</span><span class="token tag attr-value punctuation" style="color:#393A34">"</span><span class="token tag" style="color:#00009f"> </span><span class="token tag punctuation" style="color:#393A34">/></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" 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_LjdS" 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></div><p><strong>quicklink</strong></p><p>quicklink 是 Google 开源的预加载库,quicklink 会判断链接进入视口之后,在闲时预加载。quicklink 实际上加速的是次级页面。</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="7-接口请求优化">7. 接口请求优化<a href="#7-接口请求优化" class="hash-link" aria-label="Direct link to 7. 接口请求优化" title="Direct link to 7. 接口请求优化"></a></h3><p>浏览器在加载完 HTML 和资源之后,一般需要请求接口获取数据之后才会完整渲染页面,对接口请求进行优化也可加快页面的展示。</p><p><strong>接口合并</strong></p><p>过多的接口请求会影响页面初始化时的渲染过程,可以通过增加一层中间层合并部分请求,达到加速页面展示的目的。</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="扩展阅读">扩展阅读<a href="#扩展阅读" class="hash-link" aria-label="Direct link to 扩展阅读" title="Direct link to 扩展阅读"></a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="1-native-相关优化">1. Native 相关优化<a href="#1-native-相关优化" class="hash-link" aria-label="Direct link to 1. Native 相关优化" title="Direct link to 1. Native 相关优化"></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_WYt5" id="参考资料">参考资料<a href="#参考资料" class="hash-link" aria-label="Direct link to 参考资料" title="Direct link to 参考资料"></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"><a class="pagination-nav__link pagination-nav__link--prev" href="/awesome-interview/book3/algorithm-binary-tree-k"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">算法:二叉搜索树的第 k 个结点</div></a><a class="pagination-nav__link pagination-nav__link--next" href="/awesome-interview/book4/browser-router"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">浏览器:前端路由实现</div></a></nav></div></div><div class="col col--3"><div class="tableOfContents_bqdL 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.a75952d5.js"></script>
<script src="/awesome-interview/assets/js/main.a5e14537.js"></script>
</body>
</html>