功能优化是个大课题,涉及到了网络、操作系统、Web等一系列常识,每个环节都能够凭借相关技术⼿段来进行优化,所以系统性地环绕一个web页面从恳求到展示,到交互的全进程每个环节的常识点去学习,去考虑能够每个环节能够做什么优化,然后凭借各类网页目标剖析去衡量页面功能,那么咱们也必定能开宣布功能优异的页面,一起面试的时分,与功能相关的问题也是能手到擒来。

  1. 关于功能优化

什么是前端功能优化?

前端功能是指⻚⾯信息加⼯(⽐如数据展示、动画、操作效率等)的效率。

优化是指凭借相关技术⼿段提⾼这样的效率。

  1. 为什么前端功能如此重要?

咱们知道,现在便是一个“流量为王”的时代,一个网站最重要的的便是用户,有了用户你才干有业务,打比方,你是一个电商网站,那么你必定希望你的用户越多越好,这样才会有更多的人去阅览你的商品,然后在你的网站上花钱,买东西,这样你才干产生收益,但假设你的网站翻开要十几秒,恳求接口要十几秒,那用户还愿意等么?

看一下以下的用户体会图:

Web功能的核算办法与优化计划(一)

国外一些著名公司的调研:

BBC页⾯加载时长每增加1秒,⽤户丢失10%

Pinterest减少页⾯加载时长40%, 提⾼了搜索和注册数15%

DoubleClick发现假如移动⽹站加载时长超越3秒,53%的⽤户会抛弃

所以说,做好功能优化,提高用户体会很重要!

  1. 网页功能目标及影响因素

什么是网页功能目标?

已然前端页面功能如此之重要,也是用户体会的中心衡量标准。咱们想要让网站的功能提升,详细指的是什么?怎样去量化咱们的优化?而功能体会这种东西往往是相对的,所以在讨论功能时,咱们需求有精确的数据,需求有能够丈量的客观的标准来界说,这些标准便是网页功能****目标。

  1. Timing

页面运转的时刻线(核算了从阅览器从网址开端导航到 window.onload事情触发的一系列关键的时刻点):

Web功能的核算办法与优化计划(一)

各个时刻点的意义:

开端导航

  • startTime:即navigationStart, 导航开端的时刻

Prompt for unload(上一个页面卸载)

  • unloadEventStart:表明窗口中的前一个网页(与当时页面同域)unload的时刻戳。假如没有前一个网页,或许前一个网页和当时页面不是同域,则回来值为0。
  • unloadEventEnd:表明当unload事情完毕时的时刻戳。 假如没有前一个网页,或许前一个网页和当时页面不是同域,则回来值为0。

Redirect(重定向)

  • redirectStart:表明当榜首个HTTP重定向开端时的时刻戳。假如没有重定向,或许其间一个重定向不是同域,则回来值为0。
  • redirectEnd:表明当终究一个HTTP重定向完结时,即接收到HTTP呼应的终究一个字节时的时刻戳。假如没有重定向,或许其间一个重定向不是同域,则回来值为0。
  • fetchStart:表明当阅览器准备好运用HTTP恳求获取文档时的时刻戳。这个时刻是产生在检查任何应用程序缓存之前。

DNS (DNS解析)

  • domainLookupStart:表明当DNS域名查询开端时的时刻戳。假如运用了耐久衔接,或许信息存储在缓存或本地资源中(即无DNS查询),则该值将与fetchStart相同。
  • domainLookupEnd:表明当DNS域名查询完结时的时刻戳。假如运用了耐久衔接,或许信息存储在缓存或本地资源中(即无DNS查询),则该值将与fetchStart相同。

TCP 三次握手

  • connectStart:表明HTTP TCP开端树立衔接的时刻戳。假如传输层陈述了一个错误,而且从头开端树立衔接,则给出终究一次树立衔接的开端时刻戳。假如运用耐久衔接,则该值与fetchStart相同。
  • secureConnectionStart:表明当安全衔接握手(HTTPS衔接)开端时的时刻戳。假如没有安全衔接,则回来0。
  • connectEnd:表明HTTP TCP完结树立衔接(完结握手)的时刻戳。假如传输层陈述了一个错误,而且从头开端树立衔接,则给出终究树立衔接的完毕时刻。假如运用耐久衔接,则该值与fetchStart相同。当一切安全衔接握手或SOCKS身份验证都被终止时,该衔接被视为已翻开。

Request(恳求数据)

  • requestStart:表明阅览器发送恳求从服务器或本地缓存中获取实践文档的时刻戳。假如传输层在恳求开端后失败,而且衔接从头翻开,则此特点将被设置为与新恳求对应的时刻。
  • responseStart:表明当阅览器从服务器的缓存或本地资源接收到呼应的榜首个字节时的时刻戳(⾸字节时刻)。
  • responseEnd:表明当阅览器从服务器、缓存或本地资源接收到呼应的终究一个字节时或许当衔接被关闭时(假如这是首要产生的)的时刻戳。

processing, JS 履行、 DOM 解析烘托

  • domInteractive:表明解析器完结解析dom树的时刻戳,这时document.readyState变为’interactive’,相应的readystatechange事情被抛出。这时分只是解析完结DOM树,还没开端加载网页内的资源(可交互时刻 ,测试点 )。
  • domContentLoadedEventStart:表明DOM解析完结后,网页内的资源开端加载的时刻戳。就在解析器发送DOMContentLoaded事情之前。
  • domContentLoadedEventEnd:表明DOM解析完结后,网页内的资源加载完结的时刻戳。即在一切需求尽快履行的脚本(按次序或不按次序)被履行之后。
  • domComplete:表明当解析器完结它在主文档上的作业时,也便是DOM解析完结,且资源也准备就绪的时刻。document.readyState变为’complete’,相应的readystatechange事情被抛出。

load事情开端

  • loadEventStart:表明当为当时文档发送load事情时,也便是load回调函数开端履行的时刻。假如这个事情还没有被发送,它将回来0。

  • loadEventEnd:表明当load事情的回调函数履行完毕的时刻,即加载事情完结时。假如这个事情还没有被发送,或许还没有完结,它将回来0(完全加载时刻,测试点 )。

经过时刻线上的各个时刻点,能够得到的功能目标有:

// performance.timing
console.table([['DNS解析耗时', performance.timing.domainLookupEnd - performance.timing.domainLookupStart],
['TCP衔接耗时', performance.timing.connectEnd - performance.timing.connectStart],
['恳求耗时', performance.timing.responseEnd - performance.timing.requestStart],
['解析DOM树耗时', performance.timing.domComplete - performance.timing.domInteractive],
['domready时刻', performance.timing.domContentLoadedEventEnd - performance.timing.fetchStart],
['onload时刻', performance.timing.loadEventEnd - performance.timing.fetchStart]
]);
  1. 关于Performance API

Performance API 是一组用于衡量 web 应用功能的标准接口,学习链接:developer.mozilla.org/zh-CN/docs/…

常用Performance API

  • performance.timing能够获取网页运转进程中每个时刻点对应的时刻戳(绝对时刻,ms),但却即将废弃

Web功能的核算办法与优化计划(一)

  • performance.getEntries(),以目标数组的办法回来一切资源的数据,包括css,img,script,xmlhttprequest,link等等

Web功能的核算办法与优化计划(一)

  • performance.getEntriesByType( :string),和上面的 getEntries 办法相似,不过是多了一层类型的挑选,常见功能类型能够有 navigation(页面导航)、resource(资源加载)、paint(制作目标)等
// 页面导航时刻
performance.getEntriesByType('navigation')
// 静态资源
performance.getEntriesByType('resource')
// 制作目标
performance.getEntriesByType('paint')
/*需求守时轮询, 才干继续获取功能目标*/
  • performance.getEntriesByName(name: string, type?:string),理,和上面的 getEntries 办法相似,多了一层名字的挑选,也能够传第二个参数再加一层类型的挑选
performance.getEntriesByName('https://i0.hdslb.com/bfs/svg-next/BDC/danmu_square_line/v1.json')
performance.getEntriesByName('https://cloud.tencent.com/developer/api/user/session')
/*需求守时轮询, 才干继续获取功能目标*/
  • performance.now(),回来当时时刻与performance.timing.navigationStart的时刻差
console.log(performance.now())
// 5483324.099999994
  • PerformanceObserver (调查者模式)引荐, 首要用于监测功能度量事情
/* 写法一 */
//直接往 PerformanceObserver() 入参匿名回调函数,成功 new 了一个 PerformanceObserver 类的,名为 observer 的目标
var observer = new PerformanceObserver(function (list, obj) {
  var entries = list.getEntries();
  for (var i = 0; i < entries.length; i++) {
    //处理“navigation”和“resource”事情
  }
});
//调用 observer 目标的 observe() 办法
observer.observe({ entryTypes: ["navigation", "resource"] });
/* 写法二 */
//预先声明回调函数 perf_observer
function perf_observer(list, observer) {
  //处理“navigation”事情
}
//再将其传入 PerformanceObserver(),成功 new 了一个 PerformanceObserver 类的,名为 observer2 的目标
var observer2 = new PerformanceObserver(perf_observer);
//调用 observer2 目标的 observe() 办法
observer2.observe({ entryTypes: ["navigation"] });
// 事例: index-observer.html

实例化PerformanceObserver 目标,observe办法的entryTypes首要功能类型有哪些?

console.log(PerformanceObserver.supportedEntryTypes)
/*
  ['element', 'event', 'first-input', 'largest-contentful-paint', 'layout-shift', 
  'longtask', 'mark', 'measure', 'navigation', 'paint', 'resource', 'visibility-state']
*/

详细每个功能类型的意义:

element 元素加载时刻,实例项是 PerformanceElementTiming 目标。
event 事情推迟,实例项是 PerformanceEventTiming 目标。
first-input 用户榜初次与网站交互(即点击链接、点击按钮或运用自界说的 JavaScript 控件时)到阅览器实践能够呼应该交互的时刻,称之为 First input delay FID
largest-contentful-paint 屏幕上触发的最大制作元素,实例项是 LargestContentfulPaint 目标。
layout-shift 元素移动时分的布局稳定性,实例项是 LayoutShift目标。
long-animation-frame 长动画关键帧。
longtask 长使命实例,归属于 PerformanceLongTaskTiming 目标。
mark 用户自界说的功能符号。实例项是 PerformanceMark 目标。
measure 用户自界说的功能丈量。实例项是 PerformanceMeasure 目标。
navigation 页面导航出去的时刻,实例项是 PerformancePaintTiming 目标。
paint 页面加载时内容烘托的关键时刻(榜初次制作,榜初次有内容的制作,实例项是 PerformancePaintTiming 目标。
resource 页面中资源的加载时刻信息,实例项是 PerformanceResourceTiming 目标。
visibility-state 页面可见性状态更改的时刻,即选项卡何时从前台更改为后台,反之亦然。实例项是 VisibilityStateEntry 目标。
soft-navigation
  1. 用户为导向功能目标介绍

Web功能的核算办法与优化计划(一)

  1. 初次制作(First Paint)和初次内容制作(First Contentful Paint)

初次制作(FP)和初次内容制作(FCP)。在阅览器导航并烘托出像素点后,这些功能目标点立即被符号。 这些点关于用户而言十分重要,直乎感官体会!

初次制作(FP),初次烘托的时刻点。FP和FCP有点像,但FP必定先于FCP产生,例如一个页面加载时,榜首个DOM还没制作完结,可是或许这时页面的背景色彩现已出来了,这时FP目标就被记载下来了。而FCP会在页面制作完榜首个 DOM 内容后记载。

初次内容制作(FCP),初次内容制作的时刻,指页面从开端加载到页面内容的任何部分在屏幕上完结烘托的时刻。

/* PerformanceObserver监控  */
const observer = new PerformanceObserver((list) => {
  const entries = list.getEntries();
  entries.forEach((entry) => {
    if (entry.name === 'first-paint') {
      console.log('FP(初次制作):', entry.startTime);
    } else if (entry.name === 'first-contentful-paint') {
      console.log('FCP(初次内容制作):', entry.startTime);
    }
  });
});
observer.observe({ entryTypes: ['paint'] });
// 事例: index-observer.html
/* performance.getEntriesByName*/
console.log(
    "FP(初次制作):" + performance.getEntriesByName("first-paint")[0].startTime
);
console.log(
    "FCP(初次内容制作):" +
      performance.getEntriesByName("first-contentful-paint")[0].startTime
);
  1. 初次有用制作(First Meaningful Paint)

有用内容,这种一般很难明晰地界定哪些元素的加载是「有用」的(因而现在尚无规范),但关于开发者他们自己而言,他们更知道页面的哪些部分关于用户而言是最为有用的,所以这样的衡量标准更多的时分是把握在开发者手上!

const observer = new PerformanceObserver((list) => {
  const entries = list.getEntries();
  entries.forEach((entry) => {
    if (entry.name === 'https://xxxxxx.xxx.jpg') {
      console.log(entry.startTime);
    } 
  });
});
observer.observe({ entryTypes: ['resource'] }); // 可所以图片、某个Dom元素
  1. 可交互时刻(TTI)

目标丈量页面从开端加载(FCP)到首要子资源完结烘托,并能够快速、可靠地呼应用户输入所需的时刻。堵塞会影响正常可交互的时刻,阅览器主线程一次只能处理一个使命, 假如主线程长时刻被占用,那么可交互时刻也会变长,所以更多的TTI都是产生在主线程处于闲暇的时刻点

杰出的TTI应该控制在5秒以内。

丈量TTI的最佳办法是在网站上运转Lighthouse功能审阅

console.log(performance.timing.domInteractive); // 可交互时刻点
  1. 长使命(Long Task)

阅览器主线程一次只能处理一个使命。 某些状况下,一些使命将或许会花费很长的时刻来履行,继续占用主进程资源,假如这种状况产生了,主线程堵塞,剩余的使命只能在队列中等候。

用户所感知到的或许是输入的推迟,或许是哐当一下全部出现。这些是当今网页糟糕体会的首要来历之一。

Long Tasks API以为任何超越50毫秒的使命(Task)都或许存在潜在的问题,并将这些使命相关信息回调给给前端。

把 long task 时刻界说为 50ms 的首要理论依据是 Chrome 提出的 RAIL 模型,RAIL 以为事情呼应应该在 100ms 以内,翻滚和动画处理应该在 16ms 以内,才干确保好的用户体会,而假如一个 task 履行超越 50ms,则很有或许让体会达不到 RAIL 的标准,故咱们需求重点重视履行时刻超越 50ms 的使命。

const observer = new PerformanceObserver((list) => {
  const entries = list.getEntries();
  entries.forEach((entry) => {
    console.log('Long Task(长使命):', entry);
  });
});
observer.observe({ entryTypes: ['longtask'] });
// 事例: index-longTask.html
  1. Core Web Vitals(中心网页目标)

  2. 什么是Core Web Vitals?

从上一末节学习,能够知道,衡量一个 Web 页面的体会和质量有着十分多的目标,咱们又不是功能专家,所以为了简化场景,帮忙网站专心于最重要的目标,所以在新一代的谷歌阅览器官方推出了中心 Web 目标( LCP ****FID ****CLS ,帮忙咱们能够有更好的聚焦重视度和下降咱们得理解成本,那详细有哪些呢?

Web功能的核算办法与优化计划(一)

  • Largest Contentful Paint (LCP) :最大内容制作, 用于衡量加载功能。 为了供给杰出的用户体会,LCP 应在网页初次开端加载后的 2.5 秒内产生。
  • First Input Delay (FID) :初次输入推迟,用于衡量可交互性。为了供给杰出的用户体会,页面的 FID 应不超越 100 毫秒
  • Cumulative Layout Shift (CLS) :累积布局偏移,用于衡量视觉稳定性。为了供给杰出的用户体会,页面应保持 0.1 或更低的 CLS
  1. LCP: Largest Contentful Paint 最大内容制作

最大内容制作 ( LCP ) 目标会根据页面初次开端加载(FCP)的时刻点来陈述可视区域内可见的最大图画或文本块(Web性能的计算方式与优化方案(一)、、 url ()) 完结烘托的相对时刻。

Web功能的核算办法与优化计划(一)

通常Web 页面是分阶段加载的,所以,页面上最大的元素或许会产生改变。例如上图,在一个带有文本和图画的页面上,阅览器最初或许只是出现文本,而此刻阅览器会分配一个功能类型(entryType)为largest-contentful-paint 的entry。稍后,图画完结加载完结,会分配第二个功能类型(entryType)为largest-contentful-paint 的entry。

丈量办法:

const observer = new PerformanceObserver((list) => {
  const entries = list.getEntries();
  entries.forEach((entry) => {
    console.log('LCP(最大内容制作):', entry.startTime);
  });
});
observer.observe({ entryTypes: ['largest-contentful-paint'] });
// 事例: index-LCP.html
  1. FID:First Input Delay 初次输入推迟

FID( First Input Delay) 丈量从用户榜初次与页面交互,例如当他们单击链接、点按按钮或运用由 JavaScript 驱动的自界说控件,直到阅览器对交互作出呼应,并实践能够开端处理事情处理程序所经过的时刻。

Web功能的核算办法与优化计划(一)

由此图能够看出,FID值越小越好,FID 是产生在 FCP 和 TTI 之间,这个阶段虽然页面现已显现出部分内容,却不具备完全的可交互性。这个阶段用户和页面交互,往往会有较大推迟。如下图所示,阅览器接收到用户输入操作时,主线程正在忙于履行一个 Long Task,只有当这个 Task 履行完结后,阅览器才干呼应用户的输入操作。

丈量办法:


//FID 的核算需求用户实在操作页面,能够创建 PerformanceObserver 目标,监听 *first-input* 事情,
// 监听到 *first-input* 事情后,然后经过事情的开端处理时刻,减去事情的产生时刻,即为 FID。
new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    const delay = entry.processingStart - entry.startTime;
    console.log('FID 初次输入推迟:', delay, entry);
  }
}).observe({entryTypes: ['first-input']});
// 事例: index-FID.html
  1. CLS:Cumulative Layout Shift 累积布局偏移

CLS 丈量整个页面生命周期内产生的一切意外布局偏移量中最大一连串的布局偏移分数。每逢一个可见元素的方位从一个已烘托帧变更到下一个已烘托帧时,就产生了布局偏移 。

简单地说,你是否曾经历过在网上阅览一篇文章,结果页面上的某些内容忽然产生改变?文本在毫无预警的状况下移位,导致您找不到先前阅览的方位。或许更糟糕的状况:您正要点击一个链接或一个按钮,但在你手指落下的瞬间,诶?链接移位了,结果点到了别的东西,这个便是意外偏移。

是怎样核算出来的呢?

Web功能的核算办法与优化计划(一)

布局偏移分数 = 影响比例 * 距离分数
影响比例,比方上图文字块(不稳定元素)占可视区域50%,出现意外布局后,向下偏移20%,那么咱们求并集,50% + 20% = 70%
距离分数,由于向下25%,那么距离分数便是25%
布局偏移分数, 0.7 * 0.25 = 0.1875
70% * 25%

怎样衡量的呢?

    let clsValue = 0;
    let clsEntries = [];
    let sessionValue = 0;
    let sessionEntries = [];
    new PerformanceObserver((entryList) => {
        for (const entry of entryList.getEntries()) {
            // 仅核算最近没有用户输入的布局改变。
            if (!entry.hadRecentInput) {
                const firstSessionEntry = sessionEntries[0];
                const lastSessionEntry = sessionEntries[sessionEntries.length - 1];
            // 假如当时entry产生在前一个entry之后不到 1 秒且榜首个entry之后不到 5 秒,
            // 那么会对entry.value进行累加。不然,从头赋值
            // 注: 咱们把这个时刻区间范围内产生的偏移进行累计,称做一个会话窗口,
            // 对layout-shift收集到的entry进行清洗,得到最大的CLS分数
            if (sessionValue
            && entry.startTime - lastSessionEntry.startTime < 1000
            && entry.startTime - firstSessionEntry.startTime < 5000) {
                sessionValue += entry.value;
                sessionEntries.push(entry);
            } else {
                sessionValue = entry.value;
                sessionEntries = [entry];
            }
            // 假如当时sessionValue大于当时CLS值
            // 更新 CLS。
            if (sessionValue > clsValue) {
                clsValue = sessionValue;
                clsEntries = sessionEntries;
                // Log the updated value (and its entries) to the console. 
                console.log('Cumulative Layout Shift 累积布局偏移:', clsValue, clsEntries)
            }
        }
    }}).observe({ entryTypes: ['layout-shift'] });
// 功能类型layout-shift用于丈量JavaScript 中的布局偏移
// 事例: index-CLS.html
  1. Performance运用及剖析

Performance是Google阅览器自带的页面功能插件,能够记载站点在运转进程中的功能数据,有了这些功能数据,咱们就能够回放整个页面的履行进程,这样就便利咱们来定位和确诊每个时刻段内页面的运转状况,然后有用帮忙咱们找出页面的功能瓶颈。

  1. Performance配置面板

Web功能的核算办法与优化计划(一)

  1. 生成的陈述页

Web功能的核算办法与优化计划(一)

  • 时刻线:概览面板和功能面板都是依赖于时刻线的,假设咱们录制了10000毫秒,那么它们的时刻线便是10000毫秒
  • 概览面板:由页面帧速 (FPS)、CPU 资源耗费、网络恳求流量、V8 内存运用量 (堆内存)几项目标依照时刻次序记载改变的面板,FPS 图表上出现了赤色块,那么就表明赤色块附近烘托出一帧所需时刻过久,帧的烘托时刻过久,就有或许导致页面卡顿,你能够点击该赤色块,那就能够把时刻线聚焦到该问题区域。
  • 功能面板:概览面板是用来定位到或许存在问题的时刻节点,假如需求更进一步的数据,来剖析导致功能问题的原因,需求从功能面板入手。咱们介绍一下有哪些常见功能目标项:

1、Network目标:该目标展示了页面中的每个网络恳求所耗费的时长,并以瀑布流的形式展示。

2、Frames 目标: 也便是阅览器生成每帧的记载,咱们知道页面所展示出来的画面都是由烘托进程一帧一帧烘托出来的,帧记载便是用来记载烘托进程生成一切帧信息,包括了烘托出每帧的时长、每帧的图层结构等信息,你能够点击对应的帧,然后在详细信息面板里边检查详细信息。

3、Timings 目标:用来记载一些关键的时刻节点在何时产生的数据信息,像FP、LCP、DOMContentLoaded、Onload 等事情产生的时刻点,它们体现在在几条不同色彩的竖线上。

4、Main 目标 * *记载烘托主线程的使命履行进程,大部分流程、Jacvascirpt履行、V8垃圾回收、守时设置回调使命等等也是均跑在主线程的, 所以这也是咱们最需求重视的一个目标。

5、Raster 目标: ******组成线程维护了一个光栅化线程池 (Raster),用来让 GPU 履行光栅化的使命,假如你点开 Raster 项,能够看到它维护了多个线程。

6、Compositor 目标:记载了组成线程的使命履行进程

7、GPU 目标: 记载了 GPU 进程主线程的使命履行进程

8、Chrome_ChildIOThread ****目标: 烘托进程维护着一个IO线程,首要用来接收用户输入事情、网络事情、设备相关等事情,假如事情需求烘托主线程来处理,那么 IO 线程还会将这些事情转发给烘托主线程。在功能面板上,Chrome_ChildIOThread 目标对应的便是 IO 线程的使命记载。

9、Layout Shifts,页面加载进程中产生的视觉不稳定性

10、ThreadPoolForegroundWorker、ThreadPoolServiceWorker

11、 …

  1. Main目标剖析

  1. 使命与进程

Main 目标就记载烘托主线上所履行的全部使命,以及每个使命的详细履行进程,所以了解使命和进程在Performance面板的体现是很有必要的。

能够翻开 Chrome 的开发者东西,选择 Performance 标签,然后录制加载阶段使命履行记载,然后重视 Main 目标,进行截取,如下图示:

Web功能的核算办法与优化计划(一)

调查上图,这是对Main目标某个Task的截图, 能够调查到,图上方有一段灰色横条,该灰色横条就对应了一个使命,灰色长条的长度对应了使命的履行时长。可是,烘托主线程上的使命都是比较复杂的,假如只单纯记载使命履行的时长,一般很难定位问题,所以,还需求将使命履行进程中的一些关键的细节记载下来,这些细节便是使命的进程,灰线下面的横条便是一个个进程,相同这些横条的长度就代表这些进程履行的时长。

咱们能够把使命看成是一个 Task 函数,在履行 Task 函数的进程中,它会调用一系列的子函数,这些子函数便是咱们所提到的进程。

  1. 剖析页面加载进程

咱们来剖析一个简单的页面,代码如下所示:

<html>
<head>
    <title>Main目标剖析</title>
    <style>
        .area {
            border: 2px black solid;
        }
        .block {
            background-color: green;
            height: 100px;
            margin: 10px;
            width: 100px;
        }
    </style>
</head>
<body>
    <div class="area">
        <div class="block"></div>
    </div> <br>
    <script> 
        function setBlockArea() { 
            var el = document.createElement('div'); 
            el.setAttribute('class', 'area');
            el.innerHTML = '<div class="block"></div>';
            document.body.append(el); 
        } 
        setBlockArea() 
    </script>
</body>
</html>
// 完结一次制作需求履行
// profiling overhead => 剖析开支
// Schedule Style Recalculation => 调度款式从头核算准备
// Recalculate Style 从头核算款式
// Layout 布局
// Pre-Paint 准备制作
// Paint 制作
// Composite Layers 组成线程进行作业
// Layerize  将显现列表分解成一个组成的图层列表(composited layer list ),用于独立的栅格化(rasterization)和动画制作
// 事例: index-main.html

经过前面几末节,咱们了解了常用网页功能目标、中心功能目标的一些概念,一起了解怎样运用Performance API对各个目标进行功能衡量,咱们知道,假如咱们想终究在阅览器显现咱们所希望的页面和交互作用,那咱们首要需求的是咱们应用代码、资源、脚本一切准备好,才后续页面的烘托和展示,所以缩短加载的时刻,也是咱们功能优化的体现,下一篇环绕着怎样缩短加载时刻手法动身,去了解阅览器作业原理,常用框架优化战略,以及扩展常识PWA的一些应用!