From fa4ef82a5908e3a148391fc0d025705727b32f1e Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Mon, 17 Aug 2020 12:26:58 -0400 Subject: [PATCH 01/82] starting shell --- lighthouse-core/audits/lazy-third-party.js | 63 +++++++++++++++++++++ lighthouse-core/config/default-config.js | 2 + lighthouse-core/lib/i18n/locales/en-US.json | 12 ++++ lighthouse-core/lib/i18n/locales/en-XL.json | 12 ++++ lighthouse-core/test/results/sample_v2.json | 24 ++++++++ 5 files changed, 113 insertions(+) create mode 100644 lighthouse-core/audits/lazy-third-party.js diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js new file mode 100644 index 000000000000..d2106cfda87f --- /dev/null +++ b/lighthouse-core/audits/lazy-third-party.js @@ -0,0 +1,63 @@ +/** + * @license Copyright 2019 The Lighthouse Authors. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + */ +'use strict'; + +const Audit = require('./audit.js'); +const i18n = require('../lib/i18n/i18n.js'); +const thirdPartyWeb = require('../lib/third-party-web.js'); +const NetworkRecords = require('../computed/network-records.js'); +const MainResource = require('../computed/main-resource.js'); +const MainThreadTasks = require('../computed/main-thread-tasks.js'); + +const UIStrings = { + /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded. This descriptive title is shown to users when no resources have lazy loading alternatives available. */ + title: 'Lazy load third-party resources', + /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded. This descriptive title is shown to users when one or more third-party resources have available lazy loading alternatives. */ + failureTitle: 'Some third-party resources can be lazy loaded', + /** Description of a Lighthouse audit that identifies the third party code on the page that can be lazy loaded. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. */ + description: 'Some third-party resources can be fetched after the page loads. ' + + 'These third-party resources are used by embedded elements which can be replaced by a facade ' + + 'until the user needs to use them. [Learn more]().', + /** Summary text for the result of a Lighthouse audit that identifies the third party code on a web page that can be lazy loaded. This text summarizes the number of distinct lazy loadable entities that were found on the page. */ + displayValue: `{itemCount, plural, + =1 {# lazy loadable resource found} + other {# lazy loadable resources found} + }`, +}; + +const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings); + +/** @typedef {import("third-party-web").IEntity} ThirdPartyEntity */ + +class LazyThirdParty extends Audit { + /** + * @return {LH.Audit.Meta} + */ + static get meta() { + return { + id: 'lazy-third-party', + title: str_(UIStrings.title), + failureTitle: str_(UIStrings.failureTitle), + description: str_(UIStrings.description), + requiredArtifacts: ['traces', 'devtoolsLogs', 'URL'], + }; + } + + /** + * @param {LH.Artifacts} artifacts + * @param {LH.Audit.Context} context + * @return {Promise} + */ + static async audit(artifacts, context) { + return { + score: 1, + notApplicable: true, + }; + } +} + +module.exports = LazyThirdParty; +module.exports.UIStrings = UIStrings; diff --git a/lighthouse-core/config/default-config.js b/lighthouse-core/config/default-config.js index 80468cf491d9..694cd85a064c 100644 --- a/lighthouse-core/config/default-config.js +++ b/lighthouse-core/config/default-config.js @@ -235,6 +235,7 @@ const defaultConfig = { 'timing-budget', 'resource-summary', 'third-party-summary', + 'lazy-third-party', 'largest-contentful-paint-element', 'layout-shift-elements', 'long-tasks', @@ -466,6 +467,7 @@ const defaultConfig = { {id: 'timing-budget', weight: 0, group: 'budgets'}, {id: 'resource-summary', weight: 0, group: 'diagnostics'}, {id: 'third-party-summary', weight: 0, group: 'diagnostics'}, + {id: 'lazy-third-party', weight: 0, group: 'diagnostics'}, {id: 'largest-contentful-paint-element', weight: 0, group: 'diagnostics'}, {id: 'layout-shift-elements', weight: 0, group: 'diagnostics'}, {id: 'uses-passive-event-listeners', weight: 0, group: 'diagnostics'}, diff --git a/lighthouse-core/lib/i18n/locales/en-US.json b/lighthouse-core/lib/i18n/locales/en-US.json index 31cb7b294b67..c9450d97e7c6 100644 --- a/lighthouse-core/lib/i18n/locales/en-US.json +++ b/lighthouse-core/lib/i18n/locales/en-US.json @@ -860,6 +860,18 @@ "lighthouse-core/audits/layout-shift-elements.js | title": { "message": "Avoid large layout shifts" }, + "lighthouse-core/audits/lazy-third-party.js | description": { + "message": "Some third-party resources can be fetched after the page loads. These third-party resources are used by embedded elements which can be replaced by a facade until the user needs to use them. [Learn more]()." + }, + "lighthouse-core/audits/lazy-third-party.js | displayValue": { + "message": "{itemCount, plural,\n =1 {# lazy loadable resource found}\n other {# lazy loadable resources found}\n }" + }, + "lighthouse-core/audits/lazy-third-party.js | failureTitle": { + "message": "Some third-party resources can be lazy loaded" + }, + "lighthouse-core/audits/lazy-third-party.js | title": { + "message": "Lazy load third-party resources" + }, "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": { "message": "A fast page load over a cellular network ensures a good mobile user experience. [Learn more](https://web.dev/load-fast-enough-for-pwa/)." }, diff --git a/lighthouse-core/lib/i18n/locales/en-XL.json b/lighthouse-core/lib/i18n/locales/en-XL.json index 09960d66c632..d44b0c4ae62b 100644 --- a/lighthouse-core/lib/i18n/locales/en-XL.json +++ b/lighthouse-core/lib/i18n/locales/en-XL.json @@ -860,6 +860,18 @@ "lighthouse-core/audits/layout-shift-elements.js | title": { "message": "Âv́ôíd̂ ĺâŕĝé l̂áŷóût́ ŝh́îf́t̂ś" }, + "lighthouse-core/audits/lazy-third-party.js | description": { + "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ćâń b̂é f̂ét̂ćĥéd̂ áf̂t́êŕ t̂h́ê ṕâǵê ĺôád̂ś. T̂h́êśê t́ĥír̂d́-p̂ár̂t́ŷ ŕêśôúr̂ćêś âŕê úŝéd̂ b́ŷ ém̂b́êd́d̂éd̂ él̂ém̂én̂t́ŝ ẃĥíĉh́ ĉán̂ b́ê ŕêṕl̂áĉéd̂ b́ŷ á f̂áĉád̂é ûńt̂íl̂ t́ĥé ûśêŕ n̂éêd́ŝ t́ô úŝé t̂h́êḿ. [L̂éâŕn̂ ḿôŕê]()." + }, + "lighthouse-core/audits/lazy-third-party.js | displayValue": { + "message": "{itemCount, plural,\n =1 {# l̂áẑý l̂óâd́âb́l̂é r̂éŝóûŕĉé f̂óûńd̂}\n other {# ĺâźŷ ĺôád̂áb̂ĺê ŕêśôúr̂ćêś f̂óûńd̂}\n }" + }, + "lighthouse-core/audits/lazy-third-party.js | failureTitle": { + "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ćâń b̂é l̂áẑý l̂óâd́êd́" + }, + "lighthouse-core/audits/lazy-third-party.js | title": { + "message": "L̂áẑý l̂óâd́ t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ" + }, "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": { "message": "Â f́âśt̂ ṕâǵê ĺôád̂ óv̂ér̂ á ĉél̂ĺûĺâŕ n̂ét̂ẃôŕk̂ én̂śûŕêś â ǵôód̂ ḿôb́îĺê úŝér̂ éx̂ṕêŕîén̂ćê. [Ĺêár̂ń m̂ór̂é](https://web.dev/load-fast-enough-for-pwa/)." }, diff --git a/lighthouse-core/test/results/sample_v2.json b/lighthouse-core/test/results/sample_v2.json index 4b9dbedb9fe8..6b0d677f9d4b 100644 --- a/lighthouse-core/test/results/sample_v2.json +++ b/lighthouse-core/test/results/sample_v2.json @@ -1705,6 +1705,13 @@ } } }, + "lazy-third-party": { + "id": "lazy-third-party", + "title": "Lazy load third-party resources", + "description": "Some third-party resources can be fetched after the page loads. These third-party resources are used by embedded elements which can be replaced by a facade until the user needs to use them. [Learn more]().", + "score": null, + "scoreDisplayMode": "notApplicable" + }, "largest-contentful-paint-element": { "id": "largest-contentful-paint-element", "title": "Largest Contentful Paint element", @@ -4418,6 +4425,11 @@ "weight": 0, "group": "diagnostics" }, + { + "id": "lazy-third-party", + "weight": 0, + "group": "diagnostics" + }, { "id": "largest-contentful-paint-element", "weight": 0, @@ -5605,6 +5617,12 @@ "duration": 100, "entryType": "measure" }, + { + "startTime": 0, + "name": "lh:audit:lazy-third-party", + "duration": 100, + "entryType": "measure" + }, { "startTime": 0, "name": "lh:audit:largest-contentful-paint-element", @@ -6862,6 +6880,12 @@ "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": [ "audits[third-party-summary].details.headings[2].text" ], + "lighthouse-core/audits/lazy-third-party.js | title": [ + "audits[lazy-third-party].title" + ], + "lighthouse-core/audits/lazy-third-party.js | description": [ + "audits[lazy-third-party].description" + ], "lighthouse-core/audits/largest-contentful-paint-element.js | title": [ "audits[largest-contentful-paint-element].title" ], From f7a73cacc1cb59305daea4f8e62cef96d3c40f38 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 19 Aug 2020 14:51:05 -0400 Subject: [PATCH 02/82] basic audit --- lighthouse-core/audits/lazy-third-party.js | 130 +++++++++++++++++- lighthouse-core/audits/third-party-summary.js | 4 +- lighthouse-core/lib/third-party-web.js | 27 ++++ package.json | 2 +- yarn.lock | 8 +- 5 files changed, 158 insertions(+), 13 deletions(-) diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js index d2106cfda87f..02c6f9ba3856 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/lazy-third-party.js @@ -6,6 +6,7 @@ 'use strict'; const Audit = require('./audit.js'); +const BootupTime = require('./bootup-time.js'); const i18n = require('../lib/i18n/i18n.js'); const thirdPartyWeb = require('../lib/third-party-web.js'); const NetworkRecords = require('../computed/network-records.js'); @@ -21,16 +22,22 @@ const UIStrings = { description: 'Some third-party resources can be fetched after the page loads. ' + 'These third-party resources are used by embedded elements which can be replaced by a facade ' + 'until the user needs to use them. [Learn more]().', - /** Summary text for the result of a Lighthouse audit that identifies the third party code on a web page that can be lazy loaded. This text summarizes the number of distinct lazy loadable entities that were found on the page. */ + /** Summary text for the result of a Lighthouse audit that identifies the third party code on a web page that can be lazy loaded. This text summarizes the number of lazy loading facades that can be used on the page. */ displayValue: `{itemCount, plural, - =1 {# lazy loadable resource found} - other {# lazy loadable resources found} + =1 {# facade alternative available} + other {# facade alternatives available} }`, + /** Label for a table column that displays the name of a lazy loading facade alternative for a third party resource. */ + columnFacade: 'Facade Alternative', }; const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings); /** @typedef {import("third-party-web").IEntity} ThirdPartyEntity */ +/** @typedef {import("third-party-web").IFacade} ThirdPartyFacade */ + +/** @typedef {{mainThreadTime: number, transferSize: number, blockingTime: number}} Summary */ +/** @typedef {{summary: Summary, urlSummaries: Map}} FacadeSummary */ class LazyThirdParty extends Audit { /** @@ -46,15 +53,128 @@ class LazyThirdParty extends Audit { }; } + /** + * + * @param {Array} networkRecords + * @param {Array} mainThreadTasks + * @param {number} cpuMultiplier + * @param {ThirdPartyEntity | undefined} mainEntity + * @return {Map} + */ + static getSummaries(networkRecords, mainThreadTasks, cpuMultiplier, mainEntity) { + /** @type {Map} */ + const summaries = new Map(); + const defaultStat = {mainThreadTime: 0, blockingTime: 0, transferSize: 0}; + const defaultFacadeStat = {summary: {...defaultStat}, urlSummaries: new Map()}; + + for (const request of networkRecords) { + const entity = thirdPartyWeb.getEntity(request.url); + const facade = thirdPartyWeb.getFirstFacade(request.url); + if (!facade || !entity || mainEntity && entity.name === mainEntity.name) continue; + + const facadeStats = summaries.get(facade) || {...defaultFacadeStat}; + facadeStats.summary.transferSize += request.transferSize; + + const urlStats = facadeStats.urlSummaries.get(request.url) || {...defaultStat}; + urlStats.transferSize += request.transferSize; + facadeStats.urlSummaries.set(request.url, urlStats); + + summaries.set(facade, facadeStats); + } + + const jsURLs = BootupTime.getJavaScriptURLs(networkRecords); + + for (const task of mainThreadTasks) { + const attributableURL = BootupTime.getAttributableURLForTask(task, jsURLs); + const entity = thirdPartyWeb.getEntity(attributableURL); + const facade = thirdPartyWeb.getFirstFacade(attributableURL); + if (!facade || !entity || mainEntity && entity.name === mainEntity.name) continue; + + const facadeStats = summaries.get(facade) || {...defaultFacadeStat}; + const urlStats = facadeStats.urlSummaries.get(attributableURL) || {...defaultStat}; + + const taskDuration = task.selfTime * cpuMultiplier; + facadeStats.summary.mainThreadTime += taskDuration; + urlStats.mainThreadTime += taskDuration; + + // The amount of time spent *blocking* on main thread is the sum of all time longer than 50ms. + // Note that this is not totally equivalent to the TBT definition since it fails to account for FCP, + // but a majority of third-party work occurs after FCP and should yield largely similar numbers. + const blockingTime = Math.max(taskDuration - 50, 0); + facadeStats.summary.blockingTime += blockingTime; + urlStats.blockingTime += blockingTime; + + facadeStats.urlSummaries.set(attributableURL, urlStats); + summaries.set(facade, facadeStats); + } + + return summaries; + } + /** * @param {LH.Artifacts} artifacts * @param {LH.Audit.Context} context * @return {Promise} */ static async audit(artifacts, context) { + const settings = context.settings || {}; + const trace = artifacts.traces[Audit.DEFAULT_PASS]; + const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS]; + const networkRecords = await NetworkRecords.request(devtoolsLog, context); + const mainResource = await MainResource.request({devtoolsLog, URL: artifacts.URL}, context); + const mainEntity = thirdPartyWeb.getEntity(mainResource.url); + const tasks = await MainThreadTasks.request(trace, context); + const multiplier = settings.throttlingMethod === 'simulate' ? + settings.throttling.cpuSlowdownMultiplier : 1; + const summaries = this.getSummaries(networkRecords, tasks, multiplier, mainEntity); + + const summary = {wastedBytes: 0, wastedMs: 0}; + + /** @type LH.Audit.Details.TableItem[] */ + const results = Array.from(summaries) + .map(([facade, facadeStats]) => { + /** @type LH.Audit.Details.TableItem[] */ + const items = []; + for (const [url, urlStats] of Array.from(facadeStats.urlSummaries)) { + items.push({url, ...urlStats}); + } + summary.wastedBytes += facadeStats.summary.transferSize; + summary.wastedMs += facadeStats.summary.blockingTime; + return { + facade: /** @type {LH.Audit.Details.LinkValue} */ { + type: 'link', + text: facade.name, + url: facade.repo, + }, + transferSize: facadeStats.summary.transferSize, + mainThreadTime: facadeStats.summary.mainThreadTime, + blockingTime: facadeStats.summary.blockingTime, + subItems: {type: 'subitems', items}, + }; + }); + + /** @type {LH.Audit.Details.Table['headings']} */ + const headings = [ + {key: 'facade', itemType: 'link', text: str_(UIStrings.columnFacade), + subItemsHeading: {key: 'url', itemType: 'url'}}, + {key: 'transferSize', granularity: 1, itemType: 'bytes', + text: str_(i18n.UIStrings.columnTransferSize), subItemsHeading: {key: 'transferSize'}}, + {key: 'blockingTime', granularity: 1, itemType: 'ms', + text: str_(i18n.UIStrings.columnBlockingTime), subItemsHeading: {key: 'blockingTime'}}, + ]; + + if (!results.length) { + return { + score: 1, + notApplicable: true, + }; + } return { - score: 1, - notApplicable: true, + score: 0, + displayValue: str_(UIStrings.displayValue, { + itemCount: results.length, + }), + details: Audit.makeTableDetails(headings, results, summary), }; } } diff --git a/lighthouse-core/audits/third-party-summary.js b/lighthouse-core/audits/third-party-summary.js index ac8337d79caa..0c5d04a9b593 100644 --- a/lighthouse-core/audits/third-party-summary.js +++ b/lighthouse-core/audits/third-party-summary.js @@ -24,8 +24,6 @@ const UIStrings = { 'your page has primarily finished loading. [Learn more](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/).', /** Label for a table column that displays the name of a third-party provider that potentially links to their website. */ columnThirdParty: 'Third-Party', - /** Label for a table column that displays how much time each row spent blocking other work on the main thread, entries will be the number of milliseconds spent. */ - columnBlockingTime: 'Main-Thread Blocking Time', /** Summary text for the result of a Lighthouse audit that identifies the code on a web page that the user doesn't control (referred to as "third-party code"). This text summarizes the number of distinct entities that were found on the page. */ displayValue: 'Third-party code blocked the main thread for ' + `{timeInMs, number, milliseconds}\xa0ms`, @@ -142,7 +140,7 @@ class ThirdPartySummary extends Audit { {key: 'transferSize', granularity: 1, itemType: 'bytes', text: str_(i18n.UIStrings.columnTransferSize)}, {key: 'blockingTime', granularity: 1, itemType: 'ms', - text: str_(UIStrings.columnBlockingTime)}, + text: str_(i18n.UIStrings.columnBlockingTime)}, ]; if (!results.length) { diff --git a/lighthouse-core/lib/third-party-web.js b/lighthouse-core/lib/third-party-web.js index 4b0cf60797ac..87b547e0fe9c 100644 --- a/lighthouse-core/lib/third-party-web.js +++ b/lighthouse-core/lib/third-party-web.js @@ -8,6 +8,8 @@ const thirdPartyWeb = require('third-party-web/httparchive-nostats-subset'); /** @typedef {import("third-party-web").IEntity} ThirdPartyEntity */ +/** @typedef {import("third-party-web").IProduct} ThirdPartyProduct */ +/** @typedef {import("third-party-web").IFacade} ThirdPartyFacade */ /** * `third-party-web` throws when the passed in string doesn't appear to have any domain whatsoever. @@ -23,6 +25,29 @@ function getEntity(url) { } } +/** + * @param {string} url + * @return {ThirdPartyProduct|undefined} + */ +function getProduct(url) { + try { + return thirdPartyWeb.getProduct(url); + } catch (_) { + return undefined; + } +} + +/** + * The first facade should always be the best one. + * @param {string} url + * @return {ThirdPartyFacade|undefined} + */ +function getFirstFacade(url) { + const product = getProduct(url); + if (!product || !product.facades || !product.facades.length) return undefined; + return product.facades[0]; +} + /** * @param {string} url * @param {ThirdPartyEntity | undefined} mainDocumentEntity @@ -44,6 +69,8 @@ function isFirstParty(url, mainDocumentEntity) { module.exports = { getEntity, + getProduct, + getFirstFacade, isThirdParty, isFirstParty, }; diff --git a/package.json b/package.json index 7ebfa3eecfaf..a4ebbcbbdc4e 100644 --- a/package.json +++ b/package.json @@ -169,7 +169,7 @@ "robots-parser": "^2.0.1", "semver": "^5.3.0", "speedline-core": "^1.4.3", - "third-party-web": "^0.12.1", + "third-party-web": "^0.12.2", "update-notifier": "^4.1.0", "ws": "3.3.2", "yargs": "3.32.0", diff --git a/yarn.lock b/yarn.lock index f54b24f9330a..78574711e06e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8056,10 +8056,10 @@ text-table@~0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= -third-party-web@^0.12.1: - version "0.12.1" - resolved "https://registry.yarnpkg.com/third-party-web/-/third-party-web-0.12.1.tgz#f5b09c1403000b28241f445401c590de52670ab7" - integrity sha512-cdZaoOuZ+lN/lPLYGBlEqgIvtQ/3dt4OcgJ6euTQ/sljUcnWj/RgLIkIdXOWdKXsJav4aPgiygOyJd/Ife813A== +third-party-web@^0.12.2: + version "0.12.2" + resolved "https://registry.yarnpkg.com/third-party-web/-/third-party-web-0.12.2.tgz#6d9ce50ff94d88f7e57998dc4423a5e3e7b6735d" + integrity sha512-LWkBqBnubxaXkKU1eoobaASUxzjqmIGSTrnei5OhrAvBPojq+d21/U5xbwh0LBaeMypCLBhlL3BneyDVjBc//A== throat@^4.0.0: version "4.1.0" From 520411438305bf1750c5acb7dcc1d9f3c14e883f Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 19 Aug 2020 14:51:22 -0400 Subject: [PATCH 03/82] update sample (yikes) --- lighthouse-core/lib/i18n/i18n.js | 2 ++ lighthouse-core/lib/i18n/locales/ar-XB.json | 3 --- lighthouse-core/lib/i18n/locales/ar.json | 3 --- lighthouse-core/lib/i18n/locales/bg.json | 3 --- lighthouse-core/lib/i18n/locales/ca.json | 3 --- lighthouse-core/lib/i18n/locales/cs.json | 3 --- lighthouse-core/lib/i18n/locales/da.json | 3 --- lighthouse-core/lib/i18n/locales/de.json | 3 --- lighthouse-core/lib/i18n/locales/el.json | 3 --- lighthouse-core/lib/i18n/locales/en-GB.json | 3 --- lighthouse-core/lib/i18n/locales/en-US.json | 11 +++++++---- lighthouse-core/lib/i18n/locales/en-XA.json | 3 --- lighthouse-core/lib/i18n/locales/en-XL.json | 11 +++++++---- lighthouse-core/lib/i18n/locales/es-419.json | 3 --- lighthouse-core/lib/i18n/locales/es.json | 3 --- lighthouse-core/lib/i18n/locales/fi.json | 3 --- lighthouse-core/lib/i18n/locales/fil.json | 3 --- lighthouse-core/lib/i18n/locales/fr.json | 3 --- lighthouse-core/lib/i18n/locales/he.json | 3 --- lighthouse-core/lib/i18n/locales/hi.json | 3 --- lighthouse-core/lib/i18n/locales/hr.json | 3 --- lighthouse-core/lib/i18n/locales/hu.json | 3 --- lighthouse-core/lib/i18n/locales/id.json | 3 --- lighthouse-core/lib/i18n/locales/it.json | 3 --- lighthouse-core/lib/i18n/locales/ja.json | 3 --- lighthouse-core/lib/i18n/locales/ko.json | 3 --- lighthouse-core/lib/i18n/locales/lt.json | 3 --- lighthouse-core/lib/i18n/locales/lv.json | 3 --- lighthouse-core/lib/i18n/locales/nl.json | 3 --- lighthouse-core/lib/i18n/locales/no.json | 3 --- lighthouse-core/lib/i18n/locales/pl.json | 3 --- lighthouse-core/lib/i18n/locales/pt-PT.json | 3 --- lighthouse-core/lib/i18n/locales/pt.json | 3 --- lighthouse-core/lib/i18n/locales/ro.json | 3 --- lighthouse-core/lib/i18n/locales/ru.json | 3 --- lighthouse-core/lib/i18n/locales/sk.json | 3 --- lighthouse-core/lib/i18n/locales/sl.json | 3 --- lighthouse-core/lib/i18n/locales/sr-Latn.json | 3 --- lighthouse-core/lib/i18n/locales/sr.json | 3 --- lighthouse-core/lib/i18n/locales/sv.json | 3 --- lighthouse-core/lib/i18n/locales/ta.json | 3 --- lighthouse-core/lib/i18n/locales/te.json | 3 --- lighthouse-core/lib/i18n/locales/th.json | 3 --- lighthouse-core/lib/i18n/locales/tr.json | 3 --- lighthouse-core/lib/i18n/locales/uk.json | 3 --- lighthouse-core/lib/i18n/locales/vi.json | 3 --- lighthouse-core/lib/i18n/locales/zh-HK.json | 3 --- lighthouse-core/lib/i18n/locales/zh-TW.json | 3 --- lighthouse-core/lib/i18n/locales/zh.json | 3 --- lighthouse-core/test/results/sample_v2.json | 2 +- 50 files changed, 17 insertions(+), 147 deletions(-) diff --git a/lighthouse-core/lib/i18n/i18n.js b/lighthouse-core/lib/i18n/i18n.js index 21368f19223b..f0ca68d2631e 100644 --- a/lighthouse-core/lib/i18n/i18n.js +++ b/lighthouse-core/lib/i18n/i18n.js @@ -68,6 +68,8 @@ const UIStrings = { columnWastedBytes: 'Potential Savings', /** Label for a column in a data table; entries will be the number of milliseconds the user could reduce page load by if they implemented the suggestions. */ columnWastedMs: 'Potential Savings', + /** Label for a table column that displays how much time each row spent blocking other work on the main thread, entries will be the number of milliseconds spent. */ + columnBlockingTime: 'Main-Thread Blocking Time', /** Label for a column in a data table; entries will be the number of milliseconds spent during a particular activity. */ columnTimeSpent: 'Time Spent', /** Label for a column in a data table; entries will be the location of a specific line of code in a file, in the format "line: 102". */ diff --git a/lighthouse-core/lib/i18n/locales/ar-XB.json b/lighthouse-core/lib/i18n/locales/ar-XB.json index e20b7fca665a..22f6f98d4053 100644 --- a/lighthouse-core/lib/i18n/locales/ar-XB.json +++ b/lighthouse-core/lib/i18n/locales/ar-XB.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "‏‮Sets‬‏ ‏‮a‬‏ ‏‮theme‬‏ ‏‮color‬‏ ‏‮for‬‏ ‏‮the‬‏ ‏‮address‬‏ ‏‮bar‬‏." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "‏‮Main‬‏-‏‮Thread‬‏ ‏‮Blocking‬‏ ‏‮Time‬‏" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "‏‮Third‬‏-‏‮Party‬‏" }, diff --git a/lighthouse-core/lib/i18n/locales/ar.json b/lighthouse-core/lib/i18n/locales/ar.json index 764a02ea63c0..33e14816f5df 100644 --- a/lighthouse-core/lib/i18n/locales/ar.json +++ b/lighthouse-core/lib/i18n/locales/ar.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "ضبط لون تصميم لشريط العناوين" }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "وقت حظر سلسلة المحادثات الأساسية" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "الجهة الخارجية" }, diff --git a/lighthouse-core/lib/i18n/locales/bg.json b/lighthouse-core/lib/i18n/locales/bg.json index eecdf9912c0e..eb2c444964d4 100644 --- a/lighthouse-core/lib/i18n/locales/bg.json +++ b/lighthouse-core/lib/i18n/locales/bg.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Зададен е тематичен цвят за адресната лента." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Време на блокиране на основната нишка" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Трета страна" }, diff --git a/lighthouse-core/lib/i18n/locales/ca.json b/lighthouse-core/lib/i18n/locales/ca.json index 09fefaf64f0d..a3727bd73e3d 100644 --- a/lighthouse-core/lib/i18n/locales/ca.json +++ b/lighthouse-core/lib/i18n/locales/ca.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Estableix un color temàtic per a la barra d'adreces." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Temps de bloqueig del fil principal" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Tercers" }, diff --git a/lighthouse-core/lib/i18n/locales/cs.json b/lighthouse-core/lib/i18n/locales/cs.json index 7da54b115878..1efff32d54d0 100644 --- a/lighthouse-core/lib/i18n/locales/cs.json +++ b/lighthouse-core/lib/i18n/locales/cs.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Nastavuje barvu motivu adresního řádku." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Doba blokování hlavního podprocesu" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Třetí strana" }, diff --git a/lighthouse-core/lib/i18n/locales/da.json b/lighthouse-core/lib/i18n/locales/da.json index 60ee8a0ea959..83b4a59951a8 100644 --- a/lighthouse-core/lib/i18n/locales/da.json +++ b/lighthouse-core/lib/i18n/locales/da.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Angiver en temafarve til adresselinjen." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Tidspunkt for blokering af den primære tråd" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Tredjepart" }, diff --git a/lighthouse-core/lib/i18n/locales/de.json b/lighthouse-core/lib/i18n/locales/de.json index 4ee1a4408244..e3d94bcf9d4c 100644 --- a/lighthouse-core/lib/i18n/locales/de.json +++ b/lighthouse-core/lib/i18n/locales/de.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Legt eine Designfarbe für die Adressleiste fest." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Dauer der Blockierung des Hauptthreads" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Drittanbieter" }, diff --git a/lighthouse-core/lib/i18n/locales/el.json b/lighthouse-core/lib/i18n/locales/el.json index f8148677280c..31b5576d89c6 100644 --- a/lighthouse-core/lib/i18n/locales/el.json +++ b/lighthouse-core/lib/i18n/locales/el.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Ορίζει ένα χρώμα θέματος για τη γραμμή διευθύνσεων." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Χρόνος αποκλεισμού κύριου νήματος" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Τρίτο μέρος" }, diff --git a/lighthouse-core/lib/i18n/locales/en-GB.json b/lighthouse-core/lib/i18n/locales/en-GB.json index 79a954927ef6..422b35983d8c 100644 --- a/lighthouse-core/lib/i18n/locales/en-GB.json +++ b/lighthouse-core/lib/i18n/locales/en-GB.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Sets a theme colour for the address bar." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Main-thread blocking time" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Third-party" }, diff --git a/lighthouse-core/lib/i18n/locales/en-US.json b/lighthouse-core/lib/i18n/locales/en-US.json index c9450d97e7c6..4203b4c411f2 100644 --- a/lighthouse-core/lib/i18n/locales/en-US.json +++ b/lighthouse-core/lib/i18n/locales/en-US.json @@ -860,11 +860,14 @@ "lighthouse-core/audits/layout-shift-elements.js | title": { "message": "Avoid large layout shifts" }, + "lighthouse-core/audits/lazy-third-party.js | columnFacade": { + "message": "Facade Alternative" + }, "lighthouse-core/audits/lazy-third-party.js | description": { "message": "Some third-party resources can be fetched after the page loads. These third-party resources are used by embedded elements which can be replaced by a facade until the user needs to use them. [Learn more]()." }, "lighthouse-core/audits/lazy-third-party.js | displayValue": { - "message": "{itemCount, plural,\n =1 {# lazy loadable resource found}\n other {# lazy loadable resources found}\n }" + "message": "{itemCount, plural,\n =1 {# facade alternative available}\n other {# facade alternatives available}\n }" }, "lighthouse-core/audits/lazy-third-party.js | failureTitle": { "message": "Some third-party resources can be lazy loaded" @@ -1265,9 +1268,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Sets a theme color for the address bar." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Main-Thread Blocking Time" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Third-Party" }, @@ -1532,6 +1532,9 @@ "lighthouse-core/gather/gather-runner.js | warningTimeout": { "message": "The page loaded too slowly to finish within the time limit. Results may be incomplete." }, + "lighthouse-core/lib/i18n/i18n.js | columnBlockingTime": { + "message": "Main-Thread Blocking Time" + }, "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": { "message": "Cache TTL" }, diff --git a/lighthouse-core/lib/i18n/locales/en-XA.json b/lighthouse-core/lib/i18n/locales/en-XA.json index fbaf8f2ad59d..b97174a5a9d0 100644 --- a/lighthouse-core/lib/i18n/locales/en-XA.json +++ b/lighthouse-core/lib/i18n/locales/en-XA.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "[Šéţš å ţĥémé çöļöŕ ƒöŕ ţĥé åððŕéšš бåŕ. one two three four five six seven eight]" }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "[Måîñ-Ţĥŕéåð Бļöçķîñĝ Ţîmé one two three]" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "[Ţĥîŕð-Þåŕţý one two]" }, diff --git a/lighthouse-core/lib/i18n/locales/en-XL.json b/lighthouse-core/lib/i18n/locales/en-XL.json index d44b0c4ae62b..f41e71a26462 100644 --- a/lighthouse-core/lib/i18n/locales/en-XL.json +++ b/lighthouse-core/lib/i18n/locales/en-XL.json @@ -860,11 +860,14 @@ "lighthouse-core/audits/layout-shift-elements.js | title": { "message": "Âv́ôíd̂ ĺâŕĝé l̂áŷóût́ ŝh́îf́t̂ś" }, + "lighthouse-core/audits/lazy-third-party.js | columnFacade": { + "message": "F̂áĉád̂é Âĺt̂ér̂ńât́îv́ê" + }, "lighthouse-core/audits/lazy-third-party.js | description": { "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ćâń b̂é f̂ét̂ćĥéd̂ áf̂t́êŕ t̂h́ê ṕâǵê ĺôád̂ś. T̂h́êśê t́ĥír̂d́-p̂ár̂t́ŷ ŕêśôúr̂ćêś âŕê úŝéd̂ b́ŷ ém̂b́êd́d̂éd̂ él̂ém̂én̂t́ŝ ẃĥíĉh́ ĉán̂ b́ê ŕêṕl̂áĉéd̂ b́ŷ á f̂áĉád̂é ûńt̂íl̂ t́ĥé ûśêŕ n̂éêd́ŝ t́ô úŝé t̂h́êḿ. [L̂éâŕn̂ ḿôŕê]()." }, "lighthouse-core/audits/lazy-third-party.js | displayValue": { - "message": "{itemCount, plural,\n =1 {# l̂áẑý l̂óâd́âb́l̂é r̂éŝóûŕĉé f̂óûńd̂}\n other {# ĺâźŷ ĺôád̂áb̂ĺê ŕêśôúr̂ćêś f̂óûńd̂}\n }" + "message": "{itemCount, plural,\n =1 {# f̂áĉád̂é âĺt̂ér̂ńât́îv́ê áv̂áîĺâb́l̂é}\n other {# f̂áĉád̂é âĺt̂ér̂ńât́îv́êś âv́âíl̂áb̂ĺê}\n }" }, "lighthouse-core/audits/lazy-third-party.js | failureTitle": { "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ćâń b̂é l̂áẑý l̂óâd́êd́" @@ -1265,9 +1268,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Ŝét̂ś â t́ĥém̂é ĉól̂ór̂ f́ôŕ t̂h́ê ád̂d́r̂éŝś b̂ár̂." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "M̂áîń-T̂h́r̂éâd́ B̂ĺôćk̂ín̂ǵ T̂ím̂é" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "T̂h́îŕd̂-Ṕâŕt̂ý" }, @@ -1532,6 +1532,9 @@ "lighthouse-core/gather/gather-runner.js | warningTimeout": { "message": "T̂h́ê ṕâǵê ĺôád̂éd̂ t́ôó ŝĺôẃl̂ý t̂ó f̂ín̂íŝh́ ŵít̂h́îń t̂h́ê t́îḿê ĺîḿît́. R̂éŝúl̂t́ŝ ḿâý b̂é îńĉóm̂ṕl̂ét̂é." }, + "lighthouse-core/lib/i18n/i18n.js | columnBlockingTime": { + "message": "M̂áîń-T̂h́r̂éâd́ B̂ĺôćk̂ín̂ǵ T̂ím̂é" + }, "lighthouse-core/lib/i18n/i18n.js | columnCacheTTL": { "message": "Ĉáĉh́ê T́T̂Ĺ" }, diff --git a/lighthouse-core/lib/i18n/locales/es-419.json b/lighthouse-core/lib/i18n/locales/es-419.json index 9b3d5f5b9823..ceb1decc3c9d 100644 --- a/lighthouse-core/lib/i18n/locales/es-419.json +++ b/lighthouse-core/lib/i18n/locales/es-419.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Establece un color de tema para la barra de direcciones." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Tiempo de bloqueo del subproceso principal" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Terceros" }, diff --git a/lighthouse-core/lib/i18n/locales/es.json b/lighthouse-core/lib/i18n/locales/es.json index 332b6dc65129..e74efd0b6bf1 100644 --- a/lighthouse-core/lib/i18n/locales/es.json +++ b/lighthouse-core/lib/i18n/locales/es.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Establece un color personalizado en la barra de direcciones." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Tiempo de bloqueo del hilo principal" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Proveedor externo" }, diff --git a/lighthouse-core/lib/i18n/locales/fi.json b/lighthouse-core/lib/i18n/locales/fi.json index 8dd61d85c249..639a643ac586 100644 --- a/lighthouse-core/lib/i18n/locales/fi.json +++ b/lighthouse-core/lib/i18n/locales/fi.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Asettaa osoitepalkin teemavärin" }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Pääsäikeen estoaika" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Kolmas osapuoli" }, diff --git a/lighthouse-core/lib/i18n/locales/fil.json b/lighthouse-core/lib/i18n/locales/fil.json index fe01dbcefbe5..b18468a148c7 100644 --- a/lighthouse-core/lib/i18n/locales/fil.json +++ b/lighthouse-core/lib/i18n/locales/fil.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Nagtatakda ng kulay ng tema para sa address bar." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Oras ng Pag-block ng Pangunahing Thread" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Third-Party" }, diff --git a/lighthouse-core/lib/i18n/locales/fr.json b/lighthouse-core/lib/i18n/locales/fr.json index 1b60a55d6f83..2b2efcd51191 100644 --- a/lighthouse-core/lib/i18n/locales/fr.json +++ b/lighthouse-core/lib/i18n/locales/fr.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Une couleur de thème est configurée pour la barre d'adresse." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Durée de blocage du thread principal" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Tiers" }, diff --git a/lighthouse-core/lib/i18n/locales/he.json b/lighthouse-core/lib/i18n/locales/he.json index c88e72ac00ef..931f5bd07f78 100644 --- a/lighthouse-core/lib/i18n/locales/he.json +++ b/lighthouse-core/lib/i18n/locales/he.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "מגדיר צבע עיצוב עבור סרגל הכתובות." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "משך החסימה של התהליכון הראשי" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "צד שלישי" }, diff --git a/lighthouse-core/lib/i18n/locales/hi.json b/lighthouse-core/lib/i18n/locales/hi.json index 2916d912785d..dfe818981001 100644 --- a/lighthouse-core/lib/i18n/locales/hi.json +++ b/lighthouse-core/lib/i18n/locales/hi.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "'पता बार' के लिए थीम का रंग सेट करता है." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "मुख्य थ्रेड ब्लॉक होने का समय" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "तीसरा पक्ष" }, diff --git a/lighthouse-core/lib/i18n/locales/hr.json b/lighthouse-core/lib/i18n/locales/hr.json index fcfcc8413d1d..41c3d46c255c 100644 --- a/lighthouse-core/lib/i18n/locales/hr.json +++ b/lighthouse-core/lib/i18n/locales/hr.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Postavlja boju teme za adresnu traku." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Vrijeme blokiranja glavne niti" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Treća strana" }, diff --git a/lighthouse-core/lib/i18n/locales/hu.json b/lighthouse-core/lib/i18n/locales/hu.json index 9181065d3037..6b44320220da 100644 --- a/lighthouse-core/lib/i18n/locales/hu.json +++ b/lighthouse-core/lib/i18n/locales/hu.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "A téma színét állítja be a címsávon." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Fő szál akadályozásának időtartama" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Harmadik fél" }, diff --git a/lighthouse-core/lib/i18n/locales/id.json b/lighthouse-core/lib/i18n/locales/id.json index 01be9597cc27..0ff57fe718c5 100644 --- a/lighthouse-core/lib/i18n/locales/id.json +++ b/lighthouse-core/lib/i18n/locales/id.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Menyetel warna tema untuk kolom URL." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Waktu Pemblokiran Thread Utama" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Pihak Ketiga" }, diff --git a/lighthouse-core/lib/i18n/locales/it.json b/lighthouse-core/lib/i18n/locales/it.json index a6d387119b09..b35635864c4f 100644 --- a/lighthouse-core/lib/i18n/locales/it.json +++ b/lighthouse-core/lib/i18n/locales/it.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Imposta un colore tema per la barra degli indirizzi." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Durata blocco thread principale" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Terza parte" }, diff --git a/lighthouse-core/lib/i18n/locales/ja.json b/lighthouse-core/lib/i18n/locales/ja.json index 5274f14a813a..a79053d3e1b0 100644 --- a/lighthouse-core/lib/i18n/locales/ja.json +++ b/lighthouse-core/lib/i18n/locales/ja.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "アドレスバーにテーマの色が設定されています。" }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "メインスレッドのブロック時間" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "第三者" }, diff --git a/lighthouse-core/lib/i18n/locales/ko.json b/lighthouse-core/lib/i18n/locales/ko.json index 124366205452..884b9e224fbd 100644 --- a/lighthouse-core/lib/i18n/locales/ko.json +++ b/lighthouse-core/lib/i18n/locales/ko.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "주소 표시줄의 테마 색상을 설정함" }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "기본 스레드 차단 시간" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "타사" }, diff --git a/lighthouse-core/lib/i18n/locales/lt.json b/lighthouse-core/lib/i18n/locales/lt.json index c7c950181f3c..67af7de6fd05 100644 --- a/lighthouse-core/lib/i18n/locales/lt.json +++ b/lighthouse-core/lib/i18n/locales/lt.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Nustatoma adreso juostos temos spalva." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Pagrindinės grupės blokavimo laikas" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Trečioji šalis" }, diff --git a/lighthouse-core/lib/i18n/locales/lv.json b/lighthouse-core/lib/i18n/locales/lv.json index dc9fb92caa10..72e8ad175620 100644 --- a/lighthouse-core/lib/i18n/locales/lv.json +++ b/lighthouse-core/lib/i18n/locales/lv.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Lapa iestata adreses joslas motīva krāsu." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Galvenā pavediena bloķēšanas laiks" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Trešā puse" }, diff --git a/lighthouse-core/lib/i18n/locales/nl.json b/lighthouse-core/lib/i18n/locales/nl.json index 9c5a40769354..d75c9b346f3d 100644 --- a/lighthouse-core/lib/i18n/locales/nl.json +++ b/lighthouse-core/lib/i18n/locales/nl.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Hiermee wordt een themakleur voor de adresbalk ingesteld." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Tijd dat primaire thread is geblokkeerd" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Derden" }, diff --git a/lighthouse-core/lib/i18n/locales/no.json b/lighthouse-core/lib/i18n/locales/no.json index 177a9b4482f7..831ee90e883b 100644 --- a/lighthouse-core/lib/i18n/locales/no.json +++ b/lighthouse-core/lib/i18n/locales/no.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Angir en temafarge for adressefeltet." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Blokkeringstid i hovedtråden" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Tredjepart" }, diff --git a/lighthouse-core/lib/i18n/locales/pl.json b/lighthouse-core/lib/i18n/locales/pl.json index 875becf92357..20aab6b5fa0f 100644 --- a/lighthouse-core/lib/i18n/locales/pl.json +++ b/lighthouse-core/lib/i18n/locales/pl.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Ustawia motyw kolorystyczny paska adresu." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Czas blokowania głównego wątku" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Dostawca zewnętrzny" }, diff --git a/lighthouse-core/lib/i18n/locales/pt-PT.json b/lighthouse-core/lib/i18n/locales/pt-PT.json index 5b1ebc21def3..2ba03ac88c45 100644 --- a/lighthouse-core/lib/i18n/locales/pt-PT.json +++ b/lighthouse-core/lib/i18n/locales/pt-PT.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Define uma cor do tema para a barra de endereço" }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Tempo de bloqueio do thread principal" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Terceiros" }, diff --git a/lighthouse-core/lib/i18n/locales/pt.json b/lighthouse-core/lib/i18n/locales/pt.json index e281cfa4d01b..727dced384b9 100644 --- a/lighthouse-core/lib/i18n/locales/pt.json +++ b/lighthouse-core/lib/i18n/locales/pt.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Foi definida uma cor de tema para a barra de endereços." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Tempo de bloqueio da linha de execução principal" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Terceiros" }, diff --git a/lighthouse-core/lib/i18n/locales/ro.json b/lighthouse-core/lib/i18n/locales/ro.json index 8fa5ae2b53ef..521555411e95 100644 --- a/lighthouse-core/lib/i18n/locales/ro.json +++ b/lighthouse-core/lib/i18n/locales/ro.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Setează o culoare tematică pentru bara de adrese." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Timpul de blocare a firului principal" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Terță parte" }, diff --git a/lighthouse-core/lib/i18n/locales/ru.json b/lighthouse-core/lib/i18n/locales/ru.json index 9795026ae899..402ba60e6383 100644 --- a/lighthouse-core/lib/i18n/locales/ru.json +++ b/lighthouse-core/lib/i18n/locales/ru.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Изменяет цвет адресной строки в соответствии с темой" }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Время блокировки основного потока" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Сторонний поставщик" }, diff --git a/lighthouse-core/lib/i18n/locales/sk.json b/lighthouse-core/lib/i18n/locales/sk.json index 1d0bf272ce2a..764e4eb8b677 100644 --- a/lighthouse-core/lib/i18n/locales/sk.json +++ b/lighthouse-core/lib/i18n/locales/sk.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Nastavuje farbu motívu pre panel s adresou." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Čas blokovania hlavného vlákna" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Tretia strana" }, diff --git a/lighthouse-core/lib/i18n/locales/sl.json b/lighthouse-core/lib/i18n/locales/sl.json index 1575521970c2..724207672c06 100644 --- a/lighthouse-core/lib/i18n/locales/sl.json +++ b/lighthouse-core/lib/i18n/locales/sl.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Nastavi barvo teme za naslovno vrstico." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Čas blokiranja glavne niti" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Drugi ponudniki" }, diff --git a/lighthouse-core/lib/i18n/locales/sr-Latn.json b/lighthouse-core/lib/i18n/locales/sr-Latn.json index 153c864ffa21..4ee7a00381a9 100644 --- a/lighthouse-core/lib/i18n/locales/sr-Latn.json +++ b/lighthouse-core/lib/i18n/locales/sr-Latn.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Podešava boju teme za traku za adresu." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Period blokiranja glavne niti" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Nezavisni dobavljač" }, diff --git a/lighthouse-core/lib/i18n/locales/sr.json b/lighthouse-core/lib/i18n/locales/sr.json index c6460a758830..f80acf90d874 100644 --- a/lighthouse-core/lib/i18n/locales/sr.json +++ b/lighthouse-core/lib/i18n/locales/sr.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Подешава боју теме за траку за адресу." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Период блокирања главне нити" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Независни добављач" }, diff --git a/lighthouse-core/lib/i18n/locales/sv.json b/lighthouse-core/lib/i18n/locales/sv.json index 07ab50bae08e..b550b6a62cf5 100644 --- a/lighthouse-core/lib/i18n/locales/sv.json +++ b/lighthouse-core/lib/i18n/locales/sv.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Anger ett färgtema för adressfältet." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Tidsåtgång för blockering av huvudtråd" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Tredje part" }, diff --git a/lighthouse-core/lib/i18n/locales/ta.json b/lighthouse-core/lib/i18n/locales/ta.json index 132bc42f3797..8e4fba5458e4 100644 --- a/lighthouse-core/lib/i18n/locales/ta.json +++ b/lighthouse-core/lib/i18n/locales/ta.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "முகவரிப் பட்டிக்கான தீம் வண்ணத்தை அமைக்கும்." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "முக்கியத் தொடரிழையில் தடுப்பதற்குச் செலவிட்ட நேரம்" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "மூன்றாம் தரப்பு" }, diff --git a/lighthouse-core/lib/i18n/locales/te.json b/lighthouse-core/lib/i18n/locales/te.json index f16001277ad8..a1e98698e611 100644 --- a/lighthouse-core/lib/i18n/locales/te.json +++ b/lighthouse-core/lib/i18n/locales/te.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "చిరునామా బార్ కోసం థీమ్ రంగు సెట్ చేయబడింది." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "ప్రధాన థ్రెడ్ బ్లాక్ చేయబడే సమయం" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "మూడవ పక్షం" }, diff --git a/lighthouse-core/lib/i18n/locales/th.json b/lighthouse-core/lib/i18n/locales/th.json index 28dceb39a451..c32d49a5108c 100644 --- a/lighthouse-core/lib/i18n/locales/th.json +++ b/lighthouse-core/lib/i18n/locales/th.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "กำหนดสีธีมของแถบที่อยู่" }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "เวลาในการบล็อกเทรดหลัก" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "บุคคลที่สาม" }, diff --git a/lighthouse-core/lib/i18n/locales/tr.json b/lighthouse-core/lib/i18n/locales/tr.json index 90550de9c296..bef2a2c43890 100644 --- a/lighthouse-core/lib/i18n/locales/tr.json +++ b/lighthouse-core/lib/i18n/locales/tr.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Adres çubuğu için tema rengi ayarlar." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Ana İleti Dizisi Engelleme Süresi" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Üçüncü Taraf" }, diff --git a/lighthouse-core/lib/i18n/locales/uk.json b/lighthouse-core/lib/i18n/locales/uk.json index 0c42784f0ede..f13d678068ec 100644 --- a/lighthouse-core/lib/i18n/locales/uk.json +++ b/lighthouse-core/lib/i18n/locales/uk.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Змінює колір адресного рядка відповідно до теми." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Час блокування основного ланцюжка" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Сторонні розробники" }, diff --git a/lighthouse-core/lib/i18n/locales/vi.json b/lighthouse-core/lib/i18n/locales/vi.json index dfa7ab10480c..a70153059358 100644 --- a/lighthouse-core/lib/i18n/locales/vi.json +++ b/lighthouse-core/lib/i18n/locales/vi.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Đặt màu giao diện cho thanh địa chỉ." }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "Thời gian chặn chuỗi chính" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Bên thứ ba" }, diff --git a/lighthouse-core/lib/i18n/locales/zh-HK.json b/lighthouse-core/lib/i18n/locales/zh-HK.json index 9500352019cf..f7f7153237b4 100644 --- a/lighthouse-core/lib/i18n/locales/zh-HK.json +++ b/lighthouse-core/lib/i18n/locales/zh-HK.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "設定網址列的主題顏色。" }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "主要執行緒封鎖時間" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "第三方" }, diff --git a/lighthouse-core/lib/i18n/locales/zh-TW.json b/lighthouse-core/lib/i18n/locales/zh-TW.json index f7a24da4b18b..95ea730ad550 100644 --- a/lighthouse-core/lib/i18n/locales/zh-TW.json +++ b/lighthouse-core/lib/i18n/locales/zh-TW.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "設定網址列的主題顏色。" }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "主要執行緒封鎖時間" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "第三方" }, diff --git a/lighthouse-core/lib/i18n/locales/zh.json b/lighthouse-core/lib/i18n/locales/zh.json index f401e94c1f4d..5a9fa83bdead 100644 --- a/lighthouse-core/lib/i18n/locales/zh.json +++ b/lighthouse-core/lib/i18n/locales/zh.json @@ -1226,9 +1226,6 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "为地址栏设置主题背景颜色。" }, - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": { - "message": "主线程拦截时间" - }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "第三方" }, diff --git a/lighthouse-core/test/results/sample_v2.json b/lighthouse-core/test/results/sample_v2.json index 6b0d677f9d4b..74dcf0ef13f7 100644 --- a/lighthouse-core/test/results/sample_v2.json +++ b/lighthouse-core/test/results/sample_v2.json @@ -6877,7 +6877,7 @@ "lighthouse-core/audits/third-party-summary.js | columnThirdParty": [ "audits[third-party-summary].details.headings[0].text" ], - "lighthouse-core/audits/third-party-summary.js | columnBlockingTime": [ + "lighthouse-core/lib/i18n/i18n.js | columnBlockingTime": [ "audits[third-party-summary].details.headings[2].text" ], "lighthouse-core/audits/lazy-third-party.js | title": [ From 4e68d605df199dde90d0bb78f32d6c737b88a6b8 Mon Sep 17 00:00:00 2001 From: Adam Raine <6752989+adamraine@users.noreply.github.com> Date: Wed, 19 Aug 2020 16:56:09 -0400 Subject: [PATCH 04/82] license Co-authored-by: Connor Clark --- lighthouse-core/audits/lazy-third-party.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js index 02c6f9ba3856..b3be16bb80b2 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/lazy-third-party.js @@ -1,5 +1,5 @@ /** - * @license Copyright 2019 The Lighthouse Authors. All Rights Reserved. + * @license Copyright 2020 The Lighthouse Authors. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ From 3740ba1bc885d19eb77c89a33a3907b202aaac2c Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Thu, 20 Aug 2020 12:41:29 -0400 Subject: [PATCH 05/82] remove code duplication --- lighthouse-core/audits/lazy-third-party.js | 96 +++++++--------------- 1 file changed, 31 insertions(+), 65 deletions(-) diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js index 02c6f9ba3856..7b609ee7e102 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/lazy-third-party.js @@ -6,12 +6,12 @@ 'use strict'; const Audit = require('./audit.js'); -const BootupTime = require('./bootup-time.js'); const i18n = require('../lib/i18n/i18n.js'); const thirdPartyWeb = require('../lib/third-party-web.js'); const NetworkRecords = require('../computed/network-records.js'); const MainResource = require('../computed/main-resource.js'); const MainThreadTasks = require('../computed/main-thread-tasks.js'); +const ThirdPartySummary = require('./third-party-summary.js'); const UIStrings = { /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded. This descriptive title is shown to users when no resources have lazy loading alternatives available. */ @@ -29,6 +29,8 @@ const UIStrings = { }`, /** Label for a table column that displays the name of a lazy loading facade alternative for a third party resource. */ columnFacade: 'Facade Alternative', + /** Label for a table column that displays the name of the third party product that a URL is used for. */ + columnProduct: 'Product', }; const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings); @@ -36,8 +38,7 @@ const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings); /** @typedef {import("third-party-web").IEntity} ThirdPartyEntity */ /** @typedef {import("third-party-web").IFacade} ThirdPartyFacade */ -/** @typedef {{mainThreadTime: number, transferSize: number, blockingTime: number}} Summary */ -/** @typedef {{summary: Summary, urlSummaries: Map}} FacadeSummary */ +/** @typedef {{facade: ThirdPartyFacade, urlSummaries: Map}} FacadeSummary */ class LazyThirdParty extends Audit { /** @@ -54,61 +55,25 @@ class LazyThirdParty extends Audit { } /** - * - * @param {Array} networkRecords - * @param {Array} mainThreadTasks - * @param {number} cpuMultiplier + * @param {Map} + * @return {Map} */ - static getSummaries(networkRecords, mainThreadTasks, cpuMultiplier, mainEntity) { - /** @type {Map} */ - const summaries = new Map(); - const defaultStat = {mainThreadTime: 0, blockingTime: 0, transferSize: 0}; - const defaultFacadeStat = {summary: {...defaultStat}, urlSummaries: new Map()}; - - for (const request of networkRecords) { - const entity = thirdPartyWeb.getEntity(request.url); - const facade = thirdPartyWeb.getFirstFacade(request.url); - if (!facade || !entity || mainEntity && entity.name === mainEntity.name) continue; - - const facadeStats = summaries.get(facade) || {...defaultFacadeStat}; - facadeStats.summary.transferSize += request.transferSize; - - const urlStats = facadeStats.urlSummaries.get(request.url) || {...defaultStat}; - urlStats.transferSize += request.transferSize; - facadeStats.urlSummaries.set(request.url, urlStats); - - summaries.set(facade, facadeStats); - } + static getFacadeSummaries(byURL, mainEntity) { + /** @type {Map} */ + const facadeSummaries = new Map(); - const jsURLs = BootupTime.getJavaScriptURLs(networkRecords); - - for (const task of mainThreadTasks) { - const attributableURL = BootupTime.getAttributableURLForTask(task, jsURLs); - const entity = thirdPartyWeb.getEntity(attributableURL); - const facade = thirdPartyWeb.getFirstFacade(attributableURL); + for (const [url, urlSummary] of byURL) { + const entity = thirdPartyWeb.getEntity(url); + const facade = thirdPartyWeb.getFirstFacade(url); if (!facade || !entity || mainEntity && entity.name === mainEntity.name) continue; - const facadeStats = summaries.get(facade) || {...defaultFacadeStat}; - const urlStats = facadeStats.urlSummaries.get(attributableURL) || {...defaultStat}; - - const taskDuration = task.selfTime * cpuMultiplier; - facadeStats.summary.mainThreadTime += taskDuration; - urlStats.mainThreadTime += taskDuration; - - // The amount of time spent *blocking* on main thread is the sum of all time longer than 50ms. - // Note that this is not totally equivalent to the TBT definition since it fails to account for FCP, - // but a majority of third-party work occurs after FCP and should yield largely similar numbers. - const blockingTime = Math.max(taskDuration - 50, 0); - facadeStats.summary.blockingTime += blockingTime; - urlStats.blockingTime += blockingTime; - - facadeStats.urlSummaries.set(attributableURL, urlStats); - summaries.set(facade, facadeStats); + const facadeSummary = facadeSummaries.get(facade.name) || {facade, urlSummaries: new Map()}; + facadeSummary.urlSummaries.set(url, urlSummary); + facadeSummaries.set(facade.name, facadeSummary); } - return summaries; + return facadeSummaries; } /** @@ -126,29 +91,28 @@ class LazyThirdParty extends Audit { const tasks = await MainThreadTasks.request(trace, context); const multiplier = settings.throttlingMethod === 'simulate' ? settings.throttling.cpuSlowdownMultiplier : 1; - const summaries = this.getSummaries(networkRecords, tasks, multiplier, mainEntity); + const {byURL} = ThirdPartySummary.getSummaries(networkRecords, tasks, multiplier); + const facadeSummaries = LazyThirdParty.getFacadeSummaries(byURL, mainEntity); const summary = {wastedBytes: 0, wastedMs: 0}; /** @type LH.Audit.Details.TableItem[] */ - const results = Array.from(summaries) - .map(([facade, facadeStats]) => { + const results = Array.from(facadeSummaries) + .map(([name, facadeSummary]) => { /** @type LH.Audit.Details.TableItem[] */ const items = []; - for (const [url, urlStats] of Array.from(facadeStats.urlSummaries)) { - items.push({url, ...urlStats}); + for (const [url, urlStats] of Array.from(facadeSummary.urlSummaries)) { + const product = thirdPartyWeb.getProduct(url) || {name: ''}; + items.push({url, productName: product.name, ...urlStats}); + summary.wastedBytes += urlStats.transferSize; + summary.wastedMs += urlStats.blockingTime; } - summary.wastedBytes += facadeStats.summary.transferSize; - summary.wastedMs += facadeStats.summary.blockingTime; return { facade: /** @type {LH.Audit.Details.LinkValue} */ { type: 'link', - text: facade.name, - url: facade.repo, + text: name, + url: facadeSummary.facade.repo, }, - transferSize: facadeStats.summary.transferSize, - mainThreadTime: facadeStats.summary.mainThreadTime, - blockingTime: facadeStats.summary.blockingTime, subItems: {type: 'subitems', items}, }; }); @@ -157,9 +121,11 @@ class LazyThirdParty extends Audit { const headings = [ {key: 'facade', itemType: 'link', text: str_(UIStrings.columnFacade), subItemsHeading: {key: 'url', itemType: 'url'}}, - {key: 'transferSize', granularity: 1, itemType: 'bytes', + {key: null, itemType: 'text', text: str_(UIStrings.columnProduct), + subItemsHeading: {key: 'productName'}}, + {key: null, granularity: 1, itemType: 'bytes', text: str_(i18n.UIStrings.columnTransferSize), subItemsHeading: {key: 'transferSize'}}, - {key: 'blockingTime', granularity: 1, itemType: 'ms', + {key: null, granularity: 1, itemType: 'ms', text: str_(i18n.UIStrings.columnBlockingTime), subItemsHeading: {key: 'blockingTime'}}, ]; From e600084edc16d6c3f0804350a47e6d50e49035ab Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Thu, 20 Aug 2020 12:41:47 -0400 Subject: [PATCH 06/82] update sample --- lighthouse-core/lib/i18n/locales/en-US.json | 3 +++ lighthouse-core/lib/i18n/locales/en-XL.json | 3 +++ 2 files changed, 6 insertions(+) diff --git a/lighthouse-core/lib/i18n/locales/en-US.json b/lighthouse-core/lib/i18n/locales/en-US.json index 34f046e9c499..c2c3699f99bb 100644 --- a/lighthouse-core/lib/i18n/locales/en-US.json +++ b/lighthouse-core/lib/i18n/locales/en-US.json @@ -863,6 +863,9 @@ "lighthouse-core/audits/lazy-third-party.js | columnFacade": { "message": "Facade Alternative" }, + "lighthouse-core/audits/lazy-third-party.js | columnProduct": { + "message": "Product" + }, "lighthouse-core/audits/lazy-third-party.js | description": { "message": "Some third-party resources can be fetched after the page loads. These third-party resources are used by embedded elements which can be replaced by a facade until the user needs to use them. [Learn more]()." }, diff --git a/lighthouse-core/lib/i18n/locales/en-XL.json b/lighthouse-core/lib/i18n/locales/en-XL.json index a8dd8c365dee..45254ee5d464 100644 --- a/lighthouse-core/lib/i18n/locales/en-XL.json +++ b/lighthouse-core/lib/i18n/locales/en-XL.json @@ -863,6 +863,9 @@ "lighthouse-core/audits/lazy-third-party.js | columnFacade": { "message": "F̂áĉád̂é Âĺt̂ér̂ńât́îv́ê" }, + "lighthouse-core/audits/lazy-third-party.js | columnProduct": { + "message": "P̂ŕôd́ûćt̂" + }, "lighthouse-core/audits/lazy-third-party.js | description": { "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ćâń b̂é f̂ét̂ćĥéd̂ áf̂t́êŕ t̂h́ê ṕâǵê ĺôád̂ś. T̂h́êśê t́ĥír̂d́-p̂ár̂t́ŷ ŕêśôúr̂ćêś âŕê úŝéd̂ b́ŷ ém̂b́êd́d̂éd̂ él̂ém̂én̂t́ŝ ẃĥíĉh́ ĉán̂ b́ê ŕêṕl̂áĉéd̂ b́ŷ á f̂áĉád̂é ûńt̂íl̂ t́ĥé ûśêŕ n̂éêd́ŝ t́ô úŝé t̂h́êḿ. [L̂éâŕn̂ ḿôŕê]()." }, From 585aa8b1f67913e566eba138429d83302c31de02 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Thu, 20 Aug 2020 12:44:37 -0400 Subject: [PATCH 07/82] nit --- lighthouse-core/audits/lazy-third-party.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js index 7b609ee7e102..897d6d4fdb4b 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/lazy-third-party.js @@ -117,6 +117,13 @@ class LazyThirdParty extends Audit { }; }); + if (!results.length) { + return { + score: 1, + notApplicable: true, + }; + } + /** @type {LH.Audit.Details.Table['headings']} */ const headings = [ {key: 'facade', itemType: 'link', text: str_(UIStrings.columnFacade), @@ -129,12 +136,6 @@ class LazyThirdParty extends Audit { text: str_(i18n.UIStrings.columnBlockingTime), subItemsHeading: {key: 'blockingTime'}}, ]; - if (!results.length) { - return { - score: 1, - notApplicable: true, - }; - } return { score: 0, displayValue: str_(UIStrings.displayValue, { From 94c1487613fbca1ce4951ad3a2754ef7fa0217b9 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Thu, 20 Aug 2020 12:48:01 -0400 Subject: [PATCH 08/82] define lazy loading --- lighthouse-core/audits/lazy-third-party.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js index 897d6d4fdb4b..89886d1ddf2b 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/lazy-third-party.js @@ -14,22 +14,22 @@ const MainThreadTasks = require('../computed/main-thread-tasks.js'); const ThirdPartySummary = require('./third-party-summary.js'); const UIStrings = { - /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded. This descriptive title is shown to users when no resources have lazy loading alternatives available. */ + /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded. This descriptive title is shown to users when no resources have lazy loading alternatives available. Lazy loading means loading resources is deferred until they are needed. */ title: 'Lazy load third-party resources', - /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded. This descriptive title is shown to users when one or more third-party resources have available lazy loading alternatives. */ + /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded. This descriptive title is shown to users when one or more third-party resources have available lazy loading alternatives. Lazy loading means loading resources is deferred until they are needed. */ failureTitle: 'Some third-party resources can be lazy loaded', - /** Description of a Lighthouse audit that identifies the third party code on the page that can be lazy loaded. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. */ + /** Description of a Lighthouse audit that identifies the third party code on the page that can be lazy loaded. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. Lazy loading means loading resources is deferred until they are needed. */ description: 'Some third-party resources can be fetched after the page loads. ' + 'These third-party resources are used by embedded elements which can be replaced by a facade ' + 'until the user needs to use them. [Learn more]().', - /** Summary text for the result of a Lighthouse audit that identifies the third party code on a web page that can be lazy loaded. This text summarizes the number of lazy loading facades that can be used on the page. */ + /** Summary text for the result of a Lighthouse audit that identifies the third party code on a web page that can be lazy loaded. This text summarizes the number of lazy loading facades that can be used on the page. Lazy loading means loading resources is deferred until they are needed. */ displayValue: `{itemCount, plural, =1 {# facade alternative available} other {# facade alternatives available} }`, - /** Label for a table column that displays the name of a lazy loading facade alternative for a third party resource. */ + /** Label for a table column that displays the name of a lazy loading facade alternative for a third party resource. Lazy loading means loading resources is deferred until they are needed. */ columnFacade: 'Facade Alternative', - /** Label for a table column that displays the name of the third party product that a URL is used for. */ + /** Label for a table column that displays the name of the third party product that a URL is used for. Lazy loading means loading resources is deferred until they are needed. */ columnProduct: 'Product', }; From ffd6077828ffedcbd64ca6e78c1e85d944df3039 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Thu, 20 Aug 2020 12:54:03 -0400 Subject: [PATCH 09/82] fix typo --- lighthouse-core/audits/lazy-third-party.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js index d0333a5c0f9e..db9a65d33e52 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/lazy-third-party.js @@ -55,7 +55,7 @@ class LazyThirdParty extends Audit { } /** - * @param {Map} byURL * @param {ThirdPartyEntity | undefined} mainEntity * @return {Map} */ From 6fec26fe748adf16e7212ffbe731f6377a444f90 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Thu, 20 Aug 2020 14:21:00 -0400 Subject: [PATCH 10/82] add test cases --- .../test/audits/lazy-third-party-test.js | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 lighthouse-core/test/audits/lazy-third-party-test.js diff --git a/lighthouse-core/test/audits/lazy-third-party-test.js b/lighthouse-core/test/audits/lazy-third-party-test.js new file mode 100644 index 000000000000..b280deb9d18f --- /dev/null +++ b/lighthouse-core/test/audits/lazy-third-party-test.js @@ -0,0 +1,102 @@ +/** + * @license Copyright 2020 The Lighthouse Authors. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + */ +'use strict'; + +const LazyThirdParty = require('../../audits/lazy-third-party.js'); +const networkRecordsToDevtoolsLog = require('../network-records-to-devtools-log.js'); +const createTestTrace = require('../create-test-trace.js'); + +const pwaTrace = require('../fixtures/traces/progressive-app-m60.json'); +const pwaDevtoolsLog = require('../fixtures/traces/progressive-app-m60.devtools.log.json'); +const noThirdPartyTrace = require('../fixtures/traces/no-tracingstarted-m74.json'); + +/* eslint-env jest */ +describe('Lazy load third party resources', () => { + it('correctly identifies a lazy loadable third party resource', async () => { + const artifacts = { + devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ + {url: 'https://example.com'}, + {url: 'https://widget.intercom.io/widget/tx2p130c'}, + ])}, + traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, + URL: {finalUrl: 'https://example.com'}, + }; + + const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; + const results = await LazyThirdParty.audit(artifacts, {computedCache: new Map(), settings}); + + expect(results.score).toBe(0); + expect(results.details.items).toEqual([ + { + facade: { + type: 'link', + text: 'React Live Chat Loader', + url: 'https://github.com/calibreapp/react-live-chat-loader', + }, + subItems: {type: 'subitems', items: [ + { + url: 'https://widget.intercom.io/widget/tx2p130c', + productName: 'Intercom Widget', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 0, + }, + ]}, + }, + ]); + }); + + it('does not report first party resources', async () => { + const artifacts = { + devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ + {url: 'https://youtube.com'}, + {url: 'https://www.youtube.com/embed/tgbNymZ7vqY'}, + ])}, + traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, + URL: {finalUrl: 'https://youtube.com'}, + }; + + const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; + const results = await LazyThirdParty.audit(artifacts, {computedCache: new Map(), settings}); + + expect(results).toEqual({ + score: 1, + notApplicable: true, + }); + }); + + it('only reports resources which can be lazy loaded', async () => { + const artifacts = { + devtoolsLogs: {defaultPass: pwaDevtoolsLog}, + traces: {defaultPass: pwaTrace}, + URL: {finalUrl: 'https://pwa-rocks.com'}, + }; + + const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; + const results = await LazyThirdParty.audit(artifacts, {computedCache: new Map(), settings}); + + expect(results).toEqual({ + score: 1, + notApplicable: true, + }); + }); + + it('not applicable when no third party resources are present', async () => { + const artifacts = { + devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([{url: 'chrome://version'}])}, + traces: {defaultPass: noThirdPartyTrace}, + URL: {finalUrl: 'chrome://version'}, + }; + + const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; + const results = await LazyThirdParty.audit(artifacts, {computedCache: new Map(), settings}); + + expect(results).toEqual({ + score: 1, + notApplicable: true, + }); + }); +}); From 6eba1146cdeae9f5aef34af25cd3bcdf2c2ca4e1 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Thu, 20 Aug 2020 14:26:57 -0400 Subject: [PATCH 11/82] hide third party ui filter --- lighthouse-core/report/html/renderer/report-ui-features.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lighthouse-core/report/html/renderer/report-ui-features.js b/lighthouse-core/report/html/renderer/report-ui-features.js index 1fbec12bcbc8..ebabaf13a177 100644 --- a/lighthouse-core/report/html/renderer/report-ui-features.js +++ b/lighthouse-core/report/html/renderer/report-ui-features.js @@ -216,8 +216,9 @@ class ReportUIFeatures { _setupThirdPartyFilter() { // Some audits should not display the third party filter option. const thirdPartyFilterAuditExclusions = [ - // This audit deals explicitly with third party resources. + // These audits deal explicitly with third party resources. 'uses-rel-preconnect', + 'lazy-third-party', ]; // Some audits should hide third party by default. const thirdPartyFilterAuditHideByDefault = [ From 4dc8993e717a5759fd219b216951b1c5df472f0e Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Thu, 20 Aug 2020 14:30:06 -0400 Subject: [PATCH 12/82] add temporary learn more link --- lighthouse-core/audits/lazy-third-party.js | 2 +- lighthouse-core/lib/i18n/locales/en-US.json | 2 +- lighthouse-core/lib/i18n/locales/en-XL.json | 2 +- lighthouse-core/test/results/sample_v2.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js index db9a65d33e52..d268066db7f7 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/lazy-third-party.js @@ -21,7 +21,7 @@ const UIStrings = { /** Description of a Lighthouse audit that identifies the third party code on the page that can be lazy loaded. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. Lazy loading means loading resources is deferred until they are needed. */ description: 'Some third-party resources can be fetched after the page loads. ' + 'These third-party resources are used by embedded elements which can be replaced by a facade ' + - 'until the user needs to use them. [Learn more]().', + 'until the user needs to use them. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).', /** Summary text for the result of a Lighthouse audit that identifies the third party code on a web page that can be lazy loaded. This text summarizes the number of lazy loading facades that can be used on the page. Lazy loading means loading resources is deferred until they are needed. */ displayValue: `{itemCount, plural, =1 {# facade alternative available} diff --git a/lighthouse-core/lib/i18n/locales/en-US.json b/lighthouse-core/lib/i18n/locales/en-US.json index c2c3699f99bb..fb8746b152ca 100644 --- a/lighthouse-core/lib/i18n/locales/en-US.json +++ b/lighthouse-core/lib/i18n/locales/en-US.json @@ -867,7 +867,7 @@ "message": "Product" }, "lighthouse-core/audits/lazy-third-party.js | description": { - "message": "Some third-party resources can be fetched after the page loads. These third-party resources are used by embedded elements which can be replaced by a facade until the user needs to use them. [Learn more]()." + "message": "Some third-party resources can be fetched after the page loads. These third-party resources are used by embedded elements which can be replaced by a facade until the user needs to use them. [Learn more](https://web.dev/efficiently-load-third-party-javascript/)." }, "lighthouse-core/audits/lazy-third-party.js | displayValue": { "message": "{itemCount, plural,\n =1 {# facade alternative available}\n other {# facade alternatives available}\n }" diff --git a/lighthouse-core/lib/i18n/locales/en-XL.json b/lighthouse-core/lib/i18n/locales/en-XL.json index 45254ee5d464..f74915792b87 100644 --- a/lighthouse-core/lib/i18n/locales/en-XL.json +++ b/lighthouse-core/lib/i18n/locales/en-XL.json @@ -867,7 +867,7 @@ "message": "P̂ŕôd́ûćt̂" }, "lighthouse-core/audits/lazy-third-party.js | description": { - "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ćâń b̂é f̂ét̂ćĥéd̂ áf̂t́êŕ t̂h́ê ṕâǵê ĺôád̂ś. T̂h́êśê t́ĥír̂d́-p̂ár̂t́ŷ ŕêśôúr̂ćêś âŕê úŝéd̂ b́ŷ ém̂b́êd́d̂éd̂ él̂ém̂én̂t́ŝ ẃĥíĉh́ ĉán̂ b́ê ŕêṕl̂áĉéd̂ b́ŷ á f̂áĉád̂é ûńt̂íl̂ t́ĥé ûśêŕ n̂éêd́ŝ t́ô úŝé t̂h́êḿ. [L̂éâŕn̂ ḿôŕê]()." + "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ćâń b̂é f̂ét̂ćĥéd̂ áf̂t́êŕ t̂h́ê ṕâǵê ĺôád̂ś. T̂h́êśê t́ĥír̂d́-p̂ár̂t́ŷ ŕêśôúr̂ćêś âŕê úŝéd̂ b́ŷ ém̂b́êd́d̂éd̂ él̂ém̂én̂t́ŝ ẃĥíĉh́ ĉán̂ b́ê ŕêṕl̂áĉéd̂ b́ŷ á f̂áĉád̂é ûńt̂íl̂ t́ĥé ûśêŕ n̂éêd́ŝ t́ô úŝé t̂h́êḿ. [L̂éâŕn̂ ḿôŕê](https://web.dev/efficiently-load-third-party-javascript/)." }, "lighthouse-core/audits/lazy-third-party.js | displayValue": { "message": "{itemCount, plural,\n =1 {# f̂áĉád̂é âĺt̂ér̂ńât́îv́ê áv̂áîĺâb́l̂é}\n other {# f̂áĉád̂é âĺt̂ér̂ńât́îv́êś âv́âíl̂áb̂ĺê}\n }" diff --git a/lighthouse-core/test/results/sample_v2.json b/lighthouse-core/test/results/sample_v2.json index 0e542bc1e40e..2d2c25d3d97b 100644 --- a/lighthouse-core/test/results/sample_v2.json +++ b/lighthouse-core/test/results/sample_v2.json @@ -1729,7 +1729,7 @@ "lazy-third-party": { "id": "lazy-third-party", "title": "Lazy load third-party resources", - "description": "Some third-party resources can be fetched after the page loads. These third-party resources are used by embedded elements which can be replaced by a facade until the user needs to use them. [Learn more]().", + "description": "Some third-party resources can be fetched after the page loads. These third-party resources are used by embedded elements which can be replaced by a facade until the user needs to use them. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).", "score": null, "scoreDisplayMode": "notApplicable" }, From 597fdd0a74f0ef0d165af48b7e4793377edcb94f Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Thu, 20 Aug 2020 14:57:42 -0400 Subject: [PATCH 13/82] update snapshot --- lighthouse-cli/test/cli/__snapshots__/index-test.js.snap | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap b/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap index 65912628e525..7acae0f230d6 100644 --- a/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap +++ b/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap @@ -150,6 +150,9 @@ Object { Object { "path": "third-party-summary", }, + Object { + "path": "lazy-third-party", + }, Object { "path": "largest-contentful-paint-element", }, @@ -993,6 +996,11 @@ Object { "id": "third-party-summary", "weight": 0, }, + Object { + "group": "diagnostics", + "id": "lazy-third-party", + "weight": 0, + }, Object { "group": "diagnostics", "id": "largest-contentful-paint-element", From 30397ec6abc4ae665ccf24482dbe596dc3665b15 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Thu, 20 Aug 2020 17:57:07 -0400 Subject: [PATCH 14/82] add displayValue to test --- lighthouse-core/test/audits/lazy-third-party-test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lighthouse-core/test/audits/lazy-third-party-test.js b/lighthouse-core/test/audits/lazy-third-party-test.js index b280deb9d18f..e7beff0108c5 100644 --- a/lighthouse-core/test/audits/lazy-third-party-test.js +++ b/lighthouse-core/test/audits/lazy-third-party-test.js @@ -29,6 +29,7 @@ describe('Lazy load third party resources', () => { const results = await LazyThirdParty.audit(artifacts, {computedCache: new Map(), settings}); expect(results.score).toBe(0); + expect(results.displayValue).toBeDisplayString('1 facade alternative available'); expect(results.details.items).toEqual([ { facade: { From 3c622da27cee98fda9b79a2c11b7ba87c532d62d Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Mon, 24 Aug 2020 11:14:10 -0400 Subject: [PATCH 15/82] use entity related resources --- lighthouse-core/audits/lazy-third-party.js | 48 ++++++++++++++----- lighthouse-core/audits/third-party-summary.js | 12 ++++- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js index d268066db7f7..14a48f3197f4 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/lazy-third-party.js @@ -38,7 +38,7 @@ const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings); /** @typedef {import("third-party-web").IEntity} ThirdPartyEntity */ /** @typedef {import("third-party-web").IFacade} ThirdPartyFacade */ -/** @typedef {{facade: ThirdPartyFacade, urlSummaries: Map}} FacadeSummary */ +/** @typedef {{facade: ThirdPartyFacade, cutoffTime: number, urlSummaries: Map}} FacadeSummary */ class LazyThirdParty extends Audit { /** @@ -57,23 +57,49 @@ class LazyThirdParty extends Audit { /** * @param {Map} byURL * @param {ThirdPartyEntity | undefined} mainEntity - * @return {Map} + * @return {FacadeSummary[]} */ static getFacadeSummaries(byURL, mainEntity) { - /** @type {Map} */ - const facadeSummaries = new Map(); + /** @type {Map>} */ + const entitySummaries = new Map(); for (const [url, urlSummary] of byURL) { const entity = thirdPartyWeb.getEntity(url); const facade = thirdPartyWeb.getFirstFacade(url); - if (!facade || !entity || mainEntity && entity.name === mainEntity.name) continue; + if (!entity || mainEntity && entity.name === mainEntity.name) continue; + + /** @type {Map} */ + const facadeSummaries = entitySummaries.get(entity.name) || new Map(); + if (facade) { + // Record new facades if the url has one + const facadeSummary = facadeSummaries.get(facade.name) || { + facade, + cutoffTime: Infinity, + urlSummaries: new Map(), + }; + + facadeSummary.urlSummaries.set(url, urlSummary); + facadeSummary.cutoffTime = Math.min(facadeSummary.cutoffTime, urlSummary.endTime); - const facadeSummary = facadeSummaries.get(facade.name) || {facade, urlSummaries: new Map()}; - facadeSummary.urlSummaries.set(url, urlSummary); - facadeSummaries.set(facade.name, facadeSummary); + facadeSummaries.set(facade.name, facadeSummary); + } else { + // If the url does not have a facade but its entity does, add this url to any facade summaries + // for resources fetched before this one. + for (const facadeSummary of facadeSummaries.values()) { + if (urlSummary.startTime < facadeSummary.cutoffTime) continue; + facadeSummary.urlSummaries.set(url, urlSummary); + } + } + entitySummaries.set(entity.name, facadeSummaries); } - return facadeSummaries; + const allFacadeSummaries = []; + for (const facadeSummaries of entitySummaries.values()) { + for (const facadeSummary of facadeSummaries.values()) { + allFacadeSummaries.push(facadeSummary); + } + } + return allFacadeSummaries; } /** @@ -98,7 +124,7 @@ class LazyThirdParty extends Audit { /** @type LH.Audit.Details.TableItem[] */ const results = Array.from(facadeSummaries) - .map(([name, facadeSummary]) => { + .map((facadeSummary) => { /** @type LH.Audit.Details.TableItem[] */ const items = []; for (const [url, urlStats] of Array.from(facadeSummary.urlSummaries)) { @@ -110,7 +136,7 @@ class LazyThirdParty extends Audit { return { facade: /** @type {LH.Audit.Details.LinkValue} */ { type: 'link', - text: name, + text: facadeSummary.facade.name, url: facadeSummary.facade.repo, }, subItems: {type: 'subitems', items}, diff --git a/lighthouse-core/audits/third-party-summary.js b/lighthouse-core/audits/third-party-summary.js index 5ed7a3faac99..0c104b31208d 100644 --- a/lighthouse-core/audits/third-party-summary.js +++ b/lighthouse-core/audits/third-party-summary.js @@ -43,6 +43,8 @@ const PASS_THRESHOLD_IN_MS = 250; * mainThreadTime: number, * transferSize: number, * blockingTime: number, + * startTime: number, + * endTime: number, * }} Summary */ @@ -90,11 +92,19 @@ class ThirdPartySummary extends Audit { const byURL = new Map(); /** @type {Map} */ const byEntity = new Map(); - const defaultSummary = {mainThreadTime: 0, blockingTime: 0, transferSize: 0}; + const defaultSummary = { + mainThreadTime: 0, + blockingTime: 0, + transferSize: 0, + startTime: Infinity, + endTime: 0, + }; for (const request of networkRecords) { const urlSummary = byURL.get(request.url) || {...defaultSummary}; urlSummary.transferSize += request.transferSize; + urlSummary.startTime = Math.min(urlSummary.startTime, request.startTime); + urlSummary.endTime = Math.max(urlSummary.endTime, request.endTime); byURL.set(request.url, urlSummary); } From 912e8d35dab2959056a92d6355c19796e82e26f4 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Mon, 24 Aug 2020 12:43:24 -0400 Subject: [PATCH 16/82] switch to product based report --- lighthouse-core/audits/lazy-third-party.js | 113 ++++++++++-------- lighthouse-core/lib/third-party-web.js | 12 -- .../test/audits/lazy-third-party-test.js | 36 +++++- 3 files changed, 95 insertions(+), 66 deletions(-) diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js index 14a48f3197f4..bbb6cf454c8e 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/lazy-third-party.js @@ -36,9 +36,9 @@ const UIStrings = { const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings); /** @typedef {import("third-party-web").IEntity} ThirdPartyEntity */ -/** @typedef {import("third-party-web").IFacade} ThirdPartyFacade */ +/** @typedef {import("third-party-web").IProduct} ThirdPartyProduct*/ -/** @typedef {{facade: ThirdPartyFacade, cutoffTime: number, urlSummaries: Map}} FacadeSummary */ +/** @typedef {{product: ThirdPartyProduct, cutoffTime: number, urlSummaries: Map}} ProductSummary */ class LazyThirdParty extends Audit { /** @@ -57,49 +57,49 @@ class LazyThirdParty extends Audit { /** * @param {Map} byURL * @param {ThirdPartyEntity | undefined} mainEntity - * @return {FacadeSummary[]} + * @return {ProductSummary[]} */ - static getFacadeSummaries(byURL, mainEntity) { - /** @type {Map>} */ + static getProductSummaries(byURL, mainEntity) { + /** @type {Map>} */ const entitySummaries = new Map(); for (const [url, urlSummary] of byURL) { const entity = thirdPartyWeb.getEntity(url); - const facade = thirdPartyWeb.getFirstFacade(url); + const product = thirdPartyWeb.getProduct(url); if (!entity || mainEntity && entity.name === mainEntity.name) continue; - /** @type {Map} */ - const facadeSummaries = entitySummaries.get(entity.name) || new Map(); - if (facade) { - // Record new facades if the url has one - const facadeSummary = facadeSummaries.get(facade.name) || { - facade, + /** @type {Map} */ + const productSummaries = entitySummaries.get(entity.name) || new Map(); + if (product && product.facades && product.facades.length) { + // Record new url if product has a facade + const productSummary = productSummaries.get(product.name) || { + product, cutoffTime: Infinity, urlSummaries: new Map(), }; - facadeSummary.urlSummaries.set(url, urlSummary); - facadeSummary.cutoffTime = Math.min(facadeSummary.cutoffTime, urlSummary.endTime); + productSummary.urlSummaries.set(url, urlSummary); + productSummary.cutoffTime = Math.min(productSummary.cutoffTime, urlSummary.endTime); - facadeSummaries.set(facade.name, facadeSummary); + productSummaries.set(product.name, productSummary); } else { - // If the url does not have a facade but its entity does, add this url to any facade summaries - // for resources fetched before this one. - for (const facadeSummary of facadeSummaries.values()) { - if (urlSummary.startTime < facadeSummary.cutoffTime) continue; - facadeSummary.urlSummaries.set(url, urlSummary); + // If the url does not have a facade but one or more products on its entity do, + // we still want to record this url because it was probably fetched by a product with a facade. + for (const productSummary of productSummaries.values()) { + if (urlSummary.startTime < productSummary.cutoffTime) continue; + productSummary.urlSummaries.set(url, urlSummary); } } - entitySummaries.set(entity.name, facadeSummaries); + entitySummaries.set(entity.name, productSummaries); } - const allFacadeSummaries = []; - for (const facadeSummaries of entitySummaries.values()) { - for (const facadeSummary of facadeSummaries.values()) { - allFacadeSummaries.push(facadeSummary); + const allProductSummaries = []; + for (const productSummaries of entitySummaries.values()) { + for (const productSummary of productSummaries.values()) { + allProductSummaries.push(productSummary); } } - return allFacadeSummaries; + return allProductSummaries; } /** @@ -118,30 +118,44 @@ class LazyThirdParty extends Audit { const multiplier = settings.throttlingMethod === 'simulate' ? settings.throttling.cpuSlowdownMultiplier : 1; const {byURL} = ThirdPartySummary.getSummaries(networkRecords, tasks, multiplier); - const facadeSummaries = LazyThirdParty.getFacadeSummaries(byURL, mainEntity); + const productSummaries = LazyThirdParty.getProductSummaries(byURL, mainEntity); const summary = {wastedBytes: 0, wastedMs: 0}; /** @type LH.Audit.Details.TableItem[] */ - const results = Array.from(facadeSummaries) - .map((facadeSummary) => { - /** @type LH.Audit.Details.TableItem[] */ - const items = []; - for (const [url, urlStats] of Array.from(facadeSummary.urlSummaries)) { - const product = thirdPartyWeb.getProduct(url) || {name: ''}; - items.push({url, productName: product.name, ...urlStats}); - summary.wastedBytes += urlStats.transferSize; - summary.wastedMs += urlStats.blockingTime; - } - return { - facade: /** @type {LH.Audit.Details.LinkValue} */ { - type: 'link', - text: facadeSummary.facade.name, - url: facadeSummary.facade.repo, - }, - subItems: {type: 'subitems', items}, - }; + const results = []; + for (const productSummary of productSummaries) { + const product = productSummary.product; + if (!product.facades || !product.facades.length) continue; + + // The first facade should always be the best one + const bestFacade = product.facades[0]; + + const items = []; + let transferSize = 0; + let blockingTime = 0; + for (const [url, urlStats] of Array.from(productSummary.urlSummaries)) { + items.push({url, ...urlStats}); + transferSize += urlStats.transferSize; + blockingTime += urlStats.blockingTime; + } + items.sort((firstEl, secondEl) => { + return secondEl.transferSize - firstEl.transferSize; }); + summary.wastedBytes += transferSize; + summary.wastedMs += blockingTime; + results.push({ + productName: product.name, + facade: /** @type {LH.Audit.Details.LinkValue} */ { + type: 'link', + text: bestFacade.name, + url: bestFacade.repo, + }, + transferSize, + blockingTime, + subItems: {type: 'subitems', items}, + }); + } if (!results.length) { return { @@ -152,13 +166,12 @@ class LazyThirdParty extends Audit { /** @type {LH.Audit.Details.Table['headings']} */ const headings = [ - {key: 'facade', itemType: 'link', text: str_(UIStrings.columnFacade), + {key: 'productName', itemType: 'text', text: str_(UIStrings.columnProduct), subItemsHeading: {key: 'url', itemType: 'url'}}, - {key: null, itemType: 'text', text: str_(UIStrings.columnProduct), - subItemsHeading: {key: 'productName'}}, - {key: null, granularity: 1, itemType: 'bytes', + {key: 'facade', itemType: 'link', text: str_(UIStrings.columnFacade)}, + {key: 'transferSize', granularity: 1, itemType: 'bytes', text: str_(i18n.UIStrings.columnTransferSize), subItemsHeading: {key: 'transferSize'}}, - {key: null, granularity: 1, itemType: 'ms', + {key: 'blockingTime', granularity: 1, itemType: 'ms', text: str_(i18n.UIStrings.columnBlockingTime), subItemsHeading: {key: 'blockingTime'}}, ]; diff --git a/lighthouse-core/lib/third-party-web.js b/lighthouse-core/lib/third-party-web.js index 87b547e0fe9c..c4f24a7154a1 100644 --- a/lighthouse-core/lib/third-party-web.js +++ b/lighthouse-core/lib/third-party-web.js @@ -37,17 +37,6 @@ function getProduct(url) { } } -/** - * The first facade should always be the best one. - * @param {string} url - * @return {ThirdPartyFacade|undefined} - */ -function getFirstFacade(url) { - const product = getProduct(url); - if (!product || !product.facades || !product.facades.length) return undefined; - return product.facades[0]; -} - /** * @param {string} url * @param {ThirdPartyEntity | undefined} mainDocumentEntity @@ -70,7 +59,6 @@ function isFirstParty(url, mainDocumentEntity) { module.exports = { getEntity, getProduct, - getFirstFacade, isThirdParty, isFirstParty, }; diff --git a/lighthouse-core/test/audits/lazy-third-party-test.js b/lighthouse-core/test/audits/lazy-third-party-test.js index e7beff0108c5..2d7b5a365dec 100644 --- a/lighthouse-core/test/audits/lazy-third-party-test.js +++ b/lighthouse-core/test/audits/lazy-third-party-test.js @@ -18,8 +18,24 @@ describe('Lazy load third party resources', () => { it('correctly identifies a lazy loadable third party resource', async () => { const artifacts = { devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ - {url: 'https://example.com'}, - {url: 'https://widget.intercom.io/widget/tx2p130c'}, + { + url: 'https://example.com', + startTime: 0, + endTime: 50, + transferSize: 2000, + }, + { + url: 'https://widget.intercom.io/widget/tx2p130c', + startTime: 100, + endTime: 150, + transferSize: 4000, + }, + { + url: 'https://js.intercomcdn.com/frame-modern.bb95039c.js', + startTime: 200, + endTime: 250, + transferSize: 8000, + }, ])}, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, URL: {finalUrl: 'https://example.com'}, @@ -32,18 +48,30 @@ describe('Lazy load third party resources', () => { expect(results.displayValue).toBeDisplayString('1 facade alternative available'); expect(results.details.items).toEqual([ { + productName: 'Intercom Widget', facade: { type: 'link', text: 'React Live Chat Loader', url: 'https://github.com/calibreapp/react-live-chat-loader', }, + transferSize: 12000, + blockingTime: 0, subItems: {type: 'subitems', items: [ + { + url: 'https://js.intercomcdn.com/frame-modern.bb95039c.js', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 8000, + startTime: 200, + endTime: 250, + }, { url: 'https://widget.intercom.io/widget/tx2p130c', - productName: 'Intercom Widget', mainThreadTime: 0, blockingTime: 0, - transferSize: 0, + transferSize: 4000, + startTime: 100, + endTime: 150, }, ]}, }, From b9164326be91b5117f3d75a65a6282e7d9c878ec Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Mon, 24 Aug 2020 13:00:46 -0400 Subject: [PATCH 17/82] move to experimental --- lighthouse-core/config/default-config.js | 2 -- lighthouse-core/config/experimental-config.js | 10 ++++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lighthouse-core/config/default-config.js b/lighthouse-core/config/default-config.js index 76a97ca612dc..4b6db5016b25 100644 --- a/lighthouse-core/config/default-config.js +++ b/lighthouse-core/config/default-config.js @@ -235,7 +235,6 @@ const defaultConfig = { 'timing-budget', 'resource-summary', 'third-party-summary', - 'lazy-third-party', 'largest-contentful-paint-element', 'layout-shift-elements', 'long-tasks', @@ -468,7 +467,6 @@ const defaultConfig = { {id: 'timing-budget', weight: 0, group: 'budgets'}, {id: 'resource-summary', weight: 0, group: 'diagnostics'}, {id: 'third-party-summary', weight: 0, group: 'diagnostics'}, - {id: 'lazy-third-party', weight: 0, group: 'diagnostics'}, {id: 'largest-contentful-paint-element', weight: 0, group: 'diagnostics'}, {id: 'layout-shift-elements', weight: 0, group: 'diagnostics'}, {id: 'uses-passive-event-listeners', weight: 0, group: 'diagnostics'}, diff --git a/lighthouse-core/config/experimental-config.js b/lighthouse-core/config/experimental-config.js index c3fbdeca8181..8d23a938671c 100644 --- a/lighthouse-core/config/experimental-config.js +++ b/lighthouse-core/config/experimental-config.js @@ -15,6 +15,7 @@ const config = { extends: 'lighthouse:default', audits: [ 'full-page-screenshot', + 'lazy-third-party', ], passes: [{ passName: 'defaultPass', @@ -22,6 +23,15 @@ const config = { 'full-page-screenshot', ], }], + categories: { + // @ts-ignore: `title` is required in CategoryJson. setting to the same value as the default + // config is awkward - easier to omit the property here. Will defer to default config. + 'performance': { + auditRefs: [ + {id: 'lazy-third-party', weight: 0, group: 'diagnostics'}, + ], + }, + }, }; module.exports = config; From c59d76ac6d8ba3a7f089d6c3dc81276e7e009280 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Mon, 24 Aug 2020 13:18:14 -0400 Subject: [PATCH 18/82] update sample and snapshot --- .../test/cli/__snapshots__/index-test.js.snap | 8 ----- lighthouse-core/test/results/sample_v2.json | 30 ++++--------------- 2 files changed, 5 insertions(+), 33 deletions(-) diff --git a/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap b/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap index 7acae0f230d6..65912628e525 100644 --- a/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap +++ b/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap @@ -150,9 +150,6 @@ Object { Object { "path": "third-party-summary", }, - Object { - "path": "lazy-third-party", - }, Object { "path": "largest-contentful-paint-element", }, @@ -996,11 +993,6 @@ Object { "id": "third-party-summary", "weight": 0, }, - Object { - "group": "diagnostics", - "id": "lazy-third-party", - "weight": 0, - }, Object { "group": "diagnostics", "id": "largest-contentful-paint-element", diff --git a/lighthouse-core/test/results/sample_v2.json b/lighthouse-core/test/results/sample_v2.json index 96f69c79f45f..662cabe33a3f 100644 --- a/lighthouse-core/test/results/sample_v2.json +++ b/lighthouse-core/test/results/sample_v2.json @@ -1702,6 +1702,8 @@ "mainThreadTime": 90.36300000000001, "blockingTime": 22.918000000000006, "transferSize": 30174, + "startTime": null, + "endTime": 0, "entity": { "type": "link", "text": "Google CDN", @@ -1714,7 +1716,9 @@ "url": "http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js", "mainThreadTime": 90.36300000000001, "blockingTime": 22.918000000000006, - "transferSize": 30174 + "transferSize": 30174, + "startTime": 185607.195975, + "endTime": 185608.117509 } ] } @@ -1726,13 +1730,6 @@ } } }, - "lazy-third-party": { - "id": "lazy-third-party", - "title": "Lazy load third-party resources", - "description": "Some third-party resources can be fetched after the page loads. These third-party resources are used by embedded elements which can be replaced by a facade until the user needs to use them. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).", - "score": null, - "scoreDisplayMode": "notApplicable" - }, "largest-contentful-paint-element": { "id": "largest-contentful-paint-element", "title": "Largest Contentful Paint element", @@ -4458,11 +4455,6 @@ "weight": 0, "group": "diagnostics" }, - { - "id": "lazy-third-party", - "weight": 0, - "group": "diagnostics" - }, { "id": "largest-contentful-paint-element", "weight": 0, @@ -5655,12 +5647,6 @@ "duration": 100, "entryType": "measure" }, - { - "startTime": 0, - "name": "lh:audit:lazy-third-party", - "duration": 100, - "entryType": "measure" - }, { "startTime": 0, "name": "lh:audit:largest-contentful-paint-element", @@ -6924,12 +6910,6 @@ "lighthouse-core/lib/i18n/i18n.js | columnBlockingTime": [ "audits[third-party-summary].details.headings[2].text" ], - "lighthouse-core/audits/lazy-third-party.js | title": [ - "audits[lazy-third-party].title" - ], - "lighthouse-core/audits/lazy-third-party.js | description": [ - "audits[lazy-third-party].description" - ], "lighthouse-core/audits/largest-contentful-paint-element.js | title": [ "audits[largest-contentful-paint-element].title" ], From 34648e8b337295e5c4f133051b71bee4f1087ed2 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Mon, 24 Aug 2020 13:37:15 -0400 Subject: [PATCH 19/82] fix start end time bug --- lighthouse-core/audits/third-party-summary.js | 4 ++++ lighthouse-core/test/audits/third-party-summary-test.js | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/lighthouse-core/audits/third-party-summary.js b/lighthouse-core/audits/third-party-summary.js index 0c104b31208d..c34e7dcc19f9 100644 --- a/lighthouse-core/audits/third-party-summary.js +++ b/lighthouse-core/audits/third-party-summary.js @@ -115,6 +115,8 @@ class ThirdPartySummary extends Audit { const urlSummary = byURL.get(attributableURL) || {...defaultSummary}; const taskDuration = task.selfTime * cpuMultiplier; + urlSummary.startTime = Math.min(urlSummary.startTime, task.startTime); + urlSummary.endTime = Math.max(urlSummary.endTime, task.endTime); // The amount of time spent on main thread is the sum of all durations. urlSummary.mainThreadTime += taskDuration; // The amount of time spent *blocking* on main thread is the sum of all time longer than 50ms. @@ -138,6 +140,8 @@ class ThirdPartySummary extends Audit { entitySummary.transferSize += urlSummary.transferSize; entitySummary.mainThreadTime += urlSummary.mainThreadTime; entitySummary.blockingTime += urlSummary.blockingTime; + entitySummary.startTime = Math.min(entitySummary.startTime, urlSummary.startTime); + entitySummary.endTime = Math.max(entitySummary.endTime, urlSummary.endTime); byEntity.set(entity, entitySummary); const entityURLs = urls.get(entity) || []; diff --git a/lighthouse-core/test/audits/third-party-summary-test.js b/lighthouse-core/test/audits/third-party-summary-test.js index bb08661ac776..1e6fcd116309 100644 --- a/lighthouse-core/test/audits/third-party-summary-test.js +++ b/lighthouse-core/test/audits/third-party-summary-test.js @@ -37,12 +37,16 @@ describe('Third party summary', () => { mainThreadTime: 127.15300000000003, blockingTime: 18.186999999999998, transferSize: 30827, + startTime: 1017.212, + endTime: 225415.177259, subItems: { items: [ { blockingTime: 18.186999999999998, mainThreadTime: 127.15300000000003, transferSize: 30827, + startTime: 1017.212, + endTime: 225415.177259, url: 'https://www.googletagmanager.com/gtm.js?id=GTM-Q5SW', }, ], @@ -58,12 +62,16 @@ describe('Third party summary', () => { mainThreadTime: 95.15599999999999, blockingTime: 0, transferSize: 20913, + startTime: 1344.435, + endTime: 225416.070654, subItems: { items: [ { blockingTime: 0, mainThreadTime: 55.246999999999986, transferSize: 12906, + startTime: 1531.026, + endTime: 225415.698851, url: 'https://www.google-analytics.com/analytics.js', }, { From 6ff862c44e78fe0145c83c16763d8c27cdd9c9e4 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Mon, 24 Aug 2020 13:43:49 -0400 Subject: [PATCH 20/82] update sample --- lighthouse-core/test/results/sample_v2.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lighthouse-core/test/results/sample_v2.json b/lighthouse-core/test/results/sample_v2.json index 662cabe33a3f..2b5ddd4b68b4 100644 --- a/lighthouse-core/test/results/sample_v2.json +++ b/lighthouse-core/test/results/sample_v2.json @@ -1702,8 +1702,8 @@ "mainThreadTime": 90.36300000000001, "blockingTime": 22.918000000000006, "transferSize": 30174, - "startTime": null, - "endTime": 0, + "startTime": 4808.602, + "endTime": 185608.117509, "entity": { "type": "link", "text": "Google CDN", @@ -1717,7 +1717,7 @@ "mainThreadTime": 90.36300000000001, "blockingTime": 22.918000000000006, "transferSize": 30174, - "startTime": 185607.195975, + "startTime": 4808.602, "endTime": 185608.117509 } ] From 05450bd86f8a9263d57f0822e84dbf888e28c96b Mon Sep 17 00:00:00 2001 From: Adam Raine <6752989+adamraine@users.noreply.github.com> Date: Mon, 24 Aug 2020 13:59:45 -0400 Subject: [PATCH 21/82] Remove unnecessary typedef --- lighthouse-core/lib/third-party-web.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lighthouse-core/lib/third-party-web.js b/lighthouse-core/lib/third-party-web.js index c4f24a7154a1..360a270e826e 100644 --- a/lighthouse-core/lib/third-party-web.js +++ b/lighthouse-core/lib/third-party-web.js @@ -9,7 +9,6 @@ const thirdPartyWeb = require('third-party-web/httparchive-nostats-subset'); /** @typedef {import("third-party-web").IEntity} ThirdPartyEntity */ /** @typedef {import("third-party-web").IProduct} ThirdPartyProduct */ -/** @typedef {import("third-party-web").IFacade} ThirdPartyFacade */ /** * `third-party-web` throws when the passed in string doesn't appear to have any domain whatsoever. From 79a29826c93a007884965b1ac041ba96feb05ad6 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 26 Aug 2020 18:08:26 -0400 Subject: [PATCH 22/82] fix timing start bug --- lighthouse-core/audits/third-party-summary.js | 2 -- lighthouse-core/test/audits/third-party-summary-test.js | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/lighthouse-core/audits/third-party-summary.js b/lighthouse-core/audits/third-party-summary.js index c34e7dcc19f9..2aa1a18cc1a4 100644 --- a/lighthouse-core/audits/third-party-summary.js +++ b/lighthouse-core/audits/third-party-summary.js @@ -115,8 +115,6 @@ class ThirdPartySummary extends Audit { const urlSummary = byURL.get(attributableURL) || {...defaultSummary}; const taskDuration = task.selfTime * cpuMultiplier; - urlSummary.startTime = Math.min(urlSummary.startTime, task.startTime); - urlSummary.endTime = Math.max(urlSummary.endTime, task.endTime); // The amount of time spent on main thread is the sum of all durations. urlSummary.mainThreadTime += taskDuration; // The amount of time spent *blocking* on main thread is the sum of all time longer than 50ms. diff --git a/lighthouse-core/test/audits/third-party-summary-test.js b/lighthouse-core/test/audits/third-party-summary-test.js index 1e6fcd116309..7ac38d41632b 100644 --- a/lighthouse-core/test/audits/third-party-summary-test.js +++ b/lighthouse-core/test/audits/third-party-summary-test.js @@ -37,7 +37,7 @@ describe('Third party summary', () => { mainThreadTime: 127.15300000000003, blockingTime: 18.186999999999998, transferSize: 30827, - startTime: 1017.212, + startTime: 225414.728913, endTime: 225415.177259, subItems: { items: [ @@ -45,7 +45,7 @@ describe('Third party summary', () => { blockingTime: 18.186999999999998, mainThreadTime: 127.15300000000003, transferSize: 30827, - startTime: 1017.212, + startTime: 225414.728913, endTime: 225415.177259, url: 'https://www.googletagmanager.com/gtm.js?id=GTM-Q5SW', }, @@ -62,7 +62,7 @@ describe('Third party summary', () => { mainThreadTime: 95.15599999999999, blockingTime: 0, transferSize: 20913, - startTime: 1344.435, + startTime: 225415.251281, endTime: 225416.070654, subItems: { items: [ @@ -70,7 +70,7 @@ describe('Third party summary', () => { blockingTime: 0, mainThreadTime: 55.246999999999986, transferSize: 12906, - startTime: 1531.026, + startTime: 225415.251281, endTime: 225415.698851, url: 'https://www.google-analytics.com/analytics.js', }, From 707fe727fb0d3eee981aaa722341c1c6385a7409 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 26 Aug 2020 18:08:33 -0400 Subject: [PATCH 23/82] move to default config --- lighthouse-core/config/default-config.js | 2 ++ lighthouse-core/config/experimental-config.js | 8 -------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/lighthouse-core/config/default-config.js b/lighthouse-core/config/default-config.js index 4b6db5016b25..76a97ca612dc 100644 --- a/lighthouse-core/config/default-config.js +++ b/lighthouse-core/config/default-config.js @@ -235,6 +235,7 @@ const defaultConfig = { 'timing-budget', 'resource-summary', 'third-party-summary', + 'lazy-third-party', 'largest-contentful-paint-element', 'layout-shift-elements', 'long-tasks', @@ -467,6 +468,7 @@ const defaultConfig = { {id: 'timing-budget', weight: 0, group: 'budgets'}, {id: 'resource-summary', weight: 0, group: 'diagnostics'}, {id: 'third-party-summary', weight: 0, group: 'diagnostics'}, + {id: 'lazy-third-party', weight: 0, group: 'diagnostics'}, {id: 'largest-contentful-paint-element', weight: 0, group: 'diagnostics'}, {id: 'layout-shift-elements', weight: 0, group: 'diagnostics'}, {id: 'uses-passive-event-listeners', weight: 0, group: 'diagnostics'}, diff --git a/lighthouse-core/config/experimental-config.js b/lighthouse-core/config/experimental-config.js index 30119b3d0e83..2c7519602186 100644 --- a/lighthouse-core/config/experimental-config.js +++ b/lighthouse-core/config/experimental-config.js @@ -16,7 +16,6 @@ const config = { audits: [ 'autocomplete', 'full-page-screenshot', - 'lazy-third-party', ], passes: [{ passName: 'defaultPass', @@ -25,13 +24,6 @@ const config = { ], }], categories: { - // @ts-ignore: `title` is required in CategoryJson. setting to the same value as the default - // config is awkward - easier to omit the property here. Will defer to default config. - 'performance': { - auditRefs: [ - {id: 'lazy-third-party', weight: 0, group: 'diagnostics'}, - ], - }, // @ts-ignore: `title` is required in CategoryJson. setting to the same value as the default // config is awkward - easier to omit the property here. Will defer to default config. 'best-practices': { From fdefa48859bf5d22cc2cb10738fa71fa5cbd3f57 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 26 Aug 2020 18:09:16 -0400 Subject: [PATCH 24/82] update sample --- lighthouse-core/test/results/sample_v2.json | 28 +++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/lighthouse-core/test/results/sample_v2.json b/lighthouse-core/test/results/sample_v2.json index 2b5ddd4b68b4..525715c7bf1b 100644 --- a/lighthouse-core/test/results/sample_v2.json +++ b/lighthouse-core/test/results/sample_v2.json @@ -1702,7 +1702,7 @@ "mainThreadTime": 90.36300000000001, "blockingTime": 22.918000000000006, "transferSize": 30174, - "startTime": 4808.602, + "startTime": 185607.195975, "endTime": 185608.117509, "entity": { "type": "link", @@ -1717,7 +1717,7 @@ "mainThreadTime": 90.36300000000001, "blockingTime": 22.918000000000006, "transferSize": 30174, - "startTime": 4808.602, + "startTime": 185607.195975, "endTime": 185608.117509 } ] @@ -1730,6 +1730,13 @@ } } }, + "lazy-third-party": { + "id": "lazy-third-party", + "title": "Lazy load third-party resources", + "description": "Some third-party resources can be fetched after the page loads. These third-party resources are used by embedded elements which can be replaced by a facade until the user needs to use them. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).", + "score": null, + "scoreDisplayMode": "notApplicable" + }, "largest-contentful-paint-element": { "id": "largest-contentful-paint-element", "title": "Largest Contentful Paint element", @@ -4455,6 +4462,11 @@ "weight": 0, "group": "diagnostics" }, + { + "id": "lazy-third-party", + "weight": 0, + "group": "diagnostics" + }, { "id": "largest-contentful-paint-element", "weight": 0, @@ -5647,6 +5659,12 @@ "duration": 100, "entryType": "measure" }, + { + "startTime": 0, + "name": "lh:audit:lazy-third-party", + "duration": 100, + "entryType": "measure" + }, { "startTime": 0, "name": "lh:audit:largest-contentful-paint-element", @@ -6910,6 +6928,12 @@ "lighthouse-core/lib/i18n/i18n.js | columnBlockingTime": [ "audits[third-party-summary].details.headings[2].text" ], + "lighthouse-core/audits/lazy-third-party.js | title": [ + "audits[lazy-third-party].title" + ], + "lighthouse-core/audits/lazy-third-party.js | description": [ + "audits[lazy-third-party].description" + ], "lighthouse-core/audits/largest-contentful-paint-element.js | title": [ "audits[largest-contentful-paint-element].title" ], From 2a1284e6f8fca2eb86e430fa89b2bdd2ca552a3f Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 26 Aug 2020 18:10:02 -0400 Subject: [PATCH 25/82] update index snapshot --- lighthouse-cli/test/cli/__snapshots__/index-test.js.snap | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap b/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap index 65912628e525..7acae0f230d6 100644 --- a/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap +++ b/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap @@ -150,6 +150,9 @@ Object { Object { "path": "third-party-summary", }, + Object { + "path": "lazy-third-party", + }, Object { "path": "largest-contentful-paint-element", }, @@ -993,6 +996,11 @@ Object { "id": "third-party-summary", "weight": 0, }, + Object { + "group": "diagnostics", + "id": "lazy-third-party", + "weight": 0, + }, Object { "group": "diagnostics", "id": "largest-contentful-paint-element", From ad69849189010e0ab05d95179dcba6e521e21684 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 9 Sep 2020 16:25:16 -0400 Subject: [PATCH 26/82] nits --- lighthouse-core/audits/lazy-third-party.js | 35 ++++++++++++---------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js index bbb6cf454c8e..4ebbab0fab98 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/lazy-third-party.js @@ -5,6 +5,11 @@ */ 'use strict'; +/** + * @fileoverview Audit which identifies third-party code on the page which can be lazy loaded. + * The audit will recommend a facade alternative which is used to imitate the third party resource until it is needed. + */ + const Audit = require('./audit.js'); const i18n = require('../lib/i18n/i18n.js'); const thirdPartyWeb = require('../lib/third-party-web.js'); @@ -29,7 +34,7 @@ const UIStrings = { }`, /** Label for a table column that displays the name of a lazy loading facade alternative for a third party resource. Lazy loading means loading resources is deferred until they are needed. */ columnFacade: 'Facade Alternative', - /** Label for a table column that displays the name of the third party product that a URL is used for. Lazy loading means loading resources is deferred until they are needed. */ + /** Label for a table column that displays the name of the third party product that a URL is used for. */ columnProduct: 'Product', }; @@ -66,12 +71,12 @@ class LazyThirdParty extends Audit { for (const [url, urlSummary] of byURL) { const entity = thirdPartyWeb.getEntity(url); const product = thirdPartyWeb.getProduct(url); - if (!entity || mainEntity && entity.name === mainEntity.name) continue; + if (!entity || thirdPartyWeb.isFirstParty(url, mainEntity)) continue; /** @type {Map} */ const productSummaries = entitySummaries.get(entity.name) || new Map(); if (product && product.facades && product.facades.length) { - // Record new url if product has a facade + // Record new url if product has a facade. const productSummary = productSummaries.get(product.name) || { product, cutoffTime: Infinity, @@ -117,18 +122,19 @@ class LazyThirdParty extends Audit { const tasks = await MainThreadTasks.request(trace, context); const multiplier = settings.throttlingMethod === 'simulate' ? settings.throttling.cpuSlowdownMultiplier : 1; - const {byURL} = ThirdPartySummary.getSummaries(networkRecords, tasks, multiplier); - const productSummaries = LazyThirdParty.getProductSummaries(byURL, mainEntity); + const thirdPartySummaries = ThirdPartySummary.getSummaries(networkRecords, tasks, multiplier); + const productSummaries + = LazyThirdParty.getProductSummaries(thirdPartySummaries.byURL, mainEntity); const summary = {wastedBytes: 0, wastedMs: 0}; - /** @type LH.Audit.Details.TableItem[] */ + /** @type {LH.Audit.Details.TableItem[]} */ const results = []; for (const productSummary of productSummaries) { const product = productSummary.product; if (!product.facades || !product.facades.length) continue; - // The first facade should always be the best one + // The first facade should always be the best one. const bestFacade = product.facades[0]; const items = []; @@ -139,8 +145,8 @@ class LazyThirdParty extends Audit { transferSize += urlStats.transferSize; blockingTime += urlStats.blockingTime; } - items.sort((firstEl, secondEl) => { - return secondEl.transferSize - firstEl.transferSize; + items.sort((a, b) => { + return b.transferSize - a.transferSize; }); summary.wastedBytes += transferSize; summary.wastedMs += blockingTime; @@ -166,13 +172,12 @@ class LazyThirdParty extends Audit { /** @type {LH.Audit.Details.Table['headings']} */ const headings = [ - {key: 'productName', itemType: 'text', text: str_(UIStrings.columnProduct), - subItemsHeading: {key: 'url', itemType: 'url'}}, + /* eslint-disable max-len */ + {key: 'productName', itemType: 'text', subItemsHeading: {key: 'url', itemType: 'url'}, text: str_(UIStrings.columnProduct)}, {key: 'facade', itemType: 'link', text: str_(UIStrings.columnFacade)}, - {key: 'transferSize', granularity: 1, itemType: 'bytes', - text: str_(i18n.UIStrings.columnTransferSize), subItemsHeading: {key: 'transferSize'}}, - {key: 'blockingTime', granularity: 1, itemType: 'ms', - text: str_(i18n.UIStrings.columnBlockingTime), subItemsHeading: {key: 'blockingTime'}}, + {key: 'transferSize', granularity: 1, itemType: 'bytes', subItemsHeading: {key: 'transferSize'}, text: str_(i18n.UIStrings.columnTransferSize)}, + {key: 'blockingTime', granularity: 1, itemType: 'ms', subItemsHeading: {key: 'blockingTime'}, text: str_(i18n.UIStrings.columnBlockingTime)}, + /* eslint-enable max-len */ ]; return { From 7c6dc127fabf88529de6c8643d473ac8129ad310 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 9 Sep 2020 16:47:48 -0400 Subject: [PATCH 27/82] definitions --- lighthouse-core/audits/lazy-third-party.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js index 4ebbab0fab98..ae99802e2e6e 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/lazy-third-party.js @@ -8,6 +8,10 @@ /** * @fileoverview Audit which identifies third-party code on the page which can be lazy loaded. * The audit will recommend a facade alternative which is used to imitate the third party resource until it is needed. + * + * Entity: Set of domains which are used by a company or product area to deliver third party resources + * Product: Specific piece of software belonging to an entity. Entities can have multiple products. + * Facade: Placeholder for a product which looks likes the actual product and replaces itself with that product when the user needs it. */ const Audit = require('./audit.js'); From b17c292e601629d72815957e2776cc5110dc3f96 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 9 Sep 2020 17:41:54 -0400 Subject: [PATCH 28/82] add smoke test --- .../test/fixtures/perf/third-party.html | 14 ++++ .../test-definitions/perf/expectations.js | 70 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 lighthouse-cli/test/fixtures/perf/third-party.html diff --git a/lighthouse-cli/test/fixtures/perf/third-party.html b/lighthouse-cli/test/fixtures/perf/third-party.html new file mode 100644 index 000000000000..57ab91a4f85b --- /dev/null +++ b/lighthouse-cli/test/fixtures/perf/third-party.html @@ -0,0 +1,14 @@ + + + + + +
AAAAAAAAAAAAAAAAAAA
+ + + + diff --git a/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js b/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js index dec7c2e6533f..cb7aadbb0502 100644 --- a/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js +++ b/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js @@ -343,4 +343,74 @@ module.exports = [ }, }, }, + { + lhr: { + requestedUrl: 'http://localhost:10200/perf/third-party.html', + finalUrl: 'http://localhost:10200/perf/third-party.html', + audits: { + 'lazy-third-party': { + score: 0, + displayValue: '1 facade alternative available', + details: { + items: [ + { + productName: 'YouTube Embedded Player', + facade: { + type: 'link', + text: 'Lite YouTube', + url: 'https://github.com/paulirish/lite-youtube-embed', + }, + blockingTime: 0, + subItems: { + type: 'subitems', + items: [ + { + url: 'https://www.youtube.com/s/player/8c24a503/player_ias.vflset/en_US/base.js', + mainThreadTime: 0, + blockingTime: 0, + }, + { + url: 'https://i.ytimg.com/vi/tgbNymZ7vqY/maxresdefault.jpg', + mainThreadTime: 0, + blockingTime: 0, + }, + { + url: 'https://www.youtube.com/s/player/8c24a503/www-embed-player.vflset/www-embed-player.js', + mainThreadTime: 0, + blockingTime: 0, + }, + { + url: 'https://www.youtube.com/s/player/8c24a503/www-player.css', + mainThreadTime: 0, + blockingTime: 0, + }, + { + url: 'https://www.youtube.com/embed/tgbNymZ7vqY', + mainThreadTime: 0, + blockingTime: 0, + }, + { + url: 'https://www.youtube.com/s/player/8c24a503/player_ias.vflset/en_US/embed.js', + mainThreadTime: 0, + blockingTime: 0, + }, + { + url: 'https://www.youtube.com/yts/jsbin/fetch-polyfill-vfl6MZH8P/fetch-polyfill.js', + mainThreadTime: 0, + blockingTime: 0, + }, + { + url: 'https://yt3.ggpht.com/a/AATXAJxtCYVD65XPtigYUOad-Nd2v3EvnXnz__MkJrg=s68-c-k-c0x00ffffff-no-rj', + mainThreadTime: 0, + blockingTime: 0, + }, + ], + }, + }, + ], + }, + }, + }, + }, + }, ]; From 4d56357c29b8b7d0090a937767e1aada88b9b616 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Fri, 11 Sep 2020 12:59:57 -0400 Subject: [PATCH 29/82] nits --- lighthouse-core/audits/lazy-third-party.js | 5 ++++- lighthouse-core/lib/third-party-web.js | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js index ae99802e2e6e..4822c2b427d5 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/lazy-third-party.js @@ -88,6 +88,9 @@ class LazyThirdParty extends Audit { }; productSummary.urlSummaries.set(url, urlSummary); + + // This is the time the product resource is fetched. + // Any resources of the same entity fetched after this point are considered as part of this product. productSummary.cutoffTime = Math.min(productSummary.cutoffTime, urlSummary.endTime); productSummaries.set(product.name, productSummary); @@ -144,7 +147,7 @@ class LazyThirdParty extends Audit { const items = []; let transferSize = 0; let blockingTime = 0; - for (const [url, urlStats] of Array.from(productSummary.urlSummaries)) { + for (const [url, urlStats] of productSummary.urlSummaries) { items.push({url, ...urlStats}); transferSize += urlStats.transferSize; blockingTime += urlStats.blockingTime; diff --git a/lighthouse-core/lib/third-party-web.js b/lighthouse-core/lib/third-party-web.js index 360a270e826e..28e38be808da 100644 --- a/lighthouse-core/lib/third-party-web.js +++ b/lighthouse-core/lib/third-party-web.js @@ -25,6 +25,8 @@ function getEntity(url) { } /** + * `third-party-web` throws when the passed in string doesn't appear to have any domain whatsoever. + * We pass in some not-so-url-like things, so make the dependent-code simpler by making this call safe. * @param {string} url * @return {ThirdPartyProduct|undefined} */ From acb984a280e85fe0d6ac153946e221845cecd818 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Fri, 11 Sep 2020 19:24:29 -0400 Subject: [PATCH 30/82] two pass --- lighthouse-core/audits/lazy-third-party.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js index 4822c2b427d5..041a69271e0f 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/lazy-third-party.js @@ -77,7 +77,6 @@ class LazyThirdParty extends Audit { const product = thirdPartyWeb.getProduct(url); if (!entity || thirdPartyWeb.isFirstParty(url, mainEntity)) continue; - /** @type {Map} */ const productSummaries = entitySummaries.get(entity.name) || new Map(); if (product && product.facades && product.facades.length) { // Record new url if product has a facade. @@ -94,7 +93,17 @@ class LazyThirdParty extends Audit { productSummary.cutoffTime = Math.min(productSummary.cutoffTime, urlSummary.endTime); productSummaries.set(product.name, productSummary); - } else { + } + entitySummaries.set(entity.name, productSummaries); + } + + for (const [url, urlSummary] of byURL) { + const entity = thirdPartyWeb.getEntity(url); + const product = thirdPartyWeb.getProduct(url); + if (!entity || thirdPartyWeb.isFirstParty(url, mainEntity)) continue; + + const productSummaries = entitySummaries.get(entity.name) || new Map(); + if (!product || !product.facades || !product.facades.length) { // If the url does not have a facade but one or more products on its entity do, // we still want to record this url because it was probably fetched by a product with a facade. for (const productSummary of productSummaries.values()) { From b609197742b053879b28e686a05698d11de10975 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 15 Sep 2020 10:21:59 -0400 Subject: [PATCH 31/82] fix timing bugs --- lighthouse-core/audits/lazy-third-party.js | 4 +- lighthouse-core/audits/third-party-summary.js | 46 +++-- .../test/audits/lazy-third-party-test.js | 189 +++++++++++++++++- .../test/audits/third-party-summary-test.js | 12 +- 4 files changed, 218 insertions(+), 33 deletions(-) diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js index 041a69271e0f..4246d6244ad0 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/lazy-third-party.js @@ -90,7 +90,7 @@ class LazyThirdParty extends Audit { // This is the time the product resource is fetched. // Any resources of the same entity fetched after this point are considered as part of this product. - productSummary.cutoffTime = Math.min(productSummary.cutoffTime, urlSummary.endTime); + productSummary.cutoffTime = Math.min(productSummary.cutoffTime, urlSummary.firstEndTime); productSummaries.set(product.name, productSummary); } @@ -107,7 +107,7 @@ class LazyThirdParty extends Audit { // If the url does not have a facade but one or more products on its entity do, // we still want to record this url because it was probably fetched by a product with a facade. for (const productSummary of productSummaries.values()) { - if (urlSummary.startTime < productSummary.cutoffTime) continue; + if (urlSummary.firstStartTime < productSummary.cutoffTime) continue; productSummary.urlSummaries.set(url, urlSummary); } } diff --git a/lighthouse-core/audits/third-party-summary.js b/lighthouse-core/audits/third-party-summary.js index 2aa1a18cc1a4..125ba8418f32 100644 --- a/lighthouse-core/audits/third-party-summary.js +++ b/lighthouse-core/audits/third-party-summary.js @@ -43,11 +43,19 @@ const PASS_THRESHOLD_IN_MS = 250; * mainThreadTime: number, * transferSize: number, * blockingTime: number, - * startTime: number, - * endTime: number, + * firstStartTime: number, + * firstEndTime: number, * }} Summary */ +/** + * @typedef {{ + * mainThreadTime: number, + * transferSize: number, + * blockingTime: number, + * }} EntitySummary + */ + /** * @typedef {{ * transferSize: number, @@ -56,6 +64,12 @@ const PASS_THRESHOLD_IN_MS = 250; * }} URLSummary */ +/** @typedef {{ + * byEntity: Map, + * byURL: Map, + * urls: Map + * }} SummaryMap + */ /** * Don't bother showing resources smaller than 4KiB since they're likely to be pixels, which isn't @@ -85,26 +99,31 @@ class ThirdPartySummary extends Audit { * @param {Array} networkRecords * @param {Array} mainThreadTasks * @param {number} cpuMultiplier - * @return {{byEntity: Map, byURL: Map, urls: Map}} + * @return {SummaryMap} */ static getSummaries(networkRecords, mainThreadTasks, cpuMultiplier) { /** @type {Map} */ const byURL = new Map(); - /** @type {Map} */ + /** @type {Map} */ const byEntity = new Map(); const defaultSummary = { mainThreadTime: 0, blockingTime: 0, transferSize: 0, - startTime: Infinity, - endTime: 0, }; for (const request of networkRecords) { - const urlSummary = byURL.get(request.url) || {...defaultSummary}; + const urlSummary = byURL.get(request.url) || + {...defaultSummary, firstStartTime: Infinity, firstEndTime: Infinity}; urlSummary.transferSize += request.transferSize; - urlSummary.startTime = Math.min(urlSummary.startTime, request.startTime); - urlSummary.endTime = Math.max(urlSummary.endTime, request.endTime); + urlSummary.firstStartTime = Math.min(urlSummary.firstStartTime, request.startTime); + if (request.timing) { + // Lookahead preparser may start requests before entire HTML is loaded + const receiveHeadersEndTime = request.startTime + request.timing.receiveHeadersEnd / 1000; + urlSummary.firstEndTime = Math.min(urlSummary.firstEndTime, receiveHeadersEndTime); + } else { + urlSummary.firstEndTime = Math.min(urlSummary.firstEndTime, request.endTime); + } byURL.set(request.url, urlSummary); } @@ -113,7 +132,8 @@ class ThirdPartySummary extends Audit { for (const task of mainThreadTasks) { const attributableURL = BootupTime.getAttributableURLForTask(task, jsURLs); - const urlSummary = byURL.get(attributableURL) || {...defaultSummary}; + const urlSummary = byURL.get(attributableURL) || + {...defaultSummary, firstStartTime: Infinity, firstEndTime: Infinity}; const taskDuration = task.selfTime * cpuMultiplier; // The amount of time spent on main thread is the sum of all durations. urlSummary.mainThreadTime += taskDuration; @@ -138,8 +158,6 @@ class ThirdPartySummary extends Audit { entitySummary.transferSize += urlSummary.transferSize; entitySummary.mainThreadTime += urlSummary.mainThreadTime; entitySummary.blockingTime += urlSummary.blockingTime; - entitySummary.startTime = Math.min(entitySummary.startTime, urlSummary.startTime); - entitySummary.endTime = Math.max(entitySummary.endTime, urlSummary.endTime); byEntity.set(entity, entitySummary); const entityURLs = urls.get(entity) || []; @@ -152,8 +170,8 @@ class ThirdPartySummary extends Audit { /** * @param {ThirdPartyEntity} entity - * @param {{byEntity: Map, byURL: Map, urls: Map}} summaries - * @param {Summary} stats + * @param {SummaryMap} summaries + * @param {EntitySummary} stats * @return {Array} */ static makeSubItems(entity, summaries, stats) { diff --git a/lighthouse-core/test/audits/lazy-third-party-test.js b/lighthouse-core/test/audits/lazy-third-party-test.js index 2d7b5a365dec..1d3d9e64e8d7 100644 --- a/lighthouse-core/test/audits/lazy-third-party-test.js +++ b/lighthouse-core/test/audits/lazy-third-party-test.js @@ -20,21 +20,192 @@ describe('Lazy load third party resources', () => { devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ { url: 'https://example.com', - startTime: 0, - endTime: 50, + startTime: 100, + endTime: 101, transferSize: 2000, + timing: { + receiveHeadersEnd: 500, + }, }, { url: 'https://widget.intercom.io/widget/tx2p130c', - startTime: 100, - endTime: 150, + startTime: 200, + endTime: 201, transferSize: 4000, + timing: { + receiveHeadersEnd: 500, + }, + }, + { + url: 'https://js.intercomcdn.com/frame-modern.bb95039c.js', + startTime: 300, + endTime: 301, + transferSize: 8000, + timing: { + receiveHeadersEnd: 500, + }, + }, + ])}, + traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, + URL: {finalUrl: 'https://example.com'}, + }; + + const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; + const results = await LazyThirdParty.audit(artifacts, {computedCache: new Map(), settings}); + + expect(results.score).toBe(0); + expect(results.displayValue).toBeDisplayString('1 facade alternative available'); + expect(results.details.items).toEqual([ + { + productName: 'Intercom Widget', + facade: { + type: 'link', + text: 'React Live Chat Loader', + url: 'https://github.com/calibreapp/react-live-chat-loader', + }, + transferSize: 12000, + blockingTime: 0, + subItems: {type: 'subitems', items: [ + { + url: 'https://js.intercomcdn.com/frame-modern.bb95039c.js', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 8000, + firstStartTime: 300, + firstEndTime: 300.5, + }, + { + url: 'https://widget.intercom.io/widget/tx2p130c', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 4000, + firstStartTime: 200, + firstEndTime: 200.5, + }, + ]}, + }, + ]); + }); + + it('use first of multiple requests to product resource', async () => { + const artifacts = { + devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ + { + url: 'https://example.com', + startTime: 100, + endTime: 101, + transferSize: 2000, + timing: { + receiveHeadersEnd: 500, + }, + }, + { + url: 'https://widget.intercom.io/widget/tx2p130c', + startTime: 200, + endTime: 201, + transferSize: 2000, + timing: { + receiveHeadersEnd: 500, + }, }, { url: 'https://js.intercomcdn.com/frame-modern.bb95039c.js', + startTime: 300, + endTime: 301, + transferSize: 8000, + timing: { + receiveHeadersEnd: 500, + }, + }, + { + url: 'https://widget.intercom.io/widget/tx2p130c', + startTime: 400, + endTime: 401, + transferSize: 2000, + timing: { + receiveHeadersEnd: 500, + }, + }, + ])}, + traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, + URL: {finalUrl: 'https://example.com'}, + }; + + const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; + const results = await LazyThirdParty.audit(artifacts, {computedCache: new Map(), settings}); + + expect(results.score).toBe(0); + expect(results.displayValue).toBeDisplayString('1 facade alternative available'); + expect(results.details.items).toEqual([ + { + productName: 'Intercom Widget', + facade: { + type: 'link', + text: 'React Live Chat Loader', + url: 'https://github.com/calibreapp/react-live-chat-loader', + }, + transferSize: 12000, + blockingTime: 0, + subItems: {type: 'subitems', items: [ + { + url: 'https://js.intercomcdn.com/frame-modern.bb95039c.js', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 8000, + firstStartTime: 300, + firstEndTime: 300.5, + }, + { + url: 'https://widget.intercom.io/widget/tx2p130c', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 4000, + firstStartTime: 200, + firstEndTime: 200.5, + }, + ]}, + }, + ]); + }); + + it('uses receiveHeadersEnd as cutoff', async () => { + const artifacts = { + devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ + { + url: 'https://example.com', + startTime: 100, + endTime: 101, + transferSize: 2000, + timing: { + receiveHeadersEnd: 500, + }, + }, + { + url: 'https://widget.intercom.io/widget/tx2p130c', startTime: 200, - endTime: 250, + endTime: 202, + transferSize: 4000, + timing: { + receiveHeadersEnd: 1000, + }, + }, + { + url: 'https://js.intercomcdn.com/frame-modern.aaaaaaaaa.js', + startTime: 200.5, // Between startTime and startTime + receiveHeadersEnd, so it is ignored + endTime: 205, + transferSize: 8000, + timing: { + receiveHeadersEnd: 500, + }, + }, + { + url: 'https://js.intercomcdn.com/frame-modern.bb95039c.js', + startTime: 201.5, // Between startTime + receiveHeadersEnd and endTime, so it is included + endTime: 205, transferSize: 8000, + timing: { + receiveHeadersEnd: 500, + }, }, ])}, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, @@ -62,16 +233,16 @@ describe('Lazy load third party resources', () => { mainThreadTime: 0, blockingTime: 0, transferSize: 8000, - startTime: 200, - endTime: 250, + firstStartTime: 201.5, + firstEndTime: 202, }, { url: 'https://widget.intercom.io/widget/tx2p130c', mainThreadTime: 0, blockingTime: 0, transferSize: 4000, - startTime: 100, - endTime: 150, + firstStartTime: 200, + firstEndTime: 201, }, ]}, }, diff --git a/lighthouse-core/test/audits/third-party-summary-test.js b/lighthouse-core/test/audits/third-party-summary-test.js index 7ac38d41632b..ba981027cc5d 100644 --- a/lighthouse-core/test/audits/third-party-summary-test.js +++ b/lighthouse-core/test/audits/third-party-summary-test.js @@ -37,16 +37,14 @@ describe('Third party summary', () => { mainThreadTime: 127.15300000000003, blockingTime: 18.186999999999998, transferSize: 30827, - startTime: 225414.728913, - endTime: 225415.177259, subItems: { items: [ { blockingTime: 18.186999999999998, mainThreadTime: 127.15300000000003, transferSize: 30827, - startTime: 225414.728913, - endTime: 225415.177259, + firstStartTime: 225414.728913, + firstEndTime: 225414.940324, url: 'https://www.googletagmanager.com/gtm.js?id=GTM-Q5SW', }, ], @@ -62,16 +60,14 @@ describe('Third party summary', () => { mainThreadTime: 95.15599999999999, blockingTime: 0, transferSize: 20913, - startTime: 225415.251281, - endTime: 225416.070654, subItems: { items: [ { blockingTime: 0, mainThreadTime: 55.246999999999986, transferSize: 12906, - startTime: 225415.251281, - endTime: 225415.698851, + firstStartTime: 225415.251281, + firstEndTime: 225415.469618, url: 'https://www.google-analytics.com/analytics.js', }, { From fce91cd02bf03d597480205e4d5b06b96ca13e9e Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 15 Sep 2020 11:22:09 -0400 Subject: [PATCH 32/82] nits --- lighthouse-core/audits/lazy-third-party.js | 25 ++++++++++++------- .../test/audits/lazy-third-party-test.js | 5 ++-- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/lazy-third-party.js index 4246d6244ad0..84fd63e94893 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/lazy-third-party.js @@ -46,8 +46,14 @@ const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings); /** @typedef {import("third-party-web").IEntity} ThirdPartyEntity */ /** @typedef {import("third-party-web").IProduct} ThirdPartyProduct*/ +/** @typedef {import("third-party-web").IFacade} ThirdPartyFacade*/ -/** @typedef {{product: ThirdPartyProduct, cutoffTime: number, urlSummaries: Map}} ProductSummary */ +/** @typedef {{ + * product: ThirdPartyProduct & {facades: ThirdPartyFacade[]}, + * cutoffTime: number, + * urlSummaries: Map + * }} FacadableProductSummary + */ class LazyThirdParty extends Audit { /** @@ -66,20 +72,22 @@ class LazyThirdParty extends Audit { /** * @param {Map} byURL * @param {ThirdPartyEntity | undefined} mainEntity - * @return {ProductSummary[]} + * @return {FacadableProductSummary[]} */ - static getProductSummaries(byURL, mainEntity) { - /** @type {Map>} */ + static getFacadableProductSummaries(byURL, mainEntity) { + /** @type {Map>} */ const entitySummaries = new Map(); for (const [url, urlSummary] of byURL) { const entity = thirdPartyWeb.getEntity(url); - const product = thirdPartyWeb.getProduct(url); if (!entity || thirdPartyWeb.isFirstParty(url, mainEntity)) continue; const productSummaries = entitySummaries.get(entity.name) || new Map(); + const product = thirdPartyWeb.getProduct(url); if (product && product.facades && product.facades.length) { // Record new url if product has a facade. + + /** @type {FacadableProductSummary} */ const productSummary = productSummaries.get(product.name) || { product, cutoffTime: Infinity, @@ -99,10 +107,10 @@ class LazyThirdParty extends Audit { for (const [url, urlSummary] of byURL) { const entity = thirdPartyWeb.getEntity(url); - const product = thirdPartyWeb.getProduct(url); if (!entity || thirdPartyWeb.isFirstParty(url, mainEntity)) continue; const productSummaries = entitySummaries.get(entity.name) || new Map(); + const product = thirdPartyWeb.getProduct(url); if (!product || !product.facades || !product.facades.length) { // If the url does not have a facade but one or more products on its entity do, // we still want to record this url because it was probably fetched by a product with a facade. @@ -129,7 +137,7 @@ class LazyThirdParty extends Audit { * @return {Promise} */ static async audit(artifacts, context) { - const settings = context.settings || {}; + const settings = context.settings; const trace = artifacts.traces[Audit.DEFAULT_PASS]; const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS]; const networkRecords = await NetworkRecords.request(devtoolsLog, context); @@ -140,7 +148,7 @@ class LazyThirdParty extends Audit { settings.throttling.cpuSlowdownMultiplier : 1; const thirdPartySummaries = ThirdPartySummary.getSummaries(networkRecords, tasks, multiplier); const productSummaries - = LazyThirdParty.getProductSummaries(thirdPartySummaries.byURL, mainEntity); + = LazyThirdParty.getFacadableProductSummaries(thirdPartySummaries.byURL, mainEntity); const summary = {wastedBytes: 0, wastedMs: 0}; @@ -148,7 +156,6 @@ class LazyThirdParty extends Audit { const results = []; for (const productSummary of productSummaries) { const product = productSummary.product; - if (!product.facades || !product.facades.length) continue; // The first facade should always be the best one. const bestFacade = product.facades[0]; diff --git a/lighthouse-core/test/audits/lazy-third-party-test.js b/lighthouse-core/test/audits/lazy-third-party-test.js index 1d3d9e64e8d7..841def96d2be 100644 --- a/lighthouse-core/test/audits/lazy-third-party-test.js +++ b/lighthouse-core/test/audits/lazy-third-party-test.js @@ -87,7 +87,7 @@ describe('Lazy load third party resources', () => { ]); }); - it('use first of multiple requests to product resource', async () => { + it('handle multiple requests to same product resource', async () => { const artifacts = { devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ { @@ -268,8 +268,9 @@ describe('Lazy load third party resources', () => { }); }); - it('only reports resources which can be lazy loaded', async () => { + it('only reports resources which have facade alternatives', async () => { const artifacts = { + // This devtools log has third party requests but none have facades devtoolsLogs: {defaultPass: pwaDevtoolsLog}, traces: {defaultPass: pwaTrace}, URL: {finalUrl: 'https://pwa-rocks.com'}, From c2f07e25d292a3b7baac5ce61a6904bd611ab91f Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 15 Sep 2020 12:08:48 -0400 Subject: [PATCH 33/82] update test case structure --- .../test/audits/lazy-third-party-test.js | 175 ++++++------------ 1 file changed, 58 insertions(+), 117 deletions(-) diff --git a/lighthouse-core/test/audits/lazy-third-party-test.js b/lighthouse-core/test/audits/lazy-third-party-test.js index 841def96d2be..e37a0f8a4a9c 100644 --- a/lighthouse-core/test/audits/lazy-third-party-test.js +++ b/lighthouse-core/test/audits/lazy-third-party-test.js @@ -13,38 +13,36 @@ const pwaTrace = require('../fixtures/traces/progressive-app-m60.json'); const pwaDevtoolsLog = require('../fixtures/traces/progressive-app-m60.devtools.log.json'); const noThirdPartyTrace = require('../fixtures/traces/no-tracingstarted-m74.json'); +function resourceEntry(startTime, headerEndTime, endTime, transferSize, url) { + return { + url, + startTime, + endTime, + transferSize, + timing: { + receiveHeadersEnd: (headerEndTime - startTime) * 1000, + }, + }; +} + +function facadableProductEntry(startTime, headerEndTime, endTime, transferSize, id) { + const url = `https://widget.intercom.io/widget/${id}`; + return resourceEntry(startTime, headerEndTime, endTime, transferSize, url); +} + +function entityResourceEntry(startTime, headerEndTime, endTime, transferSize, id) { + const url = `https://js.intercomcdn.com/frame-modern.${id}.js`; + return resourceEntry(startTime, headerEndTime, endTime, transferSize, url); +} + /* eslint-env jest */ describe('Lazy load third party resources', () => { it('correctly identifies a lazy loadable third party resource', async () => { const artifacts = { devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ - { - url: 'https://example.com', - startTime: 100, - endTime: 101, - transferSize: 2000, - timing: { - receiveHeadersEnd: 500, - }, - }, - { - url: 'https://widget.intercom.io/widget/tx2p130c', - startTime: 200, - endTime: 201, - transferSize: 4000, - timing: { - receiveHeadersEnd: 500, - }, - }, - { - url: 'https://js.intercomcdn.com/frame-modern.bb95039c.js', - startTime: 300, - endTime: 301, - transferSize: 8000, - timing: { - receiveHeadersEnd: 500, - }, - }, + resourceEntry(100, 101, 102, 2000, 'https://example.com'), + facadableProductEntry(200, 201, 202, 4000, '1'), + entityResourceEntry(300, 301, 302, 8000, 'a'), ])}, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, URL: {finalUrl: 'https://example.com'}, @@ -67,20 +65,20 @@ describe('Lazy load third party resources', () => { blockingTime: 0, subItems: {type: 'subitems', items: [ { - url: 'https://js.intercomcdn.com/frame-modern.bb95039c.js', + url: 'https://js.intercomcdn.com/frame-modern.a.js', mainThreadTime: 0, blockingTime: 0, transferSize: 8000, firstStartTime: 300, - firstEndTime: 300.5, + firstEndTime: 301, }, { - url: 'https://widget.intercom.io/widget/tx2p130c', + url: 'https://widget.intercom.io/widget/1', mainThreadTime: 0, blockingTime: 0, transferSize: 4000, firstStartTime: 200, - firstEndTime: 200.5, + firstEndTime: 201, }, ]}, }, @@ -90,42 +88,11 @@ describe('Lazy load third party resources', () => { it('handle multiple requests to same product resource', async () => { const artifacts = { devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ - { - url: 'https://example.com', - startTime: 100, - endTime: 101, - transferSize: 2000, - timing: { - receiveHeadersEnd: 500, - }, - }, - { - url: 'https://widget.intercom.io/widget/tx2p130c', - startTime: 200, - endTime: 201, - transferSize: 2000, - timing: { - receiveHeadersEnd: 500, - }, - }, - { - url: 'https://js.intercomcdn.com/frame-modern.bb95039c.js', - startTime: 300, - endTime: 301, - transferSize: 8000, - timing: { - receiveHeadersEnd: 500, - }, - }, - { - url: 'https://widget.intercom.io/widget/tx2p130c', - startTime: 400, - endTime: 401, - transferSize: 2000, - timing: { - receiveHeadersEnd: 500, - }, - }, + resourceEntry(100, 101, 102, 2000, 'https://example.com'), + // The first product entry is used for the cutoff time + facadableProductEntry(200, 201, 202, 2000, '1'), + entityResourceEntry(300, 301, 302, 8000, 'a'), + facadableProductEntry(400, 401, 402, 2000, '1'), ])}, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, URL: {finalUrl: 'https://example.com'}, @@ -148,20 +115,20 @@ describe('Lazy load third party resources', () => { blockingTime: 0, subItems: {type: 'subitems', items: [ { - url: 'https://js.intercomcdn.com/frame-modern.bb95039c.js', + url: 'https://js.intercomcdn.com/frame-modern.a.js', mainThreadTime: 0, blockingTime: 0, transferSize: 8000, firstStartTime: 300, - firstEndTime: 300.5, + firstEndTime: 301, }, { - url: 'https://widget.intercom.io/widget/tx2p130c', + url: 'https://widget.intercom.io/widget/1', mainThreadTime: 0, blockingTime: 0, transferSize: 4000, firstStartTime: 200, - firstEndTime: 200.5, + firstEndTime: 201, }, ]}, }, @@ -171,42 +138,14 @@ describe('Lazy load third party resources', () => { it('uses receiveHeadersEnd as cutoff', async () => { const artifacts = { devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ - { - url: 'https://example.com', - startTime: 100, - endTime: 101, - transferSize: 2000, - timing: { - receiveHeadersEnd: 500, - }, - }, - { - url: 'https://widget.intercom.io/widget/tx2p130c', - startTime: 200, - endTime: 202, - transferSize: 4000, - timing: { - receiveHeadersEnd: 1000, - }, - }, - { - url: 'https://js.intercomcdn.com/frame-modern.aaaaaaaaa.js', - startTime: 200.5, // Between startTime and startTime + receiveHeadersEnd, so it is ignored - endTime: 205, - transferSize: 8000, - timing: { - receiveHeadersEnd: 500, - }, - }, - { - url: 'https://js.intercomcdn.com/frame-modern.bb95039c.js', - startTime: 201.5, // Between startTime + receiveHeadersEnd and endTime, so it is included - endTime: 205, - transferSize: 8000, - timing: { - receiveHeadersEnd: 500, - }, - }, + resourceEntry(100, 101, 102, 2000, 'https://example.com'), + facadableProductEntry(200, 205, 210, 4000, '1'), + // Starts between product's startTime and startTime + receiveHeadersEnd, so it is ignored + entityResourceEntry(201, 206, 208, 8000, 'a'), + // Starts between product's startTime + receiveHeadersEnd and endTime, so it is included + entityResourceEntry(206, 208, 215, 8000, 'b'), + // Starts past the cutoff but previous call to same url was before cutoff, so it is ignored + entityResourceEntry(300, 301, 303, 8000, 'a'), ])}, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, URL: {finalUrl: 'https://example.com'}, @@ -229,20 +168,20 @@ describe('Lazy load third party resources', () => { blockingTime: 0, subItems: {type: 'subitems', items: [ { - url: 'https://js.intercomcdn.com/frame-modern.bb95039c.js', + url: 'https://js.intercomcdn.com/frame-modern.b.js', mainThreadTime: 0, blockingTime: 0, transferSize: 8000, - firstStartTime: 201.5, - firstEndTime: 202, + firstStartTime: 206, + firstEndTime: 208, }, { - url: 'https://widget.intercom.io/widget/tx2p130c', + url: 'https://widget.intercom.io/widget/1', mainThreadTime: 0, blockingTime: 0, transferSize: 4000, firstStartTime: 200, - firstEndTime: 201, + firstEndTime: 205, }, ]}, }, @@ -252,11 +191,11 @@ describe('Lazy load third party resources', () => { it('does not report first party resources', async () => { const artifacts = { devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ - {url: 'https://youtube.com'}, - {url: 'https://www.youtube.com/embed/tgbNymZ7vqY'}, + resourceEntry(100, 101, 102, 2000, 'https://intercomcdn.com'), + facadableProductEntry(200, 201, 202, 4000, '1'), ])}, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, - URL: {finalUrl: 'https://youtube.com'}, + URL: {finalUrl: 'https://intercomcdn.com'}, }; const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; @@ -287,9 +226,11 @@ describe('Lazy load third party resources', () => { it('not applicable when no third party resources are present', async () => { const artifacts = { - devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([{url: 'chrome://version'}])}, + devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ + resourceEntry(100, 101, 102, 2000, 'https://example.com'), + ])}, traces: {defaultPass: noThirdPartyTrace}, - URL: {finalUrl: 'chrome://version'}, + URL: {finalUrl: 'https://example.com'}, }; const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; From fe3246e4428b5384929979d7d7aead1ae17c0885 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 15 Sep 2020 12:35:59 -0400 Subject: [PATCH 34/82] add test case --- .../test/audits/lazy-third-party-test.js | 112 ++++++++++++++++-- 1 file changed, 100 insertions(+), 12 deletions(-) diff --git a/lighthouse-core/test/audits/lazy-third-party-test.js b/lighthouse-core/test/audits/lazy-third-party-test.js index e37a0f8a4a9c..184ef47defc2 100644 --- a/lighthouse-core/test/audits/lazy-third-party-test.js +++ b/lighthouse-core/test/audits/lazy-third-party-test.js @@ -25,24 +25,34 @@ function resourceEntry(startTime, headerEndTime, endTime, transferSize, url) { }; } -function facadableProductEntry(startTime, headerEndTime, endTime, transferSize, id) { +function intercomProductEntry(startTime, headerEndTime, endTime, transferSize, id) { const url = `https://widget.intercom.io/widget/${id}`; return resourceEntry(startTime, headerEndTime, endTime, transferSize, url); } -function entityResourceEntry(startTime, headerEndTime, endTime, transferSize, id) { +function intercomResourceEntry(startTime, headerEndTime, endTime, transferSize, id) { const url = `https://js.intercomcdn.com/frame-modern.${id}.js`; return resourceEntry(startTime, headerEndTime, endTime, transferSize, url); } +function youtubeProductEntry(startTime, headerEndTime, endTime, transferSize, id) { + const url = `https://www.youtube.com/embed/${id}`; + return resourceEntry(startTime, headerEndTime, endTime, transferSize, url); +} + +function youtubeResourceEntry(startTime, headerEndTime, endTime, transferSize, id) { + const url = `https://i.ytimg.com/${id}/maxresdefault.jpg`; + return resourceEntry(startTime, headerEndTime, endTime, transferSize, url); +} + /* eslint-env jest */ describe('Lazy load third party resources', () => { it('correctly identifies a lazy loadable third party resource', async () => { const artifacts = { devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ resourceEntry(100, 101, 102, 2000, 'https://example.com'), - facadableProductEntry(200, 201, 202, 4000, '1'), - entityResourceEntry(300, 301, 302, 8000, 'a'), + intercomProductEntry(200, 201, 202, 4000, '1'), + intercomResourceEntry(300, 301, 302, 8000, 'a'), ])}, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, URL: {finalUrl: 'https://example.com'}, @@ -85,14 +95,92 @@ describe('Lazy load third party resources', () => { ]); }); + it('handles multiple products with facades', async () => { + const artifacts = { + devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ + resourceEntry(100, 101, 102, 2000, 'https://example.com'), + intercomProductEntry(200, 201, 202, 4000, '1'), + youtubeProductEntry(210, 211, 212, 3000, '2'), + intercomResourceEntry(300, 301, 302, 8000, 'a'), + youtubeResourceEntry(310, 311, 312, 7000, 'b'), + ])}, + traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, + URL: {finalUrl: 'https://example.com'}, + }; + + const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; + const results = await LazyThirdParty.audit(artifacts, {computedCache: new Map(), settings}); + + expect(results.score).toBe(0); + expect(results.displayValue).toBeDisplayString('2 facade alternatives available'); + expect(results.details.items).toEqual([ + { + productName: 'Intercom Widget', + facade: { + type: 'link', + text: 'React Live Chat Loader', + url: 'https://github.com/calibreapp/react-live-chat-loader', + }, + transferSize: 12000, + blockingTime: 0, + subItems: {type: 'subitems', items: [ + { + url: 'https://js.intercomcdn.com/frame-modern.a.js', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 8000, + firstStartTime: 300, + firstEndTime: 301, + }, + { + url: 'https://widget.intercom.io/widget/1', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 4000, + firstStartTime: 200, + firstEndTime: 201, + }, + ]}, + }, + { + productName: 'YouTube Embedded Player', + facade: { + type: 'link', + text: 'Lite YouTube', + url: 'https://github.com/paulirish/lite-youtube-embed', + }, + transferSize: 10000, + blockingTime: 0, + subItems: {type: 'subitems', items: [ + { + url: 'https://i.ytimg.com/b/maxresdefault.jpg', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 7000, + firstStartTime: 310, + firstEndTime: 311, + }, + { + url: 'https://www.youtube.com/embed/2', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 3000, + firstStartTime: 210, + firstEndTime: 211, + }, + ]}, + }, + ]); + }); + it('handle multiple requests to same product resource', async () => { const artifacts = { devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ resourceEntry(100, 101, 102, 2000, 'https://example.com'), // The first product entry is used for the cutoff time - facadableProductEntry(200, 201, 202, 2000, '1'), - entityResourceEntry(300, 301, 302, 8000, 'a'), - facadableProductEntry(400, 401, 402, 2000, '1'), + intercomProductEntry(200, 201, 202, 2000, '1'), + intercomResourceEntry(300, 301, 302, 8000, 'a'), + intercomProductEntry(400, 401, 402, 2000, '1'), ])}, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, URL: {finalUrl: 'https://example.com'}, @@ -139,13 +227,13 @@ describe('Lazy load third party resources', () => { const artifacts = { devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ resourceEntry(100, 101, 102, 2000, 'https://example.com'), - facadableProductEntry(200, 205, 210, 4000, '1'), + intercomProductEntry(200, 205, 210, 4000, '1'), // Starts between product's startTime and startTime + receiveHeadersEnd, so it is ignored - entityResourceEntry(201, 206, 208, 8000, 'a'), + intercomResourceEntry(201, 206, 208, 8000, 'a'), // Starts between product's startTime + receiveHeadersEnd and endTime, so it is included - entityResourceEntry(206, 208, 215, 8000, 'b'), + intercomResourceEntry(206, 208, 215, 8000, 'b'), // Starts past the cutoff but previous call to same url was before cutoff, so it is ignored - entityResourceEntry(300, 301, 303, 8000, 'a'), + intercomResourceEntry(300, 301, 303, 8000, 'a'), ])}, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, URL: {finalUrl: 'https://example.com'}, @@ -192,7 +280,7 @@ describe('Lazy load third party resources', () => { const artifacts = { devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ resourceEntry(100, 101, 102, 2000, 'https://intercomcdn.com'), - facadableProductEntry(200, 201, 202, 4000, '1'), + intercomProductEntry(200, 201, 202, 4000, '1'), ])}, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, URL: {finalUrl: 'https://intercomcdn.com'}, From bae311b64ecd1e4f908ca43487fba4ba8cbb0372 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 15 Sep 2020 15:08:24 -0400 Subject: [PATCH 35/82] the big rename --- .../test-definitions/perf/expectations.js | 2 +- ...-third-party.js => third-party-facades.js} | 22 +++++++++---------- lighthouse-core/config/default-config.js | 4 ++-- .../html/renderer/report-ui-features.js | 2 +- ...ty-test.js => third-party-facades-test.js} | 20 ++++++++--------- 5 files changed, 25 insertions(+), 25 deletions(-) rename lighthouse-core/audits/{lazy-third-party.js => third-party-facades.js} (85%) rename lighthouse-core/test/audits/{lazy-third-party-test.js => third-party-facades-test.js} (92%) diff --git a/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js b/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js index cb7aadbb0502..11bd783232eb 100644 --- a/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js +++ b/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js @@ -348,7 +348,7 @@ module.exports = [ requestedUrl: 'http://localhost:10200/perf/third-party.html', finalUrl: 'http://localhost:10200/perf/third-party.html', audits: { - 'lazy-third-party': { + 'third-party-facades': { score: 0, displayValue: '1 facade alternative available', details: { diff --git a/lighthouse-core/audits/lazy-third-party.js b/lighthouse-core/audits/third-party-facades.js similarity index 85% rename from lighthouse-core/audits/lazy-third-party.js rename to lighthouse-core/audits/third-party-facades.js index 84fd63e94893..e2ce61e420da 100644 --- a/lighthouse-core/audits/lazy-third-party.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -23,20 +23,20 @@ const MainThreadTasks = require('../computed/main-thread-tasks.js'); const ThirdPartySummary = require('./third-party-summary.js'); const UIStrings = { - /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded. This descriptive title is shown to users when no resources have lazy loading alternatives available. Lazy loading means loading resources is deferred until they are needed. */ - title: 'Lazy load third-party resources', - /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded. This descriptive title is shown to users when one or more third-party resources have available lazy loading alternatives. Lazy loading means loading resources is deferred until they are needed. */ - failureTitle: 'Some third-party resources can be lazy loaded', - /** Description of a Lighthouse audit that identifies the third party code on the page that can be lazy loaded. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. Lazy loading means loading resources is deferred until they are needed. */ + /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded with a facade alternative. This descriptive title is shown to users when no resources have facade alternatives available. Lazy loading means loading resources is deferred until they are needed. */ + title: 'Lazy load third-party resources with facade alternatives', + /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded with a facade alternative. This descriptive title is shown to users when one or more third-party resources have available facade alternatives. Lazy loading means loading resources is deferred until they are needed. */ + failureTitle: 'Some third-party resources can be lazy loaded with a facade alternative', + /** Description of a Lighthouse audit that identifies the third party code on the page that can be lazy loaded with a facade alternative. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. Lazy loading means loading resources is deferred until they are needed. */ description: 'Some third-party resources can be fetched after the page loads. ' + 'These third-party resources are used by embedded elements which can be replaced by a facade ' + 'until the user needs to use them. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).', - /** Summary text for the result of a Lighthouse audit that identifies the third party code on a web page that can be lazy loaded. This text summarizes the number of lazy loading facades that can be used on the page. Lazy loading means loading resources is deferred until they are needed. */ + /** Summary text for the result of a Lighthouse audit that identifies the third party code on a web page that can be lazy loaded with a facade alternative. This text summarizes the number of lazy loading facades that can be used on the page. Lazy loading means loading resources is deferred until they are needed. */ displayValue: `{itemCount, plural, =1 {# facade alternative available} other {# facade alternatives available} }`, - /** Label for a table column that displays the name of a lazy loading facade alternative for a third party resource. Lazy loading means loading resources is deferred until they are needed. */ + /** Label for a table column that displays the name of a facade alternative that lazy loads third party resource. Lazy loading means loading resources is deferred until they are needed. */ columnFacade: 'Facade Alternative', /** Label for a table column that displays the name of the third party product that a URL is used for. */ columnProduct: 'Product', @@ -55,13 +55,13 @@ const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings); * }} FacadableProductSummary */ -class LazyThirdParty extends Audit { +class ThirdPartyFacades extends Audit { /** * @return {LH.Audit.Meta} */ static get meta() { return { - id: 'lazy-third-party', + id: 'third-party-facades', title: str_(UIStrings.title), failureTitle: str_(UIStrings.failureTitle), description: str_(UIStrings.description), @@ -148,7 +148,7 @@ class LazyThirdParty extends Audit { settings.throttling.cpuSlowdownMultiplier : 1; const thirdPartySummaries = ThirdPartySummary.getSummaries(networkRecords, tasks, multiplier); const productSummaries - = LazyThirdParty.getFacadableProductSummaries(thirdPartySummaries.byURL, mainEntity); + = ThirdPartyFacades.getFacadableProductSummaries(thirdPartySummaries.byURL, mainEntity); const summary = {wastedBytes: 0, wastedMs: 0}; @@ -213,5 +213,5 @@ class LazyThirdParty extends Audit { } } -module.exports = LazyThirdParty; +module.exports = ThirdPartyFacades; module.exports.UIStrings = UIStrings; diff --git a/lighthouse-core/config/default-config.js b/lighthouse-core/config/default-config.js index 76a97ca612dc..6c1819d99dcd 100644 --- a/lighthouse-core/config/default-config.js +++ b/lighthouse-core/config/default-config.js @@ -235,7 +235,7 @@ const defaultConfig = { 'timing-budget', 'resource-summary', 'third-party-summary', - 'lazy-third-party', + 'third-party-facades', 'largest-contentful-paint-element', 'layout-shift-elements', 'long-tasks', @@ -468,7 +468,7 @@ const defaultConfig = { {id: 'timing-budget', weight: 0, group: 'budgets'}, {id: 'resource-summary', weight: 0, group: 'diagnostics'}, {id: 'third-party-summary', weight: 0, group: 'diagnostics'}, - {id: 'lazy-third-party', weight: 0, group: 'diagnostics'}, + {id: 'third-party-facades', weight: 0, group: 'diagnostics'}, {id: 'largest-contentful-paint-element', weight: 0, group: 'diagnostics'}, {id: 'layout-shift-elements', weight: 0, group: 'diagnostics'}, {id: 'uses-passive-event-listeners', weight: 0, group: 'diagnostics'}, diff --git a/lighthouse-core/report/html/renderer/report-ui-features.js b/lighthouse-core/report/html/renderer/report-ui-features.js index ebabaf13a177..3064adbad11e 100644 --- a/lighthouse-core/report/html/renderer/report-ui-features.js +++ b/lighthouse-core/report/html/renderer/report-ui-features.js @@ -218,7 +218,7 @@ class ReportUIFeatures { const thirdPartyFilterAuditExclusions = [ // These audits deal explicitly with third party resources. 'uses-rel-preconnect', - 'lazy-third-party', + 'third-party-facades', ]; // Some audits should hide third party by default. const thirdPartyFilterAuditHideByDefault = [ diff --git a/lighthouse-core/test/audits/lazy-third-party-test.js b/lighthouse-core/test/audits/third-party-facades-test.js similarity index 92% rename from lighthouse-core/test/audits/lazy-third-party-test.js rename to lighthouse-core/test/audits/third-party-facades-test.js index 184ef47defc2..05fc8f1655f1 100644 --- a/lighthouse-core/test/audits/lazy-third-party-test.js +++ b/lighthouse-core/test/audits/third-party-facades-test.js @@ -5,7 +5,7 @@ */ 'use strict'; -const LazyThirdParty = require('../../audits/lazy-third-party.js'); +const ThirdPartyFacades = require('../../audits/third-party-facades.js'); const networkRecordsToDevtoolsLog = require('../network-records-to-devtools-log.js'); const createTestTrace = require('../create-test-trace.js'); @@ -46,8 +46,8 @@ function youtubeResourceEntry(startTime, headerEndTime, endTime, transferSize, i } /* eslint-env jest */ -describe('Lazy load third party resources', () => { - it('correctly identifies a lazy loadable third party resource', async () => { +describe('Third party facades audit', () => { + it('correctly identifies a third party product with facade alternative', async () => { const artifacts = { devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ resourceEntry(100, 101, 102, 2000, 'https://example.com'), @@ -59,7 +59,7 @@ describe('Lazy load third party resources', () => { }; const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; - const results = await LazyThirdParty.audit(artifacts, {computedCache: new Map(), settings}); + const results = await ThirdPartyFacades.audit(artifacts, {computedCache: new Map(), settings}); expect(results.score).toBe(0); expect(results.displayValue).toBeDisplayString('1 facade alternative available'); @@ -109,7 +109,7 @@ describe('Lazy load third party resources', () => { }; const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; - const results = await LazyThirdParty.audit(artifacts, {computedCache: new Map(), settings}); + const results = await ThirdPartyFacades.audit(artifacts, {computedCache: new Map(), settings}); expect(results.score).toBe(0); expect(results.displayValue).toBeDisplayString('2 facade alternatives available'); @@ -187,7 +187,7 @@ describe('Lazy load third party resources', () => { }; const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; - const results = await LazyThirdParty.audit(artifacts, {computedCache: new Map(), settings}); + const results = await ThirdPartyFacades.audit(artifacts, {computedCache: new Map(), settings}); expect(results.score).toBe(0); expect(results.displayValue).toBeDisplayString('1 facade alternative available'); @@ -240,7 +240,7 @@ describe('Lazy load third party resources', () => { }; const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; - const results = await LazyThirdParty.audit(artifacts, {computedCache: new Map(), settings}); + const results = await ThirdPartyFacades.audit(artifacts, {computedCache: new Map(), settings}); expect(results.score).toBe(0); expect(results.displayValue).toBeDisplayString('1 facade alternative available'); @@ -287,7 +287,7 @@ describe('Lazy load third party resources', () => { }; const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; - const results = await LazyThirdParty.audit(artifacts, {computedCache: new Map(), settings}); + const results = await ThirdPartyFacades.audit(artifacts, {computedCache: new Map(), settings}); expect(results).toEqual({ score: 1, @@ -304,7 +304,7 @@ describe('Lazy load third party resources', () => { }; const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; - const results = await LazyThirdParty.audit(artifacts, {computedCache: new Map(), settings}); + const results = await ThirdPartyFacades.audit(artifacts, {computedCache: new Map(), settings}); expect(results).toEqual({ score: 1, @@ -322,7 +322,7 @@ describe('Lazy load third party resources', () => { }; const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; - const results = await LazyThirdParty.audit(artifacts, {computedCache: new Map(), settings}); + const results = await ThirdPartyFacades.audit(artifacts, {computedCache: new Map(), settings}); expect(results).toEqual({ score: 1, From 612c933e488a63d696b6a234bc20fa1558497720 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 15 Sep 2020 15:11:43 -0400 Subject: [PATCH 36/82] update sample and snapshot --- .../test/cli/__snapshots__/index-test.js.snap | 4 +-- lighthouse-core/lib/i18n/locales/en-US.json | 36 +++++++++---------- lighthouse-core/lib/i18n/locales/en-XL.json | 36 +++++++++---------- lighthouse-core/test/results/sample_v2.json | 24 ++++++------- 4 files changed, 49 insertions(+), 51 deletions(-) diff --git a/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap b/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap index 7acae0f230d6..243e7454c210 100644 --- a/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap +++ b/lighthouse-cli/test/cli/__snapshots__/index-test.js.snap @@ -151,7 +151,7 @@ Object { "path": "third-party-summary", }, Object { - "path": "lazy-third-party", + "path": "third-party-facades", }, Object { "path": "largest-contentful-paint-element", @@ -998,7 +998,7 @@ Object { }, Object { "group": "diagnostics", - "id": "lazy-third-party", + "id": "third-party-facades", "weight": 0, }, Object { diff --git a/lighthouse-core/lib/i18n/locales/en-US.json b/lighthouse-core/lib/i18n/locales/en-US.json index 9af3d244a117..3e38731df7a1 100644 --- a/lighthouse-core/lib/i18n/locales/en-US.json +++ b/lighthouse-core/lib/i18n/locales/en-US.json @@ -863,24 +863,6 @@ "lighthouse-core/audits/layout-shift-elements.js | title": { "message": "Avoid large layout shifts" }, - "lighthouse-core/audits/lazy-third-party.js | columnFacade": { - "message": "Facade Alternative" - }, - "lighthouse-core/audits/lazy-third-party.js | columnProduct": { - "message": "Product" - }, - "lighthouse-core/audits/lazy-third-party.js | description": { - "message": "Some third-party resources can be fetched after the page loads. These third-party resources are used by embedded elements which can be replaced by a facade until the user needs to use them. [Learn more](https://web.dev/efficiently-load-third-party-javascript/)." - }, - "lighthouse-core/audits/lazy-third-party.js | displayValue": { - "message": "{itemCount, plural,\n =1 {# facade alternative available}\n other {# facade alternatives available}\n }" - }, - "lighthouse-core/audits/lazy-third-party.js | failureTitle": { - "message": "Some third-party resources can be lazy loaded" - }, - "lighthouse-core/audits/lazy-third-party.js | title": { - "message": "Lazy load third-party resources" - }, "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": { "message": "A fast page load over a cellular network ensures a good mobile user experience. [Learn more](https://web.dev/load-fast-enough-for-pwa/)." }, @@ -1289,6 +1271,24 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Sets a theme color for the address bar." }, + "lighthouse-core/audits/third-party-facades.js | columnFacade": { + "message": "Facade Alternative" + }, + "lighthouse-core/audits/third-party-facades.js | columnProduct": { + "message": "Product" + }, + "lighthouse-core/audits/third-party-facades.js | description": { + "message": "Some third-party resources can be fetched after the page loads. These third-party resources are used by embedded elements which can be replaced by a facade until the user needs to use them. [Learn more](https://web.dev/efficiently-load-third-party-javascript/)." + }, + "lighthouse-core/audits/third-party-facades.js | displayValue": { + "message": "{itemCount, plural,\n =1 {# facade alternative available}\n other {# facade alternatives available}\n }" + }, + "lighthouse-core/audits/third-party-facades.js | failureTitle": { + "message": "Some third-party resources can be lazy loaded with a facade alternative" + }, + "lighthouse-core/audits/third-party-facades.js | title": { + "message": "Lazy load third-party resources with facade alternatives" + }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Third-Party" }, diff --git a/lighthouse-core/lib/i18n/locales/en-XL.json b/lighthouse-core/lib/i18n/locales/en-XL.json index 7217881355cf..b8d4b7056187 100644 --- a/lighthouse-core/lib/i18n/locales/en-XL.json +++ b/lighthouse-core/lib/i18n/locales/en-XL.json @@ -863,24 +863,6 @@ "lighthouse-core/audits/layout-shift-elements.js | title": { "message": "Âv́ôíd̂ ĺâŕĝé l̂áŷóût́ ŝh́îf́t̂ś" }, - "lighthouse-core/audits/lazy-third-party.js | columnFacade": { - "message": "F̂áĉád̂é Âĺt̂ér̂ńât́îv́ê" - }, - "lighthouse-core/audits/lazy-third-party.js | columnProduct": { - "message": "P̂ŕôd́ûćt̂" - }, - "lighthouse-core/audits/lazy-third-party.js | description": { - "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ćâń b̂é f̂ét̂ćĥéd̂ áf̂t́êŕ t̂h́ê ṕâǵê ĺôád̂ś. T̂h́êśê t́ĥír̂d́-p̂ár̂t́ŷ ŕêśôúr̂ćêś âŕê úŝéd̂ b́ŷ ém̂b́êd́d̂éd̂ él̂ém̂én̂t́ŝ ẃĥíĉh́ ĉán̂ b́ê ŕêṕl̂áĉéd̂ b́ŷ á f̂áĉád̂é ûńt̂íl̂ t́ĥé ûśêŕ n̂éêd́ŝ t́ô úŝé t̂h́êḿ. [L̂éâŕn̂ ḿôŕê](https://web.dev/efficiently-load-third-party-javascript/)." - }, - "lighthouse-core/audits/lazy-third-party.js | displayValue": { - "message": "{itemCount, plural,\n =1 {# f̂áĉád̂é âĺt̂ér̂ńât́îv́ê áv̂áîĺâb́l̂é}\n other {# f̂áĉád̂é âĺt̂ér̂ńât́îv́êś âv́âíl̂áb̂ĺê}\n }" - }, - "lighthouse-core/audits/lazy-third-party.js | failureTitle": { - "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ćâń b̂é l̂áẑý l̂óâd́êd́" - }, - "lighthouse-core/audits/lazy-third-party.js | title": { - "message": "L̂áẑý l̂óâd́ t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ" - }, "lighthouse-core/audits/load-fast-enough-for-pwa.js | description": { "message": "Â f́âśt̂ ṕâǵê ĺôád̂ óv̂ér̂ á ĉél̂ĺûĺâŕ n̂ét̂ẃôŕk̂ én̂śûŕêś â ǵôód̂ ḿôb́îĺê úŝér̂ éx̂ṕêŕîén̂ćê. [Ĺêár̂ń m̂ór̂é](https://web.dev/load-fast-enough-for-pwa/)." }, @@ -1289,6 +1271,24 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Ŝét̂ś â t́ĥém̂é ĉól̂ór̂ f́ôŕ t̂h́ê ád̂d́r̂éŝś b̂ár̂." }, + "lighthouse-core/audits/third-party-facades.js | columnFacade": { + "message": "F̂áĉád̂é Âĺt̂ér̂ńât́îv́ê" + }, + "lighthouse-core/audits/third-party-facades.js | columnProduct": { + "message": "P̂ŕôd́ûćt̂" + }, + "lighthouse-core/audits/third-party-facades.js | description": { + "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ćâń b̂é f̂ét̂ćĥéd̂ áf̂t́êŕ t̂h́ê ṕâǵê ĺôád̂ś. T̂h́êśê t́ĥír̂d́-p̂ár̂t́ŷ ŕêśôúr̂ćêś âŕê úŝéd̂ b́ŷ ém̂b́êd́d̂éd̂ él̂ém̂én̂t́ŝ ẃĥíĉh́ ĉán̂ b́ê ŕêṕl̂áĉéd̂ b́ŷ á f̂áĉád̂é ûńt̂íl̂ t́ĥé ûśêŕ n̂éêd́ŝ t́ô úŝé t̂h́êḿ. [L̂éâŕn̂ ḿôŕê](https://web.dev/efficiently-load-third-party-javascript/)." + }, + "lighthouse-core/audits/third-party-facades.js | displayValue": { + "message": "{itemCount, plural,\n =1 {# f̂áĉád̂é âĺt̂ér̂ńât́îv́ê áv̂áîĺâb́l̂é}\n other {# f̂áĉád̂é âĺt̂ér̂ńât́îv́êś âv́âíl̂áb̂ĺê}\n }" + }, + "lighthouse-core/audits/third-party-facades.js | failureTitle": { + "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ćâń b̂é l̂áẑý l̂óâd́êd́ ŵít̂h́ â f́âćâd́ê ál̂t́êŕn̂át̂ív̂é" + }, + "lighthouse-core/audits/third-party-facades.js | title": { + "message": "L̂áẑý l̂óâd́ t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ẃît́ĥ f́âćâd́ê ál̂t́êŕn̂át̂ív̂éŝ" + }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "T̂h́îŕd̂-Ṕâŕt̂ý" }, diff --git a/lighthouse-core/test/results/sample_v2.json b/lighthouse-core/test/results/sample_v2.json index 525715c7bf1b..cf85c7a205d5 100644 --- a/lighthouse-core/test/results/sample_v2.json +++ b/lighthouse-core/test/results/sample_v2.json @@ -1702,8 +1702,6 @@ "mainThreadTime": 90.36300000000001, "blockingTime": 22.918000000000006, "transferSize": 30174, - "startTime": 185607.195975, - "endTime": 185608.117509, "entity": { "type": "link", "text": "Google CDN", @@ -1717,8 +1715,8 @@ "mainThreadTime": 90.36300000000001, "blockingTime": 22.918000000000006, "transferSize": 30174, - "startTime": 185607.195975, - "endTime": 185608.117509 + "firstStartTime": 185607.195975, + "firstEndTime": 185607.822806 } ] } @@ -1730,9 +1728,9 @@ } } }, - "lazy-third-party": { - "id": "lazy-third-party", - "title": "Lazy load third-party resources", + "third-party-facades": { + "id": "third-party-facades", + "title": "Lazy load third-party resources with facade alternatives", "description": "Some third-party resources can be fetched after the page loads. These third-party resources are used by embedded elements which can be replaced by a facade until the user needs to use them. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).", "score": null, "scoreDisplayMode": "notApplicable" @@ -4463,7 +4461,7 @@ "group": "diagnostics" }, { - "id": "lazy-third-party", + "id": "third-party-facades", "weight": 0, "group": "diagnostics" }, @@ -5661,7 +5659,7 @@ }, { "startTime": 0, - "name": "lh:audit:lazy-third-party", + "name": "lh:audit:third-party-facades", "duration": 100, "entryType": "measure" }, @@ -6928,11 +6926,11 @@ "lighthouse-core/lib/i18n/i18n.js | columnBlockingTime": [ "audits[third-party-summary].details.headings[2].text" ], - "lighthouse-core/audits/lazy-third-party.js | title": [ - "audits[lazy-third-party].title" + "lighthouse-core/audits/third-party-facades.js | title": [ + "audits[third-party-facades].title" ], - "lighthouse-core/audits/lazy-third-party.js | description": [ - "audits[lazy-third-party].description" + "lighthouse-core/audits/third-party-facades.js | description": [ + "audits[third-party-facades].description" ], "lighthouse-core/audits/largest-contentful-paint-element.js | title": [ "audits[largest-contentful-paint-element].title" From 1d47eaa3bc47172b50d5dcbf3fcd7990c71024a9 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 15 Sep 2020 17:29:03 -0400 Subject: [PATCH 37/82] add real trace test case --- .../test/audits/third-party-facades-test.js | 465 +++++++++++++----- .../traces/video-embeds-m84.devtools.log.json | 234 +++++++++ .../fixtures/traces/video-embeds-m84.json | 266 ++++++++++ 3 files changed, 839 insertions(+), 126 deletions(-) create mode 100644 lighthouse-core/test/fixtures/traces/video-embeds-m84.devtools.log.json create mode 100644 lighthouse-core/test/fixtures/traces/video-embeds-m84.json diff --git a/lighthouse-core/test/audits/third-party-facades-test.js b/lighthouse-core/test/audits/third-party-facades-test.js index 05fc8f1655f1..abf0f61a8657 100644 --- a/lighthouse-core/test/audits/third-party-facades-test.js +++ b/lighthouse-core/test/audits/third-party-facades-test.js @@ -11,6 +11,8 @@ const createTestTrace = require('../create-test-trace.js'); const pwaTrace = require('../fixtures/traces/progressive-app-m60.json'); const pwaDevtoolsLog = require('../fixtures/traces/progressive-app-m60.devtools.log.json'); +const videoEmbedsTrace = require('../fixtures/traces/video-embeds-m84.json'); +const videoEmbedsDevtolsLog = require('../fixtures/traces/video-embeds-m84.devtools.log.json'); const noThirdPartyTrace = require('../fixtures/traces/no-tracingstarted-m74.json'); function resourceEntry(startTime, headerEndTime, endTime, transferSize, url) { @@ -49,11 +51,13 @@ function youtubeResourceEntry(startTime, headerEndTime, endTime, transferSize, i describe('Third party facades audit', () => { it('correctly identifies a third party product with facade alternative', async () => { const artifacts = { - devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ - resourceEntry(100, 101, 102, 2000, 'https://example.com'), - intercomProductEntry(200, 201, 202, 4000, '1'), - intercomResourceEntry(300, 301, 302, 8000, 'a'), - ])}, + devtoolsLogs: { + defaultPass: networkRecordsToDevtoolsLog([ + resourceEntry(100, 101, 102, 2000, 'https://example.com'), + intercomProductEntry(200, 201, 202, 4000, '1'), + intercomResourceEntry(300, 301, 302, 8000, 'a'), + ]), + }, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, URL: {finalUrl: 'https://example.com'}, }; @@ -73,37 +77,42 @@ describe('Third party facades audit', () => { }, transferSize: 12000, blockingTime: 0, - subItems: {type: 'subitems', items: [ - { - url: 'https://js.intercomcdn.com/frame-modern.a.js', - mainThreadTime: 0, - blockingTime: 0, - transferSize: 8000, - firstStartTime: 300, - firstEndTime: 301, - }, - { - url: 'https://widget.intercom.io/widget/1', - mainThreadTime: 0, - blockingTime: 0, - transferSize: 4000, - firstStartTime: 200, - firstEndTime: 201, - }, - ]}, + subItems: { + type: 'subitems', + items: [ + { + url: 'https://js.intercomcdn.com/frame-modern.a.js', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 8000, + firstStartTime: 300, + firstEndTime: 301, + }, + { + url: 'https://widget.intercom.io/widget/1', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 4000, + firstStartTime: 200, + firstEndTime: 201, + }, + ], + }, }, ]); }); it('handles multiple products with facades', async () => { const artifacts = { - devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ - resourceEntry(100, 101, 102, 2000, 'https://example.com'), - intercomProductEntry(200, 201, 202, 4000, '1'), - youtubeProductEntry(210, 211, 212, 3000, '2'), - intercomResourceEntry(300, 301, 302, 8000, 'a'), - youtubeResourceEntry(310, 311, 312, 7000, 'b'), - ])}, + devtoolsLogs: { + defaultPass: networkRecordsToDevtoolsLog([ + resourceEntry(100, 101, 102, 2000, 'https://example.com'), + intercomProductEntry(200, 201, 202, 4000, '1'), + youtubeProductEntry(210, 211, 212, 3000, '2'), + intercomResourceEntry(300, 301, 302, 8000, 'a'), + youtubeResourceEntry(310, 311, 312, 7000, 'b'), + ]), + }, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, URL: {finalUrl: 'https://example.com'}, }; @@ -123,24 +132,27 @@ describe('Third party facades audit', () => { }, transferSize: 12000, blockingTime: 0, - subItems: {type: 'subitems', items: [ - { - url: 'https://js.intercomcdn.com/frame-modern.a.js', - mainThreadTime: 0, - blockingTime: 0, - transferSize: 8000, - firstStartTime: 300, - firstEndTime: 301, - }, - { - url: 'https://widget.intercom.io/widget/1', - mainThreadTime: 0, - blockingTime: 0, - transferSize: 4000, - firstStartTime: 200, - firstEndTime: 201, - }, - ]}, + subItems: { + type: 'subitems', + items: [ + { + url: 'https://js.intercomcdn.com/frame-modern.a.js', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 8000, + firstStartTime: 300, + firstEndTime: 301, + }, + { + url: 'https://widget.intercom.io/widget/1', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 4000, + firstStartTime: 200, + firstEndTime: 201, + }, + ], + }, }, { productName: 'YouTube Embedded Player', @@ -151,37 +163,42 @@ describe('Third party facades audit', () => { }, transferSize: 10000, blockingTime: 0, - subItems: {type: 'subitems', items: [ - { - url: 'https://i.ytimg.com/b/maxresdefault.jpg', - mainThreadTime: 0, - blockingTime: 0, - transferSize: 7000, - firstStartTime: 310, - firstEndTime: 311, - }, - { - url: 'https://www.youtube.com/embed/2', - mainThreadTime: 0, - blockingTime: 0, - transferSize: 3000, - firstStartTime: 210, - firstEndTime: 211, - }, - ]}, + subItems: { + type: 'subitems', + items: [ + { + url: 'https://i.ytimg.com/b/maxresdefault.jpg', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 7000, + firstStartTime: 310, + firstEndTime: 311, + }, + { + url: 'https://www.youtube.com/embed/2', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 3000, + firstStartTime: 210, + firstEndTime: 211, + }, + ], + }, }, ]); }); it('handle multiple requests to same product resource', async () => { const artifacts = { - devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ - resourceEntry(100, 101, 102, 2000, 'https://example.com'), - // The first product entry is used for the cutoff time - intercomProductEntry(200, 201, 202, 2000, '1'), - intercomResourceEntry(300, 301, 302, 8000, 'a'), - intercomProductEntry(400, 401, 402, 2000, '1'), - ])}, + devtoolsLogs: { + defaultPass: networkRecordsToDevtoolsLog([ + resourceEntry(100, 101, 102, 2000, 'https://example.com'), + // The first product entry is used for the cutoff time + intercomProductEntry(200, 201, 202, 2000, '1'), + intercomResourceEntry(300, 301, 302, 8000, 'a'), + intercomProductEntry(400, 401, 402, 2000, '1'), + ]), + }, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, URL: {finalUrl: 'https://example.com'}, }; @@ -201,40 +218,45 @@ describe('Third party facades audit', () => { }, transferSize: 12000, blockingTime: 0, - subItems: {type: 'subitems', items: [ - { - url: 'https://js.intercomcdn.com/frame-modern.a.js', - mainThreadTime: 0, - blockingTime: 0, - transferSize: 8000, - firstStartTime: 300, - firstEndTime: 301, - }, - { - url: 'https://widget.intercom.io/widget/1', - mainThreadTime: 0, - blockingTime: 0, - transferSize: 4000, - firstStartTime: 200, - firstEndTime: 201, - }, - ]}, + subItems: { + type: 'subitems', + items: [ + { + url: 'https://js.intercomcdn.com/frame-modern.a.js', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 8000, + firstStartTime: 300, + firstEndTime: 301, + }, + { + url: 'https://widget.intercom.io/widget/1', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 4000, + firstStartTime: 200, + firstEndTime: 201, + }, + ], + }, }, ]); }); it('uses receiveHeadersEnd as cutoff', async () => { const artifacts = { - devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ - resourceEntry(100, 101, 102, 2000, 'https://example.com'), - intercomProductEntry(200, 205, 210, 4000, '1'), - // Starts between product's startTime and startTime + receiveHeadersEnd, so it is ignored - intercomResourceEntry(201, 206, 208, 8000, 'a'), - // Starts between product's startTime + receiveHeadersEnd and endTime, so it is included - intercomResourceEntry(206, 208, 215, 8000, 'b'), - // Starts past the cutoff but previous call to same url was before cutoff, so it is ignored - intercomResourceEntry(300, 301, 303, 8000, 'a'), - ])}, + devtoolsLogs: { + defaultPass: networkRecordsToDevtoolsLog([ + resourceEntry(100, 101, 102, 2000, 'https://example.com'), + intercomProductEntry(200, 205, 210, 4000, '1'), + // Starts between product's startTime and startTime + receiveHeadersEnd, so it is ignored + intercomResourceEntry(201, 206, 208, 8000, 'a'), + // Starts between product's startTime + receiveHeadersEnd and endTime, so it is included + intercomResourceEntry(206, 208, 215, 8000, 'b'), + // Starts past the cutoff but previous call to same url was before cutoff, so it is ignored + intercomResourceEntry(300, 301, 303, 8000, 'a'), + ]), + }, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, URL: {finalUrl: 'https://example.com'}, }; @@ -254,34 +276,39 @@ describe('Third party facades audit', () => { }, transferSize: 12000, blockingTime: 0, - subItems: {type: 'subitems', items: [ - { - url: 'https://js.intercomcdn.com/frame-modern.b.js', - mainThreadTime: 0, - blockingTime: 0, - transferSize: 8000, - firstStartTime: 206, - firstEndTime: 208, - }, - { - url: 'https://widget.intercom.io/widget/1', - mainThreadTime: 0, - blockingTime: 0, - transferSize: 4000, - firstStartTime: 200, - firstEndTime: 205, - }, - ]}, + subItems: { + type: 'subitems', + items: [ + { + url: 'https://js.intercomcdn.com/frame-modern.b.js', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 8000, + firstStartTime: 206, + firstEndTime: 208, + }, + { + url: 'https://widget.intercom.io/widget/1', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 4000, + firstStartTime: 200, + firstEndTime: 205, + }, + ], + }, }, ]); }); it('does not report first party resources', async () => { const artifacts = { - devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ - resourceEntry(100, 101, 102, 2000, 'https://intercomcdn.com'), - intercomProductEntry(200, 201, 202, 4000, '1'), - ])}, + devtoolsLogs: { + defaultPass: networkRecordsToDevtoolsLog([ + resourceEntry(100, 101, 102, 2000, 'https://intercomcdn.com'), + intercomProductEntry(200, 201, 202, 4000, '1'), + ]), + }, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, URL: {finalUrl: 'https://intercomcdn.com'}, }; @@ -314,9 +341,11 @@ describe('Third party facades audit', () => { it('not applicable when no third party resources are present', async () => { const artifacts = { - devtoolsLogs: {defaultPass: networkRecordsToDevtoolsLog([ - resourceEntry(100, 101, 102, 2000, 'https://example.com'), - ])}, + devtoolsLogs: { + defaultPass: networkRecordsToDevtoolsLog([ + resourceEntry(100, 101, 102, 2000, 'https://example.com'), + ]), + }, traces: {defaultPass: noThirdPartyTrace}, URL: {finalUrl: 'https://example.com'}, }; @@ -329,4 +358,188 @@ describe('Third party facades audit', () => { notApplicable: true, }); }); + + it('handles real trace', async () => { + const artifacts = { + devtoolsLogs: {defaultPass: videoEmbedsDevtolsLog}, + traces: {defaultPass: videoEmbedsTrace}, + URL: {finalUrl: 'https://example.com'}, + }; + + const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; + const results = await ThirdPartyFacades.audit(artifacts, {computedCache: new Map(), settings}); + + expect(results.score).toBe(0); + expect(results.displayValue).toBeDisplayString('2 facade alternatives available'); + expect(results.details.items).toEqual( + [ + { + blockingTime: 0, + facade: { + text: 'Lite YouTube', + type: 'link', + url: 'https://github.com/paulirish/lite-youtube-embed', + }, + productName: 'YouTube Embedded Player', + subItems: { + items: [ + { + blockingTime: 0, + firstEndTime: 47786.347774999995, + firstStartTime: 47786.326268, + mainThreadTime: 0, + transferSize: 459603, + url: 'https://www.youtube.com/s/player/e0d83c30/player_ias.vflset/en_US/base.js', + }, + { + blockingTime: 0, + firstEndTime: 47786.692717, + firstStartTime: 47786.569798, + mainThreadTime: 0, + transferSize: 66273, + url: 'https://i.ytimg.com/vi/tgbNymZ7vqY/maxresdefault.jpg', + }, + { + blockingTime: 0, + firstEndTime: 47786.436251, + firstStartTime: 47786.325979, + mainThreadTime: 0, + transferSize: 50213, + url: 'https://www.youtube.com/s/player/e0d83c30/www-embed-player.vflset/www-embed-player.js', + }, + { + blockingTime: 0, + firstEndTime: 47786.441221, + firstStartTime: 47786.324095, + mainThreadTime: 0, + transferSize: 46813, + url: 'https://www.youtube.com/s/player/e0d83c30/www-player.css', + }, + { + blockingTime: 0, + firstEndTime: 47786.580910000004, + firstStartTime: 47786.561199, + mainThreadTime: 0, + transferSize: 11477, + url: 'https://www.youtube.com/s/player/e0d83c30/player_ias.vflset/en_US/embed.js', + }, + { + blockingTime: 0, + firstEndTime: 47786.303873000004, + firstStartTime: 47786.066226, + mainThreadTime: 0, + transferSize: 10703, + url: 'https://www.youtube.com/embed/tgbNymZ7vqY', + }, + { + blockingTime: 0, + firstEndTime: 47786.414732000005, + firstStartTime: 47786.326585, + mainThreadTime: 0, + transferSize: 3191, + url: 'https://www.youtube.com/yts/jsbin/fetch-polyfill-vfl6MZH8P/fetch-polyfill.js', + }, + { + blockingTime: 0, + firstEndTime: 47786.679700999994, + firstStartTime: 47786.568895, + mainThreadTime: 0, + transferSize: 3077, + url: 'https://yt3.ggpht.com/a/AATXAJxtCYVD65XPtigYUOad-Nd2v3EvnXnz__MkJrg=s68-c-k-c0x00ffffff-no-rj', + }, + ], + type: 'subitems', + }, + transferSize: 651350, + }, + { + blockingTime: 0, + facade: { + text: 'Lite Vimeo', + type: 'link', + url: 'https://github.com/slightlyoff/lite-vimeo', + }, + productName: 'Vimeo Embedded Player', + subItems: { + items: [ + { + blockingTime: 0, + firstEndTime: 47786.422034999996, + firstStartTime: 47786.323843, + mainThreadTime: 0, + transferSize: 145772, + url: 'https://f.vimeocdn.com/p/3.22.3/js/player.js', + }, + { + blockingTime: 0, + firstEndTime: 47786.422311999995, + firstStartTime: 47786.324528, + mainThreadTime: 0, + transferSize: 17633, + url: 'https://f.vimeocdn.com/p/3.22.3/css/player.css', + }, + { + blockingTime: 0, + firstEndTime: 47786.634061000004, + firstStartTime: 47786.606134, + mainThreadTime: 0, + transferSize: 9313, + url: 'https://i.vimeocdn.com/video/784397921.webp?mw=1200&mh=675&q=70', + }, + { + blockingTime: 0, + firstEndTime: 47786.291588, + firstStartTime: 47786.074447, + mainThreadTime: 0, + transferSize: 8300, + url: 'https://player.vimeo.com/video/336812660', + }, + { + blockingTime: 0, + firstEndTime: 47786.47053, + firstStartTime: 47786.325692, + mainThreadTime: 0, + transferSize: 1474, + url: 'https://f.vimeocdn.com/js_opt/modules/utils/vuid.min.js', + }, + { + blockingTime: 0, + firstEndTime: 47786.417184000005, + firstStartTime: 47786.32147, + mainThreadTime: 0, + transferSize: 1075, + url: 'https://i.vimeocdn.com/video/784397921.jpg?mw=80&q=85', + }, + { + blockingTime: 0, + firstEndTime: 47787.641538, + firstStartTime: 47786.499527, + mainThreadTime: 0, + transferSize: 818, + url: 'https://vimeo.com/ablincoln/vuid?pid=a88cdaf56540a693f597632ffeeaf6a38f56542a1600197631', + }, + { + blockingTime: 0, + firstEndTime: 47786.70353599999, + firstStartTime: 47786.608785, + mainThreadTime: 0, + transferSize: 110, + url: 'https://fresnel.vimeocdn.com/add/player-stats?beacon=1&session-id=a88cdaf56540a693f597632ffeeaf6a38f56542a1600197631', + }, + { + blockingTime: 0, + firstEndTime: 47786.06986, + firstStartTime: 47786.069794, + mainThreadTime: 0, + transferSize: 0, + url: 'http://player.vimeo.com/video/336812660', + }, + ], + type: 'subitems', + }, + transferSize: 184495, + }, + ] + ); + }); }); diff --git a/lighthouse-core/test/fixtures/traces/video-embeds-m84.devtools.log.json b/lighthouse-core/test/fixtures/traces/video-embeds-m84.devtools.log.json new file mode 100644 index 000000000000..1af6902f7ce2 --- /dev/null +++ b/lighthouse-core/test/fixtures/traces/video-embeds-m84.devtools.log.json @@ -0,0 +1,234 @@ +[ + {"method":"Page.lifecycleEvent","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","loaderId":"7786083121DC69321F8379E792981015","name":"commit","timestamp":47785.913186}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","loaderId":"7786083121DC69321F8379E792981015","name":"DOMContentLoaded","timestamp":47785.913248}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","loaderId":"7786083121DC69321F8379E792981015","name":"load","timestamp":47785.913373}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","loaderId":"7786083121DC69321F8379E792981015","name":"networkAlmostIdle","timestamp":47785.913674}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","loaderId":"7786083121DC69321F8379E792981015","name":"networkIdle","timestamp":47785.913674}}, + {"method":"Network.requestWillBeSent","params":{"requestId":"DA13668C4781FCB2BF6F3AB0F3313AB7","loaderId":"DA13668C4781FCB2BF6F3AB0F3313AB7","documentURL":"http://localhost:8686/yt-embed.html","request":{"url":"http://localhost:8686/yt-embed.html","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"VeryHigh","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.042202,"wallTime":1600197631.790902,"initiator":{"type":"other"},"type":"Document","frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","hasUserGesture":false}}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"DA13668C4781FCB2BF6F3AB0F3313AB7","associatedCookies":[],"headers":{"Host":"localhost:8686","Connection":"keep-alive","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4143.7 Mobile Safari/537.36 Chrome-Lighthouse","Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9","Sec-Fetch-Site":"none","Sec-Fetch-Mode":"navigate","Sec-Fetch-User":"?1","Sec-Fetch-Dest":"document","Accept-Encoding":"gzip, deflate, br","Accept-Language":"en-US,en;q=0.9"}}}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"DA13668C4781FCB2BF6F3AB0F3313AB7","blockedCookies":[],"headers":{"Server":"SimpleHTTP/0.6 Python/3.6.8","Date":"Tue, 15 Sep 2020 19:20:31 GMT","Content-type":"text/html","Content-Length":"330","Last-Modified":"Tue, 15 Sep 2020 19:18:47 GMT"},"headersText":"HTTP/1.0 200 OK\r\nServer: SimpleHTTP/0.6 Python/3.6.8\r\nDate: Tue, 15 Sep 2020 19:20:31 GMT\r\nContent-type: text/html\r\nContent-Length: 330\r\nLast-Modified: Tue, 15 Sep 2020 19:18:47 GMT\r\n\r\n"}}, + {"method":"Network.responseReceived","params":{"requestId":"DA13668C4781FCB2BF6F3AB0F3313AB7","loaderId":"DA13668C4781FCB2BF6F3AB0F3313AB7","timestamp":47786.045107,"type":"Document","response":{"url":"http://localhost:8686/yt-embed.html","status":200,"statusText":"OK","headers":{"Content-type":"text/html","Content-Length":"330","Last-Modified":"Tue, 15 Sep 2020 19:18:47 GMT"},"mimeType":"text/html","requestHeaders":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9","Accept-Encoding":"gzip, deflate, br"},"connectionReused":false,"connectionId":26,"remoteIPAddress":"127.0.0.1","remotePort":8686,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":185,"timing":{"requestTime":47786.042861,"dnsStart":0.259,"dnsEnd":0.267,"connectStart":0.267,"connectEnd":0.662,"sendStart":0.705,"sendEnd":0.754,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":1.36},"responseTime":1600197631792.842,"protocol":"http/1.0","securityState":"secure"},"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A"}}, + {"method":"Page.frameStartedLoading","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A"}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","loaderId":"DA13668C4781FCB2BF6F3AB0F3313AB7","name":"init","timestamp":47786.046825}}, + {"method":"Page.frameNavigated","params":{"frame":{"id":"8ECEE70925EB8E7B8C2100384AFF4D1A","loaderId":"DA13668C4781FCB2BF6F3AB0F3313AB7","url":"http://localhost:8686/yt-embed.html","securityOrigin":"http://localhost:8686","mimeType":"text/html"}}}, + {"method":"Network.dataReceived","params":{"requestId":"DA13668C4781FCB2BF6F3AB0F3313AB7","timestamp":47786.055227,"dataLength":330,"encodedDataLength":0}}, + {"method":"Network.loadingFinished","params":{"requestId":"DA13668C4781FCB2BF6F3AB0F3313AB7","timestamp":47786.044624,"encodedDataLength":515,"shouldReportCorbBlocking":false}}, + {"method":"Page.frameAttached","params":{"frameId":"D215705AC29C284D9BB2459B7020E798","parentFrameId":"8ECEE70925EB8E7B8C2100384AFF4D1A"}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"D215705AC29C284D9BB2459B7020E798","loaderId":"4128E72F76ADE3A94BAEE1D2D1778B34","name":"init","timestamp":47786.057252}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"D215705AC29C284D9BB2459B7020E798","loaderId":"4128E72F76ADE3A94BAEE1D2D1778B34","name":"DOMContentLoaded","timestamp":47786.057809}}, + {"method":"Page.frameStartedLoading","params":{"frameId":"D215705AC29C284D9BB2459B7020E798"}}, + {"method":"Network.requestWillBeSent","params":{"requestId":"7409A683C44F8397F7103BD7E03CB6C9","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","documentURL":"https://www.youtube.com/embed/tgbNymZ7vqY","request":{"url":"https://www.youtube.com/embed/tgbNymZ7vqY","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"VeryHigh","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.065491,"wallTime":1600197631.814196,"initiator":{"type":"parser","url":"http://localhost:8686/yt-embed.html","lineNumber":5},"type":"Document","frameId":"D215705AC29C284D9BB2459B7020E798","hasUserGesture":false}}, + {"method":"Page.frameAttached","params":{"frameId":"A0D1CEFE4B294AB844A8912CA96784F9","parentFrameId":"8ECEE70925EB8E7B8C2100384AFF4D1A"}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"A0D1CEFE4B294AB844A8912CA96784F9","loaderId":"FB4672AF3C2DC8E3D150CB86D14D72B5","name":"init","timestamp":47786.058683}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"A0D1CEFE4B294AB844A8912CA96784F9","loaderId":"FB4672AF3C2DC8E3D150CB86D14D72B5","name":"DOMContentLoaded","timestamp":47786.059034}}, + {"method":"Page.frameStartedLoading","params":{"frameId":"A0D1CEFE4B294AB844A8912CA96784F9"}}, + {"method":"Network.requestWillBeSent","params":{"requestId":"51B3229F5358F49D44871ADE7185528C","loaderId":"51B3229F5358F49D44871ADE7185528C","documentURL":"http://player.vimeo.com/video/336812660","request":{"url":"http://player.vimeo.com/video/336812660","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"VeryHigh","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.069162,"wallTime":1600197631.817867,"initiator":{"type":"parser","url":"http://localhost:8686/yt-embed.html","lineNumber":6},"type":"Document","frameId":"A0D1CEFE4B294AB844A8912CA96784F9","hasUserGesture":false}}, + {"method":"Page.domContentEventFired","params":{"timestamp":47786.059918}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","loaderId":"DA13668C4781FCB2BF6F3AB0F3313AB7","name":"DOMContentLoaded","timestamp":47786.059918}}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"51B3229F5358F49D44871ADE7185528C","associatedCookies":[],"headers":{"Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4143.7 Mobile Safari/537.36 Chrome-Lighthouse","Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"}}}, + {"method":"Network.requestWillBeSent","params":{"requestId":"51B3229F5358F49D44871ADE7185528C","loaderId":"51B3229F5358F49D44871ADE7185528C","documentURL":"https://player.vimeo.com/video/336812660","request":{"url":"https://player.vimeo.com/video/336812660","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"VeryHigh","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.073945,"wallTime":1600197631.822702,"initiator":{"type":"parser","url":"http://localhost:8686/yt-embed.html","lineNumber":6},"redirectResponse":{"url":"http://player.vimeo.com/video/336812660","status":307,"statusText":"Internal Redirect","headers":{},"mimeType":"","requestHeaders":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"},"connectionReused":false,"connectionId":0,"remoteIPAddress":"","remotePort":0,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":0,"timing":{"requestTime":47786.069794,"sendStart":0.066,"sendEnd":0.066,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":0.066},"responseTime":1600197631818.549,"protocol":"http/1.1","securityState":"insecure"},"type":"Document","frameId":"A0D1CEFE4B294AB844A8912CA96784F9","hasUserGesture":false}}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"51B3229F5358F49D44871ADE7185528C","blockedCookies":[],"headers":{"Location":"https://player.vimeo.com/video/336812660","Non-Authoritative-Reason":"HSTS"},"headersText":"HTTP/1.1 307 Internal Redirect\r\nLocation: https://player.vimeo.com/video/336812660\r\nNon-Authoritative-Reason: HSTS\r\n\r\n"}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","loaderId":"DA13668C4781FCB2BF6F3AB0F3313AB7","name":"firstPaint","timestamp":47786.179669}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","loaderId":"DA13668C4781FCB2BF6F3AB0F3313AB7","name":"firstContentfulPaint","timestamp":47786.179669}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","loaderId":"DA13668C4781FCB2BF6F3AB0F3313AB7","name":"firstMeaningfulPaintCandidate","timestamp":47786.179669}}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"7409A683C44F8397F7103BD7E03CB6C9","associatedCookies":[],"headers":{":method":"GET",":authority":"www.youtube.com",":scheme":"https",":path":"/embed/tgbNymZ7vqY","upgrade-insecure-requests":"1","user-agent":"Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4143.7 Mobile Safari/537.36 Chrome-Lighthouse","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9","sec-fetch-site":"cross-site","sec-fetch-mode":"navigate","sec-fetch-dest":"iframe","referer":"http://localhost:8686/yt-embed.html","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9"}}}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"51B3229F5358F49D44871ADE7185528C","associatedCookies":[],"headers":{"Host":"player.vimeo.com","Connection":"keep-alive","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4143.7 Mobile Safari/537.36 Chrome-Lighthouse","Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9","Sec-Fetch-Site":"cross-site","Sec-Fetch-Mode":"navigate","Sec-Fetch-Dest":"iframe","Referer":"http://localhost:8686/yt-embed.html","Accept-Encoding":"gzip, deflate, br","Accept-Language":"en-US,en;q=0.9"}}}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"51B3229F5358F49D44871ADE7185528C","blockedCookies":[],"headers":{"Connection":"keep-alive","Content-Length":"5372","Server":"nginx","Content-Type":"text/html; charset=UTF-8","X-Xss-Protection":"1; mode=block","Content-Security-Policy":"script-src 'self' 'unsafe-inline' blob: resource: https://f.vimeocdn.com https://vimeo.com https://js-agent.newrelic.com https://imasdk.googleapis.com/ https://adservice.google.com/ https://s0.2mdn.net/instream/video/ https://bam.nr-data.net https://src.litix.io https://www.gstatic.com https://cdn.streamroot.io https://f.vimeocdn.com; style-src 'self' 'unsafe-inline' https://f.vimeocdn.com https://f.vimeocdn.com; connect-src 'self' ws: wss: https://vimeo.com https://vimeo.dev https://api.vimeo.com https://api.vimeo.dev https://*.ci.vimeows.com https://csi.gstatic.com https://fresnel.vimeocdn.com https://fresnel-player-dev.vimeows.com https://player-telemetry.vimeo.com https://*.akamaized.net https://*.akamaized-staging.net https://*.vimeocdn.com https://netflux.cloud.vimeo.com https://lic.staging.drmtoday.com https://lic.drmtoday.com https://wv.service.expressplay.com https://fp.service.expressplay.com https://pr.service.expressplay.com https://sentry.io https://storage.googleapis.com https://bam.nr-data.net https://live-api.cloud.vimeo.com https://live-api-dev.cloud.vimeo.com https://*.litix.io/ https://collector.vhx.tv https://collector.vhxstaging.com https://backend.dna-delivery.com https://mimir.cloud.vimeo.com; media-src 'self' blob: https://*.vimeocdn.com https://*.akamaized.net https://*.akamaized-staging.net https://*.gvt1.com https://live-api.cloud.vimeo.com https://live-api-dev.cloud.vimeo.com; object-src 'self' https://*.vimeocdn.com https://*.akamaized.net https://*.akamaized-staging.net; default-src 'none'; img-src 'self' data: https://i.vimeocdn.com https://secure-b.vimeocdn.com https://f.vimeocdn.com https://vimeo.com https://secure.gravatar.com https://i0.wp.com https://i1.wp.com https://i2.wp.com https://pagead2.googlesyndication.com https://player.vimeo.com https://*.ci.vimeows.com https://f.vimeocdn.com; frame-src 'self' https://imasdk.googleapis.com/ https://f.vimeocdn.com","X-Content-Type-Options":"nosniff","Content-Encoding":"gzip","Strict-Transport-Security":"max-age=31536000; includeSubDomains; preload","Link":"; rel=preconnect; crossorigin\n; rel=preconnect; crossorigin\n; rel=preconnect; crossorigin","P3p":"CP=\"This is not a P3P policy! See https://vimeo.com/privacy\"","Expires":"Tue, 15 Sep 2020 19:25:46 GMT","Via":"1.1 varnish\n1.1 varnish","Cache-Control":"no-store, no-cache, must-revalidate, post-check=0, pre-check=0","X-Varnish-Cache":"1","X-VServer":"infra-playproxy-a-6","X-Vimeo-DC":"ge","Accept-Ranges":"bytes","Date":"Tue, 15 Sep 2020 19:20:32 GMT","Age":"0","X-Served-By":"cache-mdw17330-MDW","X-Cache":"MISS","X-Cache-Hits":"0","X-Timer":"S1600197632.973719,VS0,VE35","Vary":"Accept-Encoding","X-Player-Backend":"p"},"headersText":"HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nContent-Length: 5372\r\nServer: nginx\r\nContent-Type: text/html; charset=UTF-8\r\nX-Xss-Protection: 1; mode=block\r\nContent-Security-Policy: script-src 'self' 'unsafe-inline' blob: resource: https://f.vimeocdn.com https://vimeo.com https://js-agent.newrelic.com https://imasdk.googleapis.com/ https://adservice.google.com/ https://s0.2mdn.net/instream/video/ https://bam.nr-data.net https://src.litix.io https://www.gstatic.com https://cdn.streamroot.io https://f.vimeocdn.com; style-src 'self' 'unsafe-inline' https://f.vimeocdn.com https://f.vimeocdn.com; connect-src 'self' ws: wss: https://vimeo.com https://vimeo.dev https://api.vimeo.com https://api.vimeo.dev https://*.ci.vimeows.com https://csi.gstatic.com https://fresnel.vimeocdn.com https://fresnel-player-dev.vimeows.com https://player-telemetry.vimeo.com https://*.akamaized.net https://*.akamaized-staging.net https://*.vimeocdn.com https://netflux.cloud.vimeo.com https://lic.staging.drmtoday.com https://lic.drmtoday.com https://wv.service.expressplay.com https://fp.service.expressplay.com https://pr.service.expressplay.com https://sentry.io https://storage.googleapis.com https://bam.nr-data.net https://live-api.cloud.vimeo.com https://live-api-dev.cloud.vimeo.com https://*.litix.io/ https://collector.vhx.tv https://collector.vhxstaging.com https://backend.dna-delivery.com https://mimir.cloud.vimeo.com; media-src 'self' blob: https://*.vimeocdn.com https://*.akamaized.net https://*.akamaized-staging.net https://*.gvt1.com https://live-api.cloud.vimeo.com https://live-api-dev.cloud.vimeo.com; object-src 'self' https://*.vimeocdn.com https://*.akamaized.net https://*.akamaized-staging.net; default-src 'none'; img-src 'self' data: https://i.vimeocdn.com https://secure-b.vimeocdn.com https://f.vimeocdn.com https://vimeo.com https://secure.gravatar.com https://i0.wp.com https://i1.wp.com https://i2.wp.com https://pagead2.googlesyndication.com https://player.vimeo.com https://*.ci.vimeows.com https://f.vimeocdn.com; frame-src 'self' https://imasdk.googleapis.com/ https://f.vimeocdn.com\r\nX-Content-Type-Options: nosniff\r\nContent-Encoding: gzip\r\nStrict-Transport-Security: max-age=31536000; includeSubDomains; preload\r\nLink: ; rel=preconnect; crossorigin\r\nLink: ; rel=preconnect; crossorigin\r\nLink: ; rel=preconnect; crossorigin\r\nP3p: CP=\"This is not a P3P policy! See https://vimeo.com/privacy\"\r\nExpires: Tue, 15 Sep 2020 19:25:46 GMT\r\nVia: 1.1 varnish\r\nCache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\nX-Varnish-Cache: 1\r\nX-VServer: infra-playproxy-a-6\r\nX-Vimeo-DC: ge\r\nAccept-Ranges: bytes\r\nDate: Tue, 15 Sep 2020 19:20:32 GMT\r\nVia: 1.1 varnish\r\nAge: 0\r\nX-Served-By: cache-mdw17330-MDW\r\nX-Cache: MISS\r\nX-Cache-Hits: 0\r\nX-Timer: S1600197632.973719,VS0,VE35\r\nVary: Accept-Encoding\r\nX-Player-Backend: p\r\n\r\n"}}, + {"method":"Network.responseReceived","params":{"requestId":"51B3229F5358F49D44871ADE7185528C","loaderId":"51B3229F5358F49D44871ADE7185528C","timestamp":47786.297169,"type":"Document","response":{"url":"https://player.vimeo.com/video/336812660","status":200,"statusText":"OK","headers":{"Content-Length":"5372","Content-Type":"text/html; charset=UTF-8","Content-Encoding":"gzip","Link":"; rel=preconnect; crossorigin\n; rel=preconnect; crossorigin\n; rel=preconnect; crossorigin","Cache-Control":"no-store, no-cache, must-revalidate, post-check=0, pre-check=0","Accept-Ranges":"bytes"},"mimeType":"text/html","requestHeaders":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9","Accept-Encoding":"gzip, deflate, br"},"connectionReused":false,"connectionId":47,"remoteIPAddress":"151.101.0.217","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":2928,"timing":{"requestTime":47786.074447,"dnsStart":0.189,"dnsEnd":54.756,"connectStart":54.756,"connectEnd":149.581,"sslStart":82.328,"sslEnd":149.576,"sendStart":149.64,"sendEnd":149.694,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":217.141},"responseTime":1600197632040.066,"protocol":"http/1.1","securityState":"secure"},"frameId":"A0D1CEFE4B294AB844A8912CA96784F9"}}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"7409A683C44F8397F7103BD7E03CB6C9","blockedCookies":[{"blockedReasons":["SameSiteUnspecifiedTreatedAsLax"],"cookieLine":"GPS=1; path=/; domain=.youtube.com; expires=Tue, 15-Sep-2020 19:50:31 GMT","cookie":{"name":"GPS","value":"1","domain":".youtube.com","path":"/","expires":1600199431.05266,"size":4,"httpOnly":false,"secure":false,"session":false,"priority":"Medium"}}],"headers":{"status":"200","strict-transport-security":"max-age=31536000","p3p":"CP=\"This is not a P3P policy! See http://support.google.com/accounts/answer/151657?hl=en for more info.\"","cache-control":"no-cache","content-type":"text/html; charset=utf-8","expires":"Tue, 27 Apr 1971 19:44:06 GMT","x-content-type-options":"nosniff","content-encoding":"br","content-length":"9925","date":"Tue, 15 Sep 2020 19:20:32 GMT","server":"YouTube Frontend Proxy","x-xss-protection":"0","set-cookie":"VISITOR_INFO1_LIVE=FQVG-TcC8XQ; path=/; domain=.youtube.com; secure; expires=Sun, 14-Mar-2021 19:20:31 GMT; httponly; samesite=None\nGPS=1; path=/; domain=.youtube.com; expires=Tue, 15-Sep-2020 19:50:31 GMT\nVISITOR_INFO1_LIVE=FQVG-TcC8XQ; path=/; domain=.youtube.com; secure; expires=Sun, 14-Mar-2021 19:20:31 GMT; httponly; samesite=None\nYSC=82k-4YzMCUo; path=/; domain=.youtube.com; secure; httponly; samesite=None","alt-svc":"h3-29=\":443\"; ma=2592000,h3-27=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""}}}, + {"method":"Network.responseReceived","params":{"requestId":"7409A683C44F8397F7103BD7E03CB6C9","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","timestamp":47786.305093,"type":"Document","response":{"url":"https://www.youtube.com/embed/tgbNymZ7vqY","status":200,"statusText":"","headers":{"status":"200","cache-control":"no-cache","content-type":"text/html; charset=utf-8","content-encoding":"br","content-length":"9925"},"mimeType":"text/html","requestHeaders":{"accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9","accept-encoding":"gzip, deflate, br"},"connectionReused":false,"connectionId":46,"remoteIPAddress":"172.217.1.46","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":760,"timing":{"requestTime":47786.066226,"dnsStart":0.163,"dnsEnd":36.584,"connectStart":36.584,"connectEnd":127.561,"sslStart":90.384,"sslEnd":127.557,"sendStart":127.682,"sendEnd":127.8,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":237.647},"responseTime":1600197632052.458,"protocol":"h2","securityState":"secure"},"frameId":"D215705AC29C284D9BB2459B7020E798"}}, + {"method":"Page.frameStoppedLoading","params":{"frameId":"A0D1CEFE4B294AB844A8912CA96784F9"}}, + {"method":"Page.frameDetached","params":{"frameId":"A0D1CEFE4B294AB844A8912CA96784F9"}}, + {"method":"Page.frameStoppedLoading","params":{"frameId":"D215705AC29C284D9BB2459B7020E798"}}, + {"method":"Page.frameDetached","params":{"frameId":"D215705AC29C284D9BB2459B7020E798"}}, + {"method":"Network.dataReceived","params":{"requestId":"51B3229F5358F49D44871ADE7185528C","timestamp":47786.316371,"dataLength":16850,"encodedDataLength":0},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.loadingFinished","params":{"requestId":"51B3229F5358F49D44871ADE7185528C","timestamp":47786.292956,"encodedDataLength":8300,"shouldReportCorbBlocking":false},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"7409A683C44F8397F7103BD7E03CB6C9","timestamp":47786.320966,"dataLength":29781,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.loadingFinished","params":{"requestId":"7409A683C44F8397F7103BD7E03CB6C9","timestamp":47786.30509,"encodedDataLength":10703,"shouldReportCorbBlocking":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56010.2","loaderId":"51B3229F5358F49D44871ADE7185528C","documentURL":"https://player.vimeo.com/video/336812660","request":{"url":"https://i.vimeocdn.com/video/784397921.jpg?mw=80&q=85","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"Low","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.321019,"wallTime":1600197632.06971,"initiator":{"type":"parser","url":"https://player.vimeo.com/video/336812660","lineNumber":0},"type":"Image","frameId":"A0D1CEFE4B294AB844A8912CA96784F9","hasUserGesture":false},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56010.3","loaderId":"51B3229F5358F49D44871ADE7185528C","documentURL":"https://player.vimeo.com/video/336812660","request":{"url":"https://f.vimeocdn.com/p/3.22.3/js/player.js","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"Low","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.323442,"wallTime":1600197632.072133,"initiator":{"type":"script","stack":{"callFrames":[{"functionName":"","scriptId":"7","url":"https://player.vimeo.com/video/336812660","lineNumber":0,"columnNumber":15662}]}},"type":"Script","frameId":"A0D1CEFE4B294AB844A8912CA96784F9","hasUserGesture":false},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56010.4","loaderId":"51B3229F5358F49D44871ADE7185528C","documentURL":"https://player.vimeo.com/video/336812660","request":{"url":"https://f.vimeocdn.com/p/3.22.3/css/player.css","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"VeryHigh","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.323908,"wallTime":1600197632.072599,"initiator":{"type":"script","stack":{"callFrames":[{"functionName":"","scriptId":"7","url":"https://player.vimeo.com/video/336812660","lineNumber":0,"columnNumber":16230}]}},"type":"Stylesheet","frameId":"A0D1CEFE4B294AB844A8912CA96784F9","hasUserGesture":false},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56010.5","loaderId":"51B3229F5358F49D44871ADE7185528C","documentURL":"https://player.vimeo.com/video/336812660","request":{"url":"https://f.vimeocdn.com/js_opt/modules/utils/vuid.min.js","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"Low","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.324141,"wallTime":1600197632.072832,"initiator":{"type":"script","stack":{"callFrames":[{"functionName":"","scriptId":"7","url":"https://player.vimeo.com/video/336812660","lineNumber":0,"columnNumber":16741}]}},"type":"Script","frameId":"A0D1CEFE4B294AB844A8912CA96784F9","hasUserGesture":false},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56007.2","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","documentURL":"https://www.youtube.com/embed/tgbNymZ7vqY","request":{"url":"https://www.youtube.com/s/player/e0d83c30/www-player.css","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"VeryHigh","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.323617,"wallTime":1600197632.072308,"initiator":{"type":"parser","url":"https://www.youtube.com/embed/tgbNymZ7vqY","lineNumber":1},"type":"Stylesheet","frameId":"D215705AC29C284D9BB2459B7020E798","hasUserGesture":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56007.3","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","documentURL":"https://www.youtube.com/embed/tgbNymZ7vqY","request":{"url":"https://www.youtube.com/s/player/e0d83c30/www-embed-player.vflset/www-embed-player.js","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"High","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.323874,"wallTime":1600197632.072565,"initiator":{"type":"parser","url":"https://www.youtube.com/embed/tgbNymZ7vqY","lineNumber":2},"type":"Script","frameId":"D215705AC29C284D9BB2459B7020E798","hasUserGesture":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56007.4","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","documentURL":"https://www.youtube.com/embed/tgbNymZ7vqY","request":{"url":"https://www.youtube.com/s/player/e0d83c30/player_ias.vflset/en_US/base.js","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"High","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.324034,"wallTime":1600197632.072727,"initiator":{"type":"parser","url":"https://www.youtube.com/embed/tgbNymZ7vqY","lineNumber":3},"type":"Script","frameId":"D215705AC29C284D9BB2459B7020E798","hasUserGesture":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56007.5","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","documentURL":"https://www.youtube.com/embed/tgbNymZ7vqY","request":{"url":"https://www.youtube.com/yts/jsbin/fetch-polyfill-vfl6MZH8P/fetch-polyfill.js","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"High","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.324204,"wallTime":1600197632.072896,"initiator":{"type":"parser","url":"https://www.youtube.com/embed/tgbNymZ7vqY","lineNumber":4},"type":"Script","frameId":"D215705AC29C284D9BB2459B7020E798","hasUserGesture":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.resourceChangedPriority","params":{"requestId":"56010.2","newPriority":"High","timestamp":47786.325661},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56007.2","associatedCookies":[{"blockedReasons":[],"cookie":{"name":"VISITOR_INFO1_LIVE","value":"FQVG-TcC8XQ","domain":".youtube.com","path":"/","expires":1615749631.052688,"size":29,"httpOnly":true,"secure":true,"session":false,"sameSite":"None","priority":"Medium"}},{"blockedReasons":[],"cookie":{"name":"YSC","value":"82k-4YzMCUo","domain":".youtube.com","path":"/","expires":-1,"size":14,"httpOnly":true,"secure":true,"session":true,"sameSite":"None","priority":"Medium"}}],"headers":{":method":"GET",":authority":"www.youtube.com",":scheme":"https",":path":"/s/player/e0d83c30/www-player.css","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"text/css,*/*;q=0.1","sec-fetch-site":"same-origin","sec-fetch-mode":"no-cors","sec-fetch-dest":"style","referer":"https://www.youtube.com/embed/tgbNymZ7vqY","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9","cookie":"VISITOR_INFO1_LIVE=FQVG-TcC8XQ; YSC=82k-4YzMCUo"}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56007.3","associatedCookies":[{"blockedReasons":[],"cookie":{"name":"VISITOR_INFO1_LIVE","value":"FQVG-TcC8XQ","domain":".youtube.com","path":"/","expires":1615749631.052688,"size":29,"httpOnly":true,"secure":true,"session":false,"sameSite":"None","priority":"Medium"}},{"blockedReasons":[],"cookie":{"name":"YSC","value":"82k-4YzMCUo","domain":".youtube.com","path":"/","expires":-1,"size":14,"httpOnly":true,"secure":true,"session":true,"sameSite":"None","priority":"Medium"}}],"headers":{":method":"GET",":authority":"www.youtube.com",":scheme":"https",":path":"/s/player/e0d83c30/www-embed-player.vflset/www-embed-player.js","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"*/*","sec-fetch-site":"same-origin","sec-fetch-mode":"no-cors","sec-fetch-dest":"script","referer":"https://www.youtube.com/embed/tgbNymZ7vqY","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9","cookie":"VISITOR_INFO1_LIVE=FQVG-TcC8XQ; YSC=82k-4YzMCUo"}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56007.4","associatedCookies":[{"blockedReasons":[],"cookie":{"name":"VISITOR_INFO1_LIVE","value":"FQVG-TcC8XQ","domain":".youtube.com","path":"/","expires":1615749631.052688,"size":29,"httpOnly":true,"secure":true,"session":false,"sameSite":"None","priority":"Medium"}},{"blockedReasons":[],"cookie":{"name":"YSC","value":"82k-4YzMCUo","domain":".youtube.com","path":"/","expires":-1,"size":14,"httpOnly":true,"secure":true,"session":true,"sameSite":"None","priority":"Medium"}}],"headers":{":method":"GET",":authority":"www.youtube.com",":scheme":"https",":path":"/s/player/e0d83c30/player_ias.vflset/en_US/base.js","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"*/*","sec-fetch-site":"same-origin","sec-fetch-mode":"no-cors","sec-fetch-dest":"script","referer":"https://www.youtube.com/embed/tgbNymZ7vqY","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9","cookie":"VISITOR_INFO1_LIVE=FQVG-TcC8XQ; YSC=82k-4YzMCUo"}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56007.5","associatedCookies":[{"blockedReasons":[],"cookie":{"name":"VISITOR_INFO1_LIVE","value":"FQVG-TcC8XQ","domain":".youtube.com","path":"/","expires":1615749631.052688,"size":29,"httpOnly":true,"secure":true,"session":false,"sameSite":"None","priority":"Medium"}},{"blockedReasons":[],"cookie":{"name":"YSC","value":"82k-4YzMCUo","domain":".youtube.com","path":"/","expires":-1,"size":14,"httpOnly":true,"secure":true,"session":true,"sameSite":"None","priority":"Medium"}}],"headers":{":method":"GET",":authority":"www.youtube.com",":scheme":"https",":path":"/yts/jsbin/fetch-polyfill-vfl6MZH8P/fetch-polyfill.js","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"*/*","sec-fetch-site":"same-origin","sec-fetch-mode":"no-cors","sec-fetch-dest":"script","referer":"https://www.youtube.com/embed/tgbNymZ7vqY","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9","cookie":"VISITOR_INFO1_LIVE=FQVG-TcC8XQ; YSC=82k-4YzMCUo"}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56007.4","blockedCookies":[],"headers":{"status":"200","accept-ranges":"bytes","vary":"Accept-Encoding, Origin","content-encoding":"gzip","content-type":"text/javascript","content-length":"459175","date":"Mon, 14 Sep 2020 17:25:18 GMT","expires":"Tue, 14 Sep 2021 17:25:18 GMT","last-modified":"Mon, 14 Sep 2020 00:19:34 GMT","x-content-type-options":"nosniff","server":"sffe","x-xss-protection":"0","cache-control":"public, max-age=31536000","age":"93314","alt-svc":"h3-29=\":443\"; ma=2592000,h3-27=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceived","params":{"requestId":"56007.4","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","timestamp":47786.3485,"type":"Script","response":{"url":"https://www.youtube.com/s/player/e0d83c30/player_ias.vflset/en_US/base.js","status":200,"statusText":"","headers":{"content-encoding":"gzip","last-modified":"Mon, 14 Sep 2020 00:19:34 GMT","content-type":"text/javascript","status":"200","cache-control":"public, max-age=31536000","accept-ranges":"bytes","content-length":"459175"},"mimeType":"text/javascript","connectionReused":true,"connectionId":46,"remoteIPAddress":"172.217.1.46","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":167,"timing":{"requestTime":47786.326268,"sendStart":1.2,"sendEnd":1.593,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":21.507},"responseTime":1600197632096.377,"protocol":"h2","securityState":"secure"},"frameId":"D215705AC29C284D9BB2459B7020E798"},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.350078,"dataLength":8415,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.351533,"dataLength":9954,"encodedDataLength":5584},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.352671,"dataLength":8206,"encodedDataLength":4188},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.362277,"dataLength":65536,"encodedDataLength":2792},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.36557,"dataLength":10513,"encodedDataLength":27202},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.374737,"dataLength":62570,"encodedDataLength":22336},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.381266,"dataLength":9686,"encodedDataLength":3470},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.384741,"dataLength":31661,"encodedDataLength":11168},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.385853,"dataLength":11259,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.391426,"dataLength":65536,"encodedDataLength":4188},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56010.2","associatedCookies":[],"headers":{":method":"GET",":authority":"i.vimeocdn.com",":scheme":"https",":path":"/video/784397921.jpg?mw=80&q=85","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"image/avif,image/webp,image/apng,image/*,*/*;q=0.8","sec-fetch-site":"cross-site","sec-fetch-mode":"no-cors","sec-fetch-dest":"image","referer":"https://player.vimeo.com/video/336812660","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9"}},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.393052,"dataLength":51807,"encodedDataLength":42558},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56010.4","associatedCookies":[],"headers":{":method":"GET",":authority":"f.vimeocdn.com",":scheme":"https",":path":"/p/3.22.3/css/player.css","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"text/css,*/*;q=0.1","sec-fetch-site":"cross-site","sec-fetch-mode":"no-cors","sec-fetch-dest":"style","referer":"https://player.vimeo.com/video/336812660","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9"}},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56010.3","associatedCookies":[],"headers":{":method":"GET",":authority":"f.vimeocdn.com",":scheme":"https",":path":"/p/3.22.3/js/player.js","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"*/*","sec-fetch-site":"cross-site","sec-fetch-mode":"no-cors","sec-fetch-dest":"script","referer":"https://player.vimeo.com/video/336812660","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9"}},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56010.5","associatedCookies":[],"headers":{":method":"GET",":authority":"f.vimeocdn.com",":scheme":"https",":path":"/js_opt/modules/utils/vuid.min.js","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"*/*","sec-fetch-site":"cross-site","sec-fetch-mode":"no-cors","sec-fetch-dest":"script","referer":"https://player.vimeo.com/video/336812660","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9"}},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.397928,"dataLength":65536,"encodedDataLength":35578},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.399506,"dataLength":30600,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.401899,"dataLength":68914,"encodedDataLength":24410},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.405198,"dataLength":24095,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.405672,"dataLength":17208,"encodedDataLength":13242},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.405973,"dataLength":19424,"encodedDataLength":5584},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.406896,"dataLength":18344,"encodedDataLength":5584},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.410366,"dataLength":49991,"encodedDataLength":16752},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.414022,"dataLength":65536,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56007.5","blockedCookies":[],"headers":{"status":"200","accept-ranges":"bytes","vary":"Accept-Encoding, Origin","content-encoding":"gzip","content-type":"text/javascript","timing-allow-origin":"https://www.youtube.com","content-length":"3027","date":"Mon, 14 Sep 2020 08:57:57 GMT","expires":"Tue, 22 Sep 2020 08:57:57 GMT","last-modified":"Mon, 14 Sep 2020 02:05:43 GMT","x-content-type-options":"nosniff","server":"sffe","x-xss-protection":"0","cache-control":"public, max-age=691200","age":"123755","alt-svc":"h3-29=\":443\"; ma=2592000,h3-27=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.415332,"dataLength":34053,"encodedDataLength":32786},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceived","params":{"requestId":"56007.5","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","timestamp":47786.415613,"type":"Script","response":{"url":"https://www.youtube.com/yts/jsbin/fetch-polyfill-vfl6MZH8P/fetch-polyfill.js","status":200,"statusText":"","headers":{"content-encoding":"gzip","status":"200","content-length":"3027","last-modified":"Mon, 14 Sep 2020 02:05:43 GMT","content-type":"text/javascript","cache-control":"public, max-age=691200","accept-ranges":"bytes"},"mimeType":"text/javascript","connectionReused":true,"connectionId":46,"remoteIPAddress":"172.217.1.46","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":155,"timing":{"requestTime":47786.326585,"sendStart":0.945,"sendEnd":1.277,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":88.147},"responseTime":1600197632163.337,"protocol":"h2","securityState":"secure"},"frameId":"D215705AC29C284D9BB2459B7020E798"},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.5","timestamp":47786.415694,"dataLength":8543,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.5","timestamp":47786.41597,"dataLength":0,"encodedDataLength":3036},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.loadingFinished","params":{"requestId":"56007.5","timestamp":47786.415028,"encodedDataLength":3191,"shouldReportCorbBlocking":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.416979,"dataLength":65536,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56010.2","blockedCookies":[],"headers":{"status":"200","content-type":"image/jpeg","etag":"ac7b4a8d2bfa6d5c0a78a039202e768e","viewmaster-server":"viewmaster-us-central1-jj73","cache-control":"public, max-age=2592000","via":"vvarnish\n1.1 varnish\n1.1 varnish","x-backend-server":"varnish","access-control-allow-origin":"*","accept-ranges":"bytes","date":"Tue, 15 Sep 2020 19:20:32 GMT","age":"1069713","x-served-by":"cache-dfw18666-DFW, cache-pwk4931-PWK","x-cache":"miss, HIT, HIT","x-cache-hits":"178, 1","x-timer":"S1600197632.133380,VS0,VE1","content-length":"777"}},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.418198,"dataLength":90694,"encodedDataLength":39048},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceived","params":{"requestId":"56010.2","loaderId":"51B3229F5358F49D44871ADE7185528C","timestamp":47786.418839,"type":"Image","response":{"url":"https://i.vimeocdn.com/video/784397921.jpg?mw=80&q=85","status":200,"statusText":"","headers":{"status":"200","content-length":"777","etag":"ac7b4a8d2bfa6d5c0a78a039202e768e","content-type":"image/jpeg","cache-control":"public, max-age=2592000","accept-ranges":"bytes"},"mimeType":"image/jpeg","connectionReused":false,"connectionId":112,"remoteIPAddress":"199.232.78.109","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":289,"timing":{"requestTime":47786.32147,"dnsStart":0.163,"dnsEnd":27.853,"connectStart":27.853,"connectEnd":70.426,"sslStart":45.436,"sslEnd":70.422,"sendStart":70.706,"sendEnd":70.787,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":95.714},"responseTime":1600197632165.812,"protocol":"h2","securityState":"secure"},"frameId":"A0D1CEFE4B294AB844A8912CA96784F9"},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.2","timestamp":47786.418947,"dataLength":777,"encodedDataLength":0},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.loadingFinished","params":{"requestId":"56010.2","timestamp":47786.417381,"encodedDataLength":1075,"shouldReportCorbBlocking":false},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.420784,"dataLength":152922,"encodedDataLength":50934},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56010.3","blockedCookies":[],"headers":{"status":"200","x-guploader-uploadid":"ABg5-UxFpHkqirvxcbyELILj37EmO4QR6bozrjgSenfPt8vXSXw8TRPqmW0-3uBXqY6C2HaqOJn1LriB97pFtnfCo5U","last-modified":"Fri, 11 Sep 2020 14:27:19 GMT","etag":"\"e9f3d3344e7dc70dcfb4aacd4a25e00e\"","content-type":"application/javascript","content-encoding":"br","server":"UploadServer","via":"1.1 varnish\n1.1 varnish","accept-ranges":"bytes","date":"Tue, 15 Sep 2020 19:20:32 GMT","age":"362791","x-served-by":"cache-bwi5142-BWI, cache-mdw17373-MDW","x-cache":"MISS, HIT","x-cache-hits":"1, 165984","x-timer":"S1600197632.137128,VS0,VE0","vary":"Accept-Encoding","cache-control":"max-age=1209600","content-length":"145320"}},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56010.4","blockedCookies":[],"headers":{"status":"200","x-guploader-uploadid":"ABg5-Ux5HLFhTx7Z5xQEUMn3hEhE9XbNcRrUMuysF0bi1JoFtdYRP2SF7lzdd6HlpMDH6TqjymVQQhXixjFWFcdxFrY","last-modified":"Fri, 11 Sep 2020 14:27:19 GMT","etag":"\"b9e9f7e3eb53e1d8a1b8450b0ece5935\"","content-type":"text/css","content-encoding":"br","server":"UploadServer","via":"1.1 varnish\n1.1 varnish","accept-ranges":"bytes","date":"Tue, 15 Sep 2020 19:20:32 GMT","age":"362791","x-served-by":"cache-bwi5146-BWI, cache-mdw17373-MDW","x-cache":"HIT, HIT","x-cache-hits":"1, 163361","x-timer":"S1600197632.137162,VS0,VE0","vary":"Accept-Encoding","cache-control":"max-age=1209600","access-control-allow-origin":"*","content-length":"17398"}},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.responseReceived","params":{"requestId":"56010.4","loaderId":"51B3229F5358F49D44871ADE7185528C","timestamp":47786.42314,"type":"Stylesheet","response":{"url":"https://f.vimeocdn.com/p/3.22.3/css/player.css","status":200,"statusText":"","headers":{"content-encoding":"br","status":"200","content-length":"17398","last-modified":"Fri, 11 Sep 2020 14:27:19 GMT","etag":"\"b9e9f7e3eb53e1d8a1b8450b0ece5935\"","content-type":"text/css","cache-control":"max-age=1209600","accept-ranges":"bytes"},"mimeType":"text/css","connectionReused":false,"connectionId":109,"remoteIPAddress":"151.101.186.109","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":217,"timing":{"requestTime":47786.324528,"dnsStart":0,"dnsEnd":24.443,"connectStart":24.443,"connectEnd":70.258,"sslStart":42.505,"sslEnd":70.254,"sendStart":70.923,"sendEnd":71.11,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":97.784},"responseTime":1600197632170.908,"protocol":"h2","securityState":"secure"},"frameId":"A0D1CEFE4B294AB844A8912CA96784F9"},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.4","timestamp":47786.425007,"dataLength":65536,"encodedDataLength":0},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.4","timestamp":47786.425177,"dataLength":1119,"encodedDataLength":9009},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.425485,"dataLength":10580,"encodedDataLength":65572},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.425969,"dataLength":201007,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.430182,"dataLength":17434,"encodedDataLength":5584},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.43614,"dataLength":65536,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56007.3","blockedCookies":[],"headers":{"status":"200","accept-ranges":"bytes","vary":"Accept-Encoding, Origin","content-encoding":"gzip","content-type":"text/javascript","content-length":"50124","date":"Mon, 14 Sep 2020 17:25:18 GMT","expires":"Tue, 14 Sep 2021 17:25:18 GMT","last-modified":"Mon, 14 Sep 2020 00:19:34 GMT","x-content-type-options":"nosniff","server":"sffe","x-xss-protection":"0","cache-control":"public, max-age=31536000","age":"93314","alt-svc":"h3-29=\":443\"; ma=2592000,h3-27=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceived","params":{"requestId":"56007.3","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","timestamp":47786.436985,"type":"Script","response":{"url":"https://www.youtube.com/s/player/e0d83c30/www-embed-player.vflset/www-embed-player.js","status":200,"statusText":"","headers":{"content-encoding":"gzip","last-modified":"Mon, 14 Sep 2020 00:19:34 GMT","content-type":"text/javascript","status":"200","cache-control":"public, max-age=31536000","accept-ranges":"bytes","content-length":"50124"},"mimeType":"text/javascript","connectionReused":true,"connectionId":46,"remoteIPAddress":"172.217.1.46","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":53,"timing":{"requestTime":47786.325979,"sendStart":1.3,"sendEnd":1.88,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":110.272},"responseTime":1600197632184.859,"protocol":"h2","securityState":"secure"},"frameId":"D215705AC29C284D9BB2459B7020E798"},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.3","timestamp":47786.437723,"dataLength":65536,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.4","timestamp":47786.437969,"dataLength":90250,"encodedDataLength":40876},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.3","timestamp":47786.439955,"dataLength":46544,"encodedDataLength":39766},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56007.2","blockedCookies":[],"headers":{"status":"200","accept-ranges":"bytes","vary":"Accept-Encoding, Origin","content-encoding":"gzip","content-type":"text/css","content-length":"46698","date":"Mon, 14 Sep 2020 17:28:40 GMT","expires":"Tue, 14 Sep 2021 17:28:40 GMT","last-modified":"Mon, 14 Sep 2020 00:19:34 GMT","x-content-type-options":"nosniff","server":"sffe","x-xss-protection":"0","cache-control":"public, max-age=31536000","age":"93112","alt-svc":"h3-29=\":443\"; ma=2592000,h3-27=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.3","timestamp":47786.441465,"dataLength":29124,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceived","params":{"requestId":"56007.2","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","timestamp":47786.442002,"type":"Stylesheet","response":{"url":"https://www.youtube.com/s/player/e0d83c30/www-player.css","status":200,"statusText":"","headers":{"content-encoding":"gzip","last-modified":"Mon, 14 Sep 2020 00:19:34 GMT","content-type":"text/css","status":"200","cache-control":"public, max-age=31536000","accept-ranges":"bytes","content-length":"46698"},"mimeType":"text/css","connectionReused":true,"connectionId":46,"remoteIPAddress":"172.217.1.46","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":88,"timing":{"requestTime":47786.324095,"sendStart":2.597,"sendEnd":3.469,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":117.126},"responseTime":1600197632189.804,"protocol":"h2","securityState":"secure"},"frameId":"D215705AC29C284D9BB2459B7020E798"},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.4","timestamp":47786.44209,"dataLength":55417,"encodedDataLength":0},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.3","timestamp":47786.443003,"dataLength":0,"encodedDataLength":10394},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.loadingFinished","params":{"requestId":"56007.3","timestamp":47786.440933,"encodedDataLength":50213,"shouldReportCorbBlocking":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.2","timestamp":47786.443066,"dataLength":65536,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.2","timestamp":47786.44318,"dataLength":65536,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.4","timestamp":47786.443418,"dataLength":40710,"encodedDataLength":5484},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.2","timestamp":47786.443762,"dataLength":65536,"encodedDataLength":46725},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.2","timestamp":47786.443876,"dataLength":20456,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.2","timestamp":47786.444107,"dataLength":65536,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.2","timestamp":47786.444214,"dataLength":37144,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.4","timestamp":47786.447429,"dataLength":0,"encodedDataLength":2923},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.loadingFinished","params":{"requestId":"56010.4","timestamp":47786.4434,"encodedDataLength":17633,"shouldReportCorbBlocking":false},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.loadingFinished","params":{"requestId":"56007.2","timestamp":47786.444266,"encodedDataLength":46813,"shouldReportCorbBlocking":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceived","params":{"requestId":"56010.3","loaderId":"51B3229F5358F49D44871ADE7185528C","timestamp":47786.449337,"type":"Script","response":{"url":"https://f.vimeocdn.com/p/3.22.3/js/player.js","status":200,"statusText":"","headers":{"content-encoding":"br","status":"200","content-length":"145320","last-modified":"Fri, 11 Sep 2020 14:27:19 GMT","etag":"\"e9f3d3344e7dc70dcfb4aacd4a25e00e\"","content-type":"application/javascript","cache-control":"max-age=1209600","accept-ranges":"bytes"},"mimeType":"application/javascript","connectionReused":true,"connectionId":109,"remoteIPAddress":"151.101.186.109","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":371,"timing":{"requestTime":47786.323843,"sendStart":71.657,"sendEnd":71.796,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":98.192},"responseTime":1600197632170.613,"protocol":"h2","securityState":"secure"},"frameId":"A0D1CEFE4B294AB844A8912CA96784F9"},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.3","timestamp":47786.449422,"dataLength":49186,"encodedDataLength":0},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.loadingFinished","params":{"requestId":"56007.4","timestamp":47786.436996,"encodedDataLength":459603,"shouldReportCorbBlocking":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.3","timestamp":47786.468293,"dataLength":131072,"encodedDataLength":57401},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56010.5","blockedCookies":[],"headers":{"status":"200","server":"Apache","last-modified":"Tue, 30 Jun 2020 18:34:52 GMT","etag":"\"a51-5a9516e540b00\"","cache-control":"max-age=315360000","expires":"Fri, 28 Jun 2030 20:27:40 GMT","content-encoding":"gzip","x-vimeo-dc":"ge","timing-allow-origin":"*","content-type":"text/javascript; charset=utf-8","via":"1.1 varnish\n1.1 varnish","accept-ranges":"bytes","date":"Tue, 15 Sep 2020 19:20:32 GMT","age":"6648772","x-served-by":"cache-bwi5130-BWI, cache-mdw17373-MDW","x-cache":"HIT, HIT","x-cache-hits":"1, 781279","x-timer":"S1600197632.139559,VS0,VE0","vary":"Accept-Encoding","content-length":"1215"}},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.3","timestamp":47786.47144,"dataLength":50408,"encodedDataLength":0},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.3","timestamp":47786.47273,"dataLength":46058,"encodedDataLength":10387},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56007.14","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","documentURL":"https://www.youtube.com/embed/tgbNymZ7vqY","request":{"url":"https://googleads.g.doubleclick.net/pagead/id","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"High","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.48466,"wallTime":1600197632.233352,"initiator":{"type":"script","stack":{"callFrames":[{"functionName":"xg","scriptId":"7","url":"https://www.youtube.com/s/player/e0d83c30/www-embed-player.vflset/www-embed-player.js","lineNumber":511,"columnNumber":493}]}},"type":"XHR","frameId":"D215705AC29C284D9BB2459B7020E798","hasUserGesture":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56007.15","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","documentURL":"https://www.youtube.com/embed/tgbNymZ7vqY","request":{"url":"https://static.doubleclick.net/instream/ad_status.js","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"Low","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.487095,"wallTime":1600197632.235787,"initiator":{"type":"script","stack":{"callFrames":[{"functionName":"af","scriptId":"7","url":"https://www.youtube.com/s/player/e0d83c30/www-embed-player.vflset/www-embed-player.js","lineNumber":424,"columnNumber":101}]}},"type":"Script","frameId":"D215705AC29C284D9BB2459B7020E798","hasUserGesture":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.3","timestamp":47786.490766,"dataLength":29303,"encodedDataLength":6855},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.3","timestamp":47786.492384,"dataLength":139511,"encodedDataLength":37017},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.3","timestamp":47786.494474,"dataLength":16840,"encodedDataLength":0},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.3","timestamp":47786.496535,"dataLength":61910,"encodedDataLength":0},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.responseReceived","params":{"requestId":"56010.5","loaderId":"51B3229F5358F49D44871ADE7185528C","timestamp":47786.497101,"type":"Script","response":{"url":"https://f.vimeocdn.com/js_opt/modules/utils/vuid.min.js","status":200,"statusText":"","headers":{"content-encoding":"gzip","status":"200","content-length":"1215","last-modified":"Tue, 30 Jun 2020 18:34:52 GMT","etag":"\"a51-5a9516e540b00\"","content-type":"text/javascript; charset=utf-8","cache-control":"max-age=315360000","accept-ranges":"bytes"},"mimeType":"text/javascript","connectionReused":true,"connectionId":109,"remoteIPAddress":"151.101.186.109","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":241,"timing":{"requestTime":47786.325692,"sendStart":69.843,"sendEnd":69.949,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":144.838},"responseTime":1600197632219.138,"protocol":"h2","securityState":"secure"},"frameId":"A0D1CEFE4B294AB844A8912CA96784F9"},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.5","timestamp":47786.497191,"dataLength":2641,"encodedDataLength":0},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.loadingFinished","params":{"requestId":"56010.5","timestamp":47786.496546,"encodedDataLength":1474,"shouldReportCorbBlocking":false},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56010.7","loaderId":"51B3229F5358F49D44871ADE7185528C","documentURL":"https://player.vimeo.com/video/336812660","request":{"url":"https://vimeo.com/ablincoln/vuid?pid=a88cdaf56540a693f597632ffeeaf6a38f56542a1600197631","method":"POST","headers":{"Content-Type":"text/plain;charset=UTF-8"},"hasPostData":true,"mixedContentType":"none","initialPriority":"VeryLow","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.499144,"wallTime":1600197632.247837,"initiator":{"type":"script","stack":{"callFrames":[{"functionName":"","scriptId":"9","url":"https://f.vimeocdn.com/js_opt/modules/utils/vuid.min.js","lineNumber":0,"columnNumber":2568}]}},"type":"Other","frameId":"A0D1CEFE4B294AB844A8912CA96784F9","hasUserGesture":false},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.3","timestamp":47786.499429,"dataLength":93529,"encodedDataLength":33741},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.loadingFinished","params":{"requestId":"56010.3","timestamp":47786.497091,"encodedDataLength":145772,"shouldReportCorbBlocking":false},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56007.16","associatedCookies":[{"blockedReasons":[],"cookie":{"name":"VISITOR_INFO1_LIVE","value":"FQVG-TcC8XQ","domain":".youtube.com","path":"/","expires":1615749631.052688,"size":29,"httpOnly":true,"secure":true,"session":false,"sameSite":"None","priority":"Medium"}},{"blockedReasons":[],"cookie":{"name":"YSC","value":"82k-4YzMCUo","domain":".youtube.com","path":"/","expires":-1,"size":14,"httpOnly":true,"secure":true,"session":true,"sameSite":"None","priority":"Medium"}}],"headers":{":method":"GET",":authority":"www.youtube.com",":scheme":"https",":path":"/s/player/e0d83c30/player_ias.vflset/en_US/embed.js","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"*/*","sec-fetch-site":"same-origin","sec-fetch-mode":"no-cors","sec-fetch-dest":"script","referer":"https://www.youtube.com/embed/tgbNymZ7vqY","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9","cookie":"VISITOR_INFO1_LIVE=FQVG-TcC8XQ; YSC=82k-4YzMCUo"}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56007.16","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","documentURL":"https://www.youtube.com/embed/tgbNymZ7vqY","request":{"url":"https://www.youtube.com/s/player/e0d83c30/player_ias.vflset/en_US/embed.js","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"Low","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.560845,"wallTime":1600197632.309538,"initiator":{"type":"script","stack":{"callFrames":[{"functionName":"QN","scriptId":"6","url":"https://www.youtube.com/s/player/e0d83c30/player_ias.vflset/en_US/base.js","lineNumber":3014,"columnNumber":124}]}},"type":"Script","frameId":"D215705AC29C284D9BB2459B7020E798","hasUserGesture":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56010.7","associatedCookies":[{"blockedReasons":[],"cookie":{"name":"vuid","value":"pl2063834542.17039668","domain":".vimeo.com","path":"/","expires":1663269632,"size":25,"httpOnly":false,"secure":true,"session":false,"sameSite":"None","priority":"Medium"}}],"headers":{"Host":"vimeo.com","Connection":"keep-alive","Content-Length":"0","User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","Content-Type":"text/plain;charset=UTF-8","Accept":"*/*","Origin":"https://player.vimeo.com","Sec-Fetch-Site":"same-site","Sec-Fetch-Mode":"no-cors","Sec-Fetch-Dest":"empty","Referer":"https://player.vimeo.com/video/336812660","Accept-Encoding":"gzip, deflate, br","Accept-Language":"en-US,en;q=0.9","Cookie":"vuid=pl2063834542.17039668"}},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56007.16","blockedCookies":[],"headers":{"status":"200","accept-ranges":"bytes","vary":"Accept-Encoding, Origin","content-encoding":"gzip","content-type":"text/javascript","content-length":"11094","date":"Mon, 14 Sep 2020 17:25:22 GMT","expires":"Tue, 14 Sep 2021 17:25:22 GMT","last-modified":"Mon, 14 Sep 2020 00:19:34 GMT","x-content-type-options":"nosniff","server":"sffe","x-xss-protection":"0","cache-control":"public, max-age=31536000","age":"93310","alt-svc":"h3-29=\":443\"; ma=2592000,h3-27=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56007.14","associatedCookies":[],"headers":{":method":"GET",":authority":"googleads.g.doubleclick.net",":scheme":"https",":path":"/pagead/id","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"*/*","origin":"https://www.youtube.com","sec-fetch-site":"cross-site","sec-fetch-mode":"cors","sec-fetch-dest":"empty","referer":"https://www.youtube.com/embed/tgbNymZ7vqY","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9"}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56007.15","associatedCookies":[],"headers":{":method":"GET",":authority":"static.doubleclick.net",":scheme":"https",":path":"/instream/ad_status.js","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"*/*","sec-fetch-site":"cross-site","sec-fetch-mode":"no-cors","sec-fetch-dest":"script","referer":"https://www.youtube.com/embed/tgbNymZ7vqY","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9"}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56010.8","associatedCookies":[],"headers":{":method":"GET",":authority":"i.vimeocdn.com",":scheme":"https",":path":"/video/784397921.webp?mw=1200&mh=675&q=70","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"image/avif,image/webp,image/apng,image/*,*/*;q=0.8","sec-fetch-site":"cross-site","sec-fetch-mode":"no-cors","sec-fetch-dest":"image","referer":"https://player.vimeo.com/video/336812660","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9"}},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56007.17","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","documentURL":"https://www.youtube.com/embed/tgbNymZ7vqY","request":{"url":"data:image/png;base64,FILLER","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"Low","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.568002,"wallTime":1600197632.316695,"initiator":{"type":"parser","url":"https://www.youtube.com/s/player/e0d83c30/www-player.css"},"type":"Image","frameId":"D215705AC29C284D9BB2459B7020E798","hasUserGesture":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestServedFromCache","params":{"requestId":"56007.17"},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceived","params":{"requestId":"56007.17","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","timestamp":47786.568024,"type":"Image","response":{"url":"data:image/png;base64,FILLER","status":200,"statusText":"OK","headers":{"Content-Type":"image/png"},"mimeType":"image/png","connectionReused":false,"connectionId":0,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":0,"protocol":"data","securityState":"unknown"},"frameId":"D215705AC29C284D9BB2459B7020E798"},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.17","timestamp":47786.56803,"dataLength":175,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.loadingFinished","params":{"requestId":"56007.17","timestamp":47786.568034,"encodedDataLength":0,"shouldReportCorbBlocking":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56007.18","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","documentURL":"https://www.youtube.com/embed/tgbNymZ7vqY","request":{"url":"https://yt3.ggpht.com/a/AATXAJxtCYVD65XPtigYUOad-Nd2v3EvnXnz__MkJrg=s68-c-k-c0x00ffffff-no-rj","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"Low","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.568581,"wallTime":1600197632.317274,"initiator":{"type":"parser","url":"https://www.youtube.com/embed/tgbNymZ7vqY"},"type":"Image","frameId":"D215705AC29C284D9BB2459B7020E798","hasUserGesture":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56007.19","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","documentURL":"https://www.youtube.com/embed/tgbNymZ7vqY","request":{"url":"https://i.ytimg.com/vi/tgbNymZ7vqY/maxresdefault.jpg","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"Low","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.569482,"wallTime":1600197632.318174,"initiator":{"type":"parser","url":"https://www.youtube.com/embed/tgbNymZ7vqY"},"type":"Image","frameId":"D215705AC29C284D9BB2459B7020E798","hasUserGesture":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56007.6","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","documentURL":"https://www.youtube.com/embed/tgbNymZ7vqY","request":{"url":"https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu4mxPKTU1Kg.ttf","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"VeryHigh","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.602037,"wallTime":1600197632.350731,"initiator":{"type":"parser","url":"https://www.youtube.com/embed/tgbNymZ7vqY"},"type":"Font","frameId":"D215705AC29C284D9BB2459B7020E798","hasUserGesture":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.resourceChangedPriority","params":{"requestId":"56007.18","newPriority":"High","timestamp":47786.606936},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.resourceChangedPriority","params":{"requestId":"56007.19","newPriority":"High","timestamp":47786.606951},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56010.8","loaderId":"51B3229F5358F49D44871ADE7185528C","documentURL":"https://player.vimeo.com/video/336812660","request":{"url":"https://i.vimeocdn.com/video/784397921.webp?mw=1200&mh=675&q=70","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"Low","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.605767,"wallTime":1600197632.35446,"initiator":{"type":"parser","url":"https://player.vimeo.com/video/336812660","lineNumber":0},"type":"Image","frameId":"A0D1CEFE4B294AB844A8912CA96784F9","hasUserGesture":false},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56010.9","loaderId":"51B3229F5358F49D44871ADE7185528C","documentURL":"https://player.vimeo.com/video/336812660","request":{"url":"https://fresnel.vimeocdn.com/add/player-stats?beacon=1&session-id=a88cdaf56540a693f597632ffeeaf6a38f56542a1600197631","method":"POST","headers":{"Content-Type":"text/plain;charset=UTF-8"},"postData":"[{\"autoplay\":false,\"background\":false,\"clip_id\":336812660,\"context\":\"embed.main\",\"device_pixel_ratio\":2,\"drm\":false,\"embed\":true,\"is_mod\":false,\"is_spatial\":false,\"logged_in\":false,\"looping\":false,\"owner_id\":90564994,\"product\":\"vimeo-vod\",\"referrer\":\"http://localhost:8686/yt-embed.html\",\"session_id\":\"a88cdaf56540a693f597632ffeeaf6a38f56542a1600197631\",\"stayed_on_auto\":true,\"version\":\"3.22.3\",\"version_backend\":\"1.21.1\",\"viewer_id\":0,\"viewer_team_id\":0,\"viewer_team_origin_user_id\":0,\"vuid\":\"pl2063834542.17039668\",\"account_type\":\"enterprise\",\"privacy\":\"anybody\",\"audio_bitrate\":0,\"auto\":true,\"average_speed\":0,\"cdn\":\"akfire_interconnect_quic\",\"delivery\":\"dash\",\"dropped_frames\":0,\"dropped_frame_percent\":0,\"event_time\":1600197631,\"ended\":false,\"forced_embed_quality\":\"none\",\"fullscreen\":false,\"highest_available_profile\":\"175\",\"highest_profile\":null,\"max_speed\":0,\"mime\":\"application/vnd.vimeo.dash+json\",\"min_speed\":0,\"most_used_profile\":null,\"origin\":\"gcs\",\"profile_id\":null,\"codec\":\"\",\"quality_downswitch_count\":0,\"quality_upswitch_count\":0,\"quality_switch_count\":0,\"separate_av\":true,\"target_profile_id\":null,\"ttfb\":0,\"video_bitrate\":0,\"video_duration\":55,\"video_file_id\":null,\"chromecast_test\":1,\"chromecast_group\":false,\"name\":\"video-ready\"}]","hasPostData":true,"mixedContentType":"none","initialPriority":"VeryLow","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.608265,"wallTime":1600197632.356958,"initiator":{"type":"script","stack":{"callFrames":[{"functionName":"","scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js","lineNumber":9,"columnNumber":237643}]}},"type":"Other","frameId":"A0D1CEFE4B294AB844A8912CA96784F9","hasUserGesture":false},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.responseReceived","params":{"requestId":"56007.16","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","timestamp":47786.60909,"type":"Script","response":{"url":"https://www.youtube.com/s/player/e0d83c30/player_ias.vflset/en_US/embed.js","status":200,"statusText":"","headers":{"content-encoding":"gzip","last-modified":"Mon, 14 Sep 2020 00:19:34 GMT","content-type":"text/javascript","status":"200","cache-control":"public, max-age=31536000","accept-ranges":"bytes","content-length":"11094"},"mimeType":"text/javascript","connectionReused":false,"connectionId":0,"remoteIPAddress":"172.217.1.46","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":383,"timing":{"requestTime":47786.561199,"dnsStart":0,"dnsEnd":0,"connectStart":0,"connectEnd":0,"sslStart":0,"sslEnd":0,"sendStart":0.283,"sendEnd":0.455,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":19.711},"responseTime":1600197632329.537,"protocol":"h3-Q050","securityState":"secure"},"frameId":"D215705AC29C284D9BB2459B7020E798"},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.16","timestamp":47786.60921,"dataLength":35953,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.16","timestamp":47786.610343,"dataLength":0,"encodedDataLength":11094},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.loadingFinished","params":{"requestId":"56007.16","timestamp":47786.581515,"encodedDataLength":11477,"shouldReportCorbBlocking":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56007.15","blockedCookies":[],"headers":{"status":"200","accept-ranges":"bytes","content-type":"text/javascript","access-control-allow-origin":"*","timing-allow-origin":"*","content-length":"29","date":"Tue, 15 Sep 2020 19:14:45 GMT","expires":"Tue, 15 Sep 2020 19:29:45 GMT","last-modified":"Thu, 12 Dec 2013 23:40:16 GMT","x-content-type-options":"nosniff","server":"sffe","x-xss-protection":"0","cache-control":"public, max-age=900","age":"347","alt-svc":"h3-Q050=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000,h3-27=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceived","params":{"requestId":"56007.15","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","timestamp":47786.630201,"type":"Script","response":{"url":"https://static.doubleclick.net/instream/ad_status.js","status":200,"statusText":"","headers":{"last-modified":"Thu, 12 Dec 2013 23:40:16 GMT","status":"200","content-type":"text/javascript","cache-control":"public, max-age=900","accept-ranges":"bytes","content-length":"29"},"mimeType":"text/javascript","connectionReused":false,"connectionId":151,"remoteIPAddress":"172.217.9.38","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":377,"timing":{"requestTime":47786.487395,"dnsStart":0.117,"dnsEnd":48.513,"connectStart":48.513,"connectEnd":116.683,"sslStart":74.387,"sslEnd":116.68,"sendStart":116.781,"sendEnd":116.857,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":142.036},"responseTime":1600197632378.034,"protocol":"h2","securityState":"secure"},"frameId":"D215705AC29C284D9BB2459B7020E798"},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.15","timestamp":47786.630285,"dataLength":29,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.loadingFinished","params":{"requestId":"56007.15","timestamp":47786.629669,"encodedDataLength":415,"shouldReportCorbBlocking":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56010.8","blockedCookies":[],"headers":{"status":"200","content-type":"image/webp","etag":"cb2f59f448702c8a5630ca93a4196adc","x-viewmaster-webp-format":"lossy","viewmaster-server":"viewmaster-us-central1-qf6x","cache-control":"public, max-age=2592000","via":"vvarnish\n1.1 varnish\n1.1 varnish","x-backend-server":"varnish","access-control-allow-origin":"*","accept-ranges":"bytes","date":"Tue, 15 Sep 2020 19:20:32 GMT","age":"2082635","x-served-by":"cache-dfw18674-DFW, cache-pwk4931-PWK","x-cache":"miss, HIT, HIT","x-cache-hits":"1, 1","x-timer":"S1600197632.349166,VS0,VE1","content-length":"9128"}},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.responseReceived","params":{"requestId":"56010.8","loaderId":"51B3229F5358F49D44871ADE7185528C","timestamp":47786.635785,"type":"Image","response":{"url":"https://i.vimeocdn.com/video/784397921.webp?mw=1200&mh=675&q=70","status":200,"statusText":"","headers":{"status":"200","content-length":"9128","etag":"cb2f59f448702c8a5630ca93a4196adc","content-type":"image/webp","cache-control":"public, max-age=2592000","accept-ranges":"bytes"},"mimeType":"image/webp","connectionReused":true,"connectionId":112,"remoteIPAddress":"199.232.78.109","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":176,"timing":{"requestTime":47786.606134,"sendStart":0.179,"sendEnd":0.28,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":27.927},"responseTime":1600197632382.678,"protocol":"h2","securityState":"secure"},"frameId":"A0D1CEFE4B294AB844A8912CA96784F9"},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.dataReceived","params":{"requestId":"56010.8","timestamp":47786.635866,"dataLength":9128,"encodedDataLength":0},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.loadingFinished","params":{"requestId":"56010.8","timestamp":47786.63528,"encodedDataLength":9313,"shouldReportCorbBlocking":false},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56010.9","associatedCookies":[],"headers":{":method":"POST",":authority":"fresnel.vimeocdn.com",":scheme":"https",":path":"/add/player-stats?beacon=1&session-id=a88cdaf56540a693f597632ffeeaf6a38f56542a1600197631","content-length":"1251","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","content-type":"text/plain;charset=UTF-8","accept":"*/*","origin":"https://player.vimeo.com","sec-fetch-site":"cross-site","sec-fetch-mode":"no-cors","sec-fetch-dest":"empty","referer":"https://player.vimeo.com/video/336812660","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9"}},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56007.18","associatedCookies":[],"headers":{":method":"GET",":authority":"yt3.ggpht.com",":scheme":"https",":path":"/a/AATXAJxtCYVD65XPtigYUOad-Nd2v3EvnXnz__MkJrg=s68-c-k-c0x00ffffff-no-rj","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"image/avif,image/webp,image/apng,image/*,*/*;q=0.8","sec-fetch-site":"cross-site","sec-fetch-mode":"no-cors","sec-fetch-dest":"image","referer":"https://www.youtube.com/embed/tgbNymZ7vqY","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9"}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56007.19","associatedCookies":[],"headers":{":method":"GET",":authority":"i.ytimg.com",":scheme":"https",":path":"/vi/tgbNymZ7vqY/maxresdefault.jpg","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"image/avif,image/webp,image/apng,image/*,*/*;q=0.8","sec-fetch-site":"cross-site","sec-fetch-mode":"no-cors","sec-fetch-dest":"image","referer":"https://www.youtube.com/embed/tgbNymZ7vqY","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9"}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56007.14","blockedCookies":[],"headers":{"status":"302","p3p":"policyref=\"https://googleads.g.doubleclick.net/pagead/gcn_p3p_.xml\", CP=\"CURa ADMa DEVa TAIo PSAo PSDo OUR IND UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR\"","timing-allow-origin":"*","location":"https://googleads.g.doubleclick.net/pagead/id?slf_rd=1","access-control-allow-credentials":"true","access-control-allow-origin":"https://www.youtube.com","date":"Tue, 15 Sep 2020 19:20:32 GMT","pragma":"no-cache","expires":"Fri, 01 Jan 1990 00:00:00 GMT","cache-control":"no-cache, no-store, must-revalidate","content-type":"text/html; charset=UTF-8","x-content-type-options":"nosniff","server":"cafe","content-length":"0","x-xss-protection":"0","set-cookie":"test_cookie=CheckForPermission; expires=Tue, 15-Sep-2020 19:35:32 GMT; path=/; domain=.doubleclick.net; Secure; SameSite=none","alt-svc":"h3-29=\"googleads.g.doubleclick.net:443\"; ma=2592000,h3-29=\":443\"; ma=2592000,h3-27=\"googleads.g.doubleclick.net:443\"; ma=2592000,h3-27=\":443\"; ma=2592000,h3-T051=\"googleads.g.doubleclick.net:443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\"googleads.g.doubleclick.net:443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q050=\"googleads.g.doubleclick.net:443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\"googleads.g.doubleclick.net:443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\"googleads.g.doubleclick.net:443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\"googleads.g.doubleclick.net:443\"; ma=2592000; v=\"46,43\",quic=\":443\"; ma=2592000; v=\"46,43\""}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56007.14","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","documentURL":"https://www.youtube.com/embed/tgbNymZ7vqY","request":{"url":"https://googleads.g.doubleclick.net/pagead/id?slf_rd=1","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"High","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.673984,"wallTime":1600197632.422678,"initiator":{"type":"parser","url":"https://www.youtube.com/embed/tgbNymZ7vqY","lineNumber":0},"redirectResponse":{"url":"https://googleads.g.doubleclick.net/pagead/id","status":302,"statusText":"","headers":{"status":"302","content-length":"0","content-type":"text/html; charset=UTF-8","cache-control":"no-cache, no-store, must-revalidate"},"mimeType":"text/html","connectionReused":false,"connectionId":150,"remoteIPAddress":"172.217.4.194","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":1012,"timing":{"requestTime":47786.485017,"dnsStart":0.174,"dnsEnd":44.086,"connectStart":44.086,"connectEnd":109.738,"sslStart":63.365,"sslEnd":109.731,"sendStart":109.897,"sendEnd":109.989,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":188.084},"responseTime":1600197632421.68,"protocol":"h2","securityState":"secure"},"type":"XHR","frameId":"D215705AC29C284D9BB2459B7020E798","hasUserGesture":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56007.18","blockedCookies":[],"headers":{"status":"200","access-control-expose-headers":"Content-Length","etag":"\"v10\"","expires":"Thu, 10 Sep 2020 12:19:38 GMT","content-disposition":"inline;filename=\"unnamed.jpg\"","content-type":"image/jpeg","vary":"Origin","access-control-allow-origin":"*","timing-allow-origin":"*","x-content-type-options":"nosniff","date":"Tue, 15 Sep 2020 16:28:38 GMT","server":"fife","content-length":"2639","x-xss-protection":"0","age":"10314","cache-control":"public, max-age=86400, no-transform","alt-svc":"h3-Q050=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000,h3-27=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceived","params":{"requestId":"56007.18","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","timestamp":47786.682168,"type":"Image","response":{"url":"https://yt3.ggpht.com/a/AATXAJxtCYVD65XPtigYUOad-Nd2v3EvnXnz__MkJrg=s68-c-k-c0x00ffffff-no-rj","status":200,"statusText":"","headers":{"status":"200","content-length":"2639","etag":"\"v10\"","content-type":"image/jpeg","cache-control":"public, max-age=86400, no-transform"},"mimeType":"image/jpeg","connectionReused":false,"connectionId":186,"remoteIPAddress":"172.217.9.33","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":429,"timing":{"requestTime":47786.568895,"dnsStart":0.18,"dnsEnd":37.824,"connectStart":37.824,"connectEnd":89.697,"sslStart":55.068,"sslEnd":89.691,"sendStart":89.842,"sendEnd":89.932,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":110.806},"responseTime":1600197632428.292,"protocol":"h2","securityState":"secure"},"frameId":"D215705AC29C284D9BB2459B7020E798"},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.18","timestamp":47786.682249,"dataLength":2639,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.loadingFinished","params":{"requestId":"56007.18","timestamp":47786.681621,"encodedDataLength":3077,"shouldReportCorbBlocking":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56007.19","blockedCookies":[],"headers":{"status":"200","accept-ranges":"bytes","content-type":"image/jpeg","timing-allow-origin":"*","content-length":"65873","date":"Tue, 15 Sep 2020 19:01:49 GMT","expires":"Tue, 15 Sep 2020 21:01:49 GMT","etag":"\"0\"","x-content-type-options":"nosniff","server":"sffe","x-xss-protection":"0","cache-control":"public, max-age=7200","age":"1123","alt-svc":"h3-29=\":443\"; ma=2592000,h3-27=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceived","params":{"requestId":"56007.19","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","timestamp":47786.695331,"type":"Image","response":{"url":"https://i.ytimg.com/vi/tgbNymZ7vqY/maxresdefault.jpg","status":200,"statusText":"","headers":{"etag":"\"0\"","content-type":"image/jpeg","status":"200","cache-control":"public, max-age=7200","accept-ranges":"bytes","content-length":"65873"},"mimeType":"image/jpeg","connectionReused":false,"connectionId":181,"remoteIPAddress":"172.217.8.214","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":355,"timing":{"requestTime":47786.569798,"dnsStart":0.182,"dnsEnd":35.828,"connectStart":35.828,"connectEnd":91.177,"sslStart":52.472,"sslEnd":91.173,"sendStart":91.272,"sendEnd":91.352,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":122.919},"responseTime":1600197632441.314,"protocol":"h2","securityState":"secure"},"frameId":"D215705AC29C284D9BB2459B7020E798"},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.19","timestamp":47786.695423,"dataLength":5575,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.19","timestamp":47786.696713,"dataLength":6980,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.19","timestamp":47786.699249,"dataLength":8367,"encodedDataLength":12564},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.19","timestamp":47786.701507,"dataLength":6980,"encodedDataLength":8376},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.19","timestamp":47786.703162,"dataLength":1396,"encodedDataLength":6980},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56010.9","blockedCookies":[],"headers":{"status":"200","access-control-allow-credentials":"true","access-control-allow-origin":"https://player.vimeo.com","date":"Tue, 15 Sep 2020 19:20:32 GMT","content-length":"0","via":"1.1 google","alt-svc":"clear"}},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.responseReceived","params":{"requestId":"56010.9","loaderId":"51B3229F5358F49D44871ADE7185528C","timestamp":47786.704156,"type":"Other","response":{"url":"https://fresnel.vimeocdn.com/add/player-stats?beacon=1&session-id=a88cdaf56540a693f597632ffeeaf6a38f56542a1600197631","status":200,"statusText":"","headers":{"status":"200","content-length":"0"},"mimeType":"text/plain","connectionReused":false,"connectionId":191,"remoteIPAddress":"34.120.202.204","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":110,"timing":{"requestTime":47786.608785,"dnsStart":0.113,"dnsEnd":0.118,"connectStart":0.118,"connectEnd":44.498,"sslStart":15.325,"sslEnd":44.493,"sendStart":44.601,"sendEnd":44.701,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":94.751},"responseTime":1600197632452.174,"protocol":"h2","securityState":"secure"},"frameId":"A0D1CEFE4B294AB844A8912CA96784F9"},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.loadingFinished","params":{"requestId":"56010.9","timestamp":47786.703717,"encodedDataLength":110,"shouldReportCorbBlocking":false},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Page.lifecycleEvent","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","loaderId":"DA13668C4781FCB2BF6F3AB0F3313AB7","name":"networkAlmostIdle","timestamp":47786.059957}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","loaderId":"DA13668C4781FCB2BF6F3AB0F3313AB7","name":"firstMeaningfulPaint","timestamp":47786.179669}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","loaderId":"DA13668C4781FCB2BF6F3AB0F3313AB7","name":"networkIdle","timestamp":47786.059957}}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56007.6","associatedCookies":[],"headers":{":method":"GET",":authority":"fonts.gstatic.com",":scheme":"https",":path":"/s/roboto/v18/KFOmCnqEu92Fr1Mu4mxPKTU1Kg.ttf","origin":"https://www.youtube.com","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"*/*","sec-fetch-site":"cross-site","sec-fetch-mode":"cors","sec-fetch-dest":"font","referer":"https://www.youtube.com/embed/tgbNymZ7vqY","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9"}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56007.14","associatedCookies":[{"blockedReasons":[],"cookie":{"name":"test_cookie","value":"CheckForPermission","domain":".doubleclick.net","path":"/","expires":1600198532.421805,"size":29,"httpOnly":false,"secure":true,"session":false,"sameSite":"None","priority":"Medium"}}],"headers":{":method":"GET",":authority":"googleads.g.doubleclick.net",":scheme":"https",":path":"/pagead/id?slf_rd=1","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36","accept":"*/*","origin":"https://www.youtube.com","sec-fetch-site":"cross-site","sec-fetch-mode":"cors","sec-fetch-dest":"empty","referer":"https://www.youtube.com/embed/tgbNymZ7vqY","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9","cookie":"test_cookie=CheckForPermission"}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.19","timestamp":47786.726555,"dataLength":16025,"encodedDataLength":1396},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.19","timestamp":47786.727898,"dataLength":2792,"encodedDataLength":16034},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56007.6","blockedCookies":[],"headers":{"status":"200","accept-ranges":"bytes","vary":"Accept-Encoding","content-encoding":"gzip","content-type":"font/ttf","access-control-allow-origin":"*","timing-allow-origin":"*","content-length":"14353","date":"Tue, 15 Sep 2020 07:45:21 GMT","expires":"Wed, 15 Sep 2021 07:45:21 GMT","last-modified":"Mon, 16 Oct 2017 17:32:51 GMT","x-content-type-options":"nosniff","server":"sffe","x-xss-protection":"0","age":"41711","cache-control":"public, max-age=31536000","alt-svc":"h3-29=\":443\"; ma=2592000,h3-27=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceived","params":{"requestId":"56007.6","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","timestamp":47786.73018,"type":"Font","response":{"url":"https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu4mxPKTU1Kg.ttf","status":200,"statusText":"","headers":{"content-encoding":"gzip","status":"200","content-length":"14353","last-modified":"Mon, 16 Oct 2017 17:32:51 GMT","content-type":"font/ttf","cache-control":"public, max-age=31536000","accept-ranges":"bytes"},"mimeType":"font/ttf","connectionReused":false,"connectionId":199,"remoteIPAddress":"172.217.0.3","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":397,"timing":{"requestTime":47786.609857,"dnsStart":0.131,"dnsEnd":35.412,"connectStart":35.412,"connectEnd":95.703,"sslStart":63.471,"sslEnd":95.699,"sendStart":95.8,"sendEnd":95.882,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":119.779},"responseTime":1600197632478.239,"protocol":"h2","securityState":"secure"},"frameId":"D215705AC29C284D9BB2459B7020E798"},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.19","timestamp":47786.731444,"dataLength":11159,"encodedDataLength":2792},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.19","timestamp":47786.733819,"dataLength":6599,"encodedDataLength":11168},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.19","timestamp":47786.734106,"dataLength":0,"encodedDataLength":6608},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.loadingFinished","params":{"requestId":"56007.19","timestamp":47786.733333,"encodedDataLength":66273,"shouldReportCorbBlocking":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.6","timestamp":47786.734901,"dataLength":17329,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.6","timestamp":47786.743989,"dataLength":3535,"encodedDataLength":12564},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.6","timestamp":47786.759485,"dataLength":0,"encodedDataLength":1798},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.loadingFinished","params":{"requestId":"56007.6","timestamp":47786.743963,"encodedDataLength":14759,"shouldReportCorbBlocking":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Page.loadEventFired","params":{"timestamp":47786.774417}}, + {"method":"Page.lifecycleEvent","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","loaderId":"DA13668C4781FCB2BF6F3AB0F3313AB7","name":"load","timestamp":47786.774417}}, + {"method":"Page.frameStoppedLoading","params":{"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A"}}, + {"method":"Network.requestWillBeSent","params":{"requestId":"56001.2","loaderId":"DA13668C4781FCB2BF6F3AB0F3313AB7","documentURL":"http://localhost:8686/yt-embed.html","request":{"url":"http://localhost:8686/favicon.ico","method":"GET","headers":{},"mixedContentType":"none","initialPriority":"High","referrerPolicy":"no-referrer-when-downgrade"},"timestamp":47786.776671,"wallTime":1600197632.525365,"initiator":{"type":"other"},"type":"Other","frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A","hasUserGesture":false}}, + {"method":"Network.requestWillBeSentExtraInfo","params":{"requestId":"56001.2","associatedCookies":[],"headers":{"Host":"localhost:8686","Connection":"keep-alive","User-Agent":"Mozilla/5.0 (Linux; Android 7.0; Moto G (4)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4143.7 Mobile Safari/537.36 Chrome-Lighthouse","Accept":"image/avif,image/webp,image/apng,image/*,*/*;q=0.8","Sec-Fetch-Site":"same-origin","Sec-Fetch-Mode":"no-cors","Sec-Fetch-Dest":"image","Referer":"http://localhost:8686/yt-embed.html","Accept-Encoding":"gzip, deflate, br","Accept-Language":"en-US,en;q=0.9"}}}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56001.2","blockedCookies":[],"headers":{"Server":"SimpleHTTP/0.6 Python/3.6.8","Date":"Tue, 15 Sep 2020 19:20:32 GMT","Connection":"close","Content-Type":"text/html;charset=utf-8","Content-Length":"469"},"headersText":"HTTP/1.0 404 File not found\r\nServer: SimpleHTTP/0.6 Python/3.6.8\r\nDate: Tue, 15 Sep 2020 19:20:32 GMT\r\nConnection: close\r\nContent-Type: text/html;charset=utf-8\r\nContent-Length: 469\r\n\r\n"}}, + {"method":"Network.responseReceived","params":{"requestId":"56001.2","loaderId":"DA13668C4781FCB2BF6F3AB0F3313AB7","timestamp":47786.778393,"type":"Other","response":{"url":"http://localhost:8686/favicon.ico","status":404,"statusText":"File not found","headers":{"Content-Length":"469","Content-Type":"text/html;charset=utf-8"},"mimeType":"text/html","connectionReused":true,"connectionId":31,"remoteIPAddress":"127.0.0.1","remotePort":8686,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":184,"timing":{"requestTime":47786.77703,"sendStart":0.176,"sendEnd":0.221,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":0.927},"responseTime":1600197632526.586,"protocol":"http/1.0","securityState":"secure"},"frameId":"8ECEE70925EB8E7B8C2100384AFF4D1A"}}, + {"method":"Network.dataReceived","params":{"requestId":"56001.2","timestamp":47786.778628,"dataLength":469,"encodedDataLength":0}}, + {"method":"Network.dataReceived","params":{"requestId":"56001.2","timestamp":47786.778874,"dataLength":0,"encodedDataLength":469}}, + {"method":"Network.loadingFinished","params":{"requestId":"56001.2","timestamp":47786.778266,"encodedDataLength":653,"shouldReportCorbBlocking":false}}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56007.14","blockedCookies":[],"headers":{"status":"200","p3p":"policyref=\"https://googleads.g.doubleclick.net/pagead/gcn_p3p_.xml\", CP=\"CURa ADMa DEVa TAIo PSAo PSDo OUR IND UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR\"","timing-allow-origin":"*","access-control-allow-credentials":"true","access-control-allow-origin":"https://www.youtube.com","content-type":"application/json; charset=UTF-8","date":"Tue, 15 Sep 2020 19:20:32 GMT","pragma":"no-cache","expires":"Fri, 01 Jan 1990 00:00:00 GMT","cache-control":"no-cache, no-store, must-revalidate","x-content-type-options":"nosniff","content-disposition":"attachment; filename=\"f.txt\"","content-encoding":"gzip","server":"cafe","content-length":"133","x-xss-protection":"0","set-cookie":"test_cookie=; domain=.doubleclick.net; path=/; expires=Mon, 21 Jul 2008 23:59:00 GMT; SameSite=none; Secure\nIDE=AHWqTUkwqZAglOH_6PFh4sqUYyc0K0jsXY_Ce0WIfNzGy8j_jI7Ldydn8sN2wN7E; expires=Thu, 15-Sep-2022 19:20:32 GMT; path=/; domain=.doubleclick.net; Secure; HttpOnly; SameSite=none","alt-svc":"h3-29=\"googleads.g.doubleclick.net:443\"; ma=2592000,h3-29=\":443\"; ma=2592000,h3-27=\"googleads.g.doubleclick.net:443\"; ma=2592000,h3-27=\":443\"; ma=2592000,h3-T051=\"googleads.g.doubleclick.net:443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-T050=\"googleads.g.doubleclick.net:443\"; ma=2592000,h3-T050=\":443\"; ma=2592000,h3-Q050=\"googleads.g.doubleclick.net:443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\"googleads.g.doubleclick.net:443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\"googleads.g.doubleclick.net:443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\"googleads.g.doubleclick.net:443\"; ma=2592000; v=\"46,43\",quic=\":443\"; ma=2592000; v=\"46,43\""}},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceived","params":{"requestId":"56007.14","loaderId":"7409A683C44F8397F7103BD7E03CB6C9","timestamp":47786.789835,"type":"XHR","response":{"url":"https://googleads.g.doubleclick.net/pagead/id?slf_rd=1","status":200,"statusText":"","headers":{"content-encoding":"gzip","status":"200","content-length":"133","content-type":"application/json; charset=UTF-8","cache-control":"no-cache, no-store, must-revalidate"},"mimeType":"application/json","connectionReused":false,"connectionId":0,"remoteIPAddress":"172.217.4.194","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":1121,"timing":{"requestTime":47786.674157,"dnsStart":0.112,"dnsEnd":0.12,"connectStart":0.328,"connectEnd":67.778,"sslStart":0.328,"sslEnd":67.778,"sendStart":36.97,"sendEnd":37.086,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":114.785},"responseTime":1600197632537.57,"protocol":"h3-Q050","securityState":"secure"},"frameId":"D215705AC29C284D9BB2459B7020E798"},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.14","timestamp":47786.789969,"dataLength":113,"encodedDataLength":0},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.dataReceived","params":{"requestId":"56007.14","timestamp":47786.791217,"dataLength":0,"encodedDataLength":133},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.loadingFinished","params":{"requestId":"56007.14","timestamp":47786.789606,"encodedDataLength":1254,"shouldReportCorbBlocking":false},"sessionId":"DA677F833BBB83B41D000F18A18B822E"}, + {"method":"Network.responseReceivedExtraInfo","params":{"requestId":"56010.7","blockedCookies":[],"headers":{"Connection":"keep-alive","Server":"nginx","Expires":"Tue, 15 Sep 2020 07:20:33 GMT","Cache-Control":"no-store, no-cache, must-revalidate, post-check=0, pre-check=0","X-UA-Compatible":"IE=edge","X-XSS-Protection":"1; mode=block","X-Content-Type-Options":"nosniff","X-Frame-Options":"sameorigin","Strict-Transport-Security":"max-age=31536000; includeSubDomains; preload","Content-Security-Policy-Report-Only":"default-src https: data: blob: wss: 'unsafe-inline' 'unsafe-eval'; report-uri /_csp","X-BApp-Server":"pweb-v3126-6m5fd","X-Vimeo-DC":"ge","Accept-Ranges":"bytes\nbytes","Via":"1.1 varnish\n1.1 varnish","Date":"Tue, 15 Sep 2020 19:20:33 GMT","X-Served-By":"cache-bwi5142-BWI, cache-chi21152-CHI","X-Cache":"MISS, MISS","X-Cache-Hits":"0, 0","X-Timer":"S1600197632.317759,VS0,VE1036","Vary":"User-Agent"},"headersText":"HTTP/1.1 204 No Content\r\nConnection: keep-alive\r\nServer: nginx\r\nExpires: Tue, 15 Sep 2020 07:20:33 GMT\r\nCache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\r\nX-UA-Compatible: IE=edge\r\nX-XSS-Protection: 1; mode=block\r\nX-Content-Type-Options: nosniff\r\nX-Frame-Options: sameorigin\r\nStrict-Transport-Security: max-age=31536000; includeSubDomains; preload\r\nContent-Security-Policy-Report-Only: default-src https: data: blob: wss: 'unsafe-inline' 'unsafe-eval'; report-uri /_csp\r\nX-BApp-Server: pweb-v3126-6m5fd\r\nX-Vimeo-DC: ge\r\nAccept-Ranges: bytes\r\nVia: 1.1 varnish\r\nAccept-Ranges: bytes\r\nDate: Tue, 15 Sep 2020 19:20:33 GMT\r\nVia: 1.1 varnish\r\nX-Served-By: cache-bwi5142-BWI, cache-chi21152-CHI\r\nX-Cache: MISS, MISS\r\nX-Cache-Hits: 0, 0\r\nX-Timer: S1600197632.317759,VS0,VE1036\r\nVary: User-Agent\r\n\r\n"},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.responseReceived","params":{"requestId":"56010.7","loaderId":"51B3229F5358F49D44871ADE7185528C","timestamp":47787.642967,"type":"Other","response":{"url":"https://vimeo.com/ablincoln/vuid?pid=a88cdaf56540a693f597632ffeeaf6a38f56542a1600197631","status":204,"statusText":"No Content","headers":{"Cache-Control":"no-store, no-cache, must-revalidate, post-check=0, pre-check=0","Accept-Ranges":"bytes, bytes"},"mimeType":"text/plain","connectionReused":false,"connectionId":149,"remoteIPAddress":"151.101.0.217","remotePort":443,"fromDiskCache":false,"fromServiceWorker":false,"fromPrefetchCache":false,"encodedDataLength":818,"timing":{"requestTime":47786.499527,"dnsStart":0.097,"dnsEnd":25.829,"connectStart":25.829,"connectEnd":77.571,"sslStart":44.659,"sslEnd":77.567,"sendStart":77.624,"sendEnd":77.682,"pushStart":0,"pushEnd":0,"receiveHeadersEnd":1142.011},"responseTime":1600197633390.104,"protocol":"http/1.1","securityState":"secure"},"frameId":"A0D1CEFE4B294AB844A8912CA96784F9"},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"}, + {"method":"Network.loadingFinished","params":{"requestId":"56010.7","timestamp":47787.64191,"encodedDataLength":818,"shouldReportCorbBlocking":false},"sessionId":"9ACCDD85E62DB148629025C55DB5B6D7"} +] \ No newline at end of file diff --git a/lighthouse-core/test/fixtures/traces/video-embeds-m84.json b/lighthouse-core/test/fixtures/traces/video-embeds-m84.json new file mode 100644 index 000000000000..0d06558ec2d2 --- /dev/null +++ b/lighthouse-core/test/fixtures/traces/video-embeds-m84.json @@ -0,0 +1,266 @@ +{ + "traceEvents": [ + {"args":{"data":{"frameTreeNodeId":2,"frames":[{"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A","name":"","processId":56001,"url":"about:blank"}],"persistentIds":true}},"cat":"disabled-by-default-devtools.timeline","name":"TracingStartedInBrowser","ph":"I","pid":55969,"s":"t","tid":775,"ts":47786037668,"tts":734763}, + {"args":{"data":{"type":"beforeunload"}},"cat":"devtools.timeline","dur":10,"name":"EventDispatch","ph":"X","pid":56001,"tdur":10,"tid":775,"ts":47786040940,"tts":586500}, + {"args":{},"cat":"disabled-by-default-devtools.timeline","dur":4292,"name":"RunTask","ph":"X","pid":56001,"tdur":4291,"tid":775,"ts":47786046202,"tts":586834}, + {"args":{"data":{"type":"pagehide"}},"cat":"devtools.timeline","dur":5,"name":"EventDispatch","ph":"X","pid":56001,"tdur":6,"tid":775,"ts":47786046659,"tts":587290}, + {"args":{"data":{"type":"visibilitychange"}},"cat":"devtools.timeline","dur":3,"name":"EventDispatch","ph":"X","pid":56001,"tdur":4,"tid":775,"ts":47786046672,"tts":587303}, + {"args":{"data":{"type":"webkitvisibilitychange"}},"cat":"devtools.timeline","dur":2,"name":"EventDispatch","ph":"X","pid":56001,"tdur":2,"tid":775,"ts":47786046678,"tts":587310}, + {"args":{"data":{"type":"unload"}},"cat":"devtools.timeline","dur":2,"name":"EventDispatch","ph":"X","pid":56001,"tdur":2,"tid":775,"ts":47786046688,"tts":587319}, + {"args":{"data":{"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A","priority":"VeryHigh","requestId":"DA13668C4781FCB2BF6F3AB0F3313AB7","requestMethod":"GET","url":"http://localhost:8686/yt-embed.html"}},"cat":"devtools.timeline","name":"ResourceSendRequest","ph":"I","pid":56001,"s":"t","tid":775,"ts":47786046945,"tts":587577}, + {"args":{"data":{"encodedDataLength":185,"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A","fromCache":false,"fromServiceWorker":false,"mimeType":"text/html","requestId":"DA13668C4781FCB2BF6F3AB0F3313AB7","responseTime":1600197631792.842,"statusCode":200,"timing":{"connectEnd":0.662,"connectStart":0.267,"dnsEnd":0.267,"dnsStart":0.259,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":1.36,"requestTime":47786.042861,"sendEnd":0.754,"sendStart":0.705,"sslEnd":-1,"sslStart":-1,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56001,"s":"t","tid":775,"ts":47786046977,"tts":587609}, + {"args":{"data":{"columnNumber":1,"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A","lineNumber":1,"url":""}},"cat":"devtools.timeline","dur":275,"name":"EvaluateScript","ph":"X","pid":56001,"tdur":276,"tid":775,"ts":47786049481,"tts":590112}, + {"args":{"data":{"columnNumber":1,"lineNumber":1,"notStreamedReason":"inline script","streamed":false,"url":""},"fileName":""},"cat":"v8,devtools.timeline","dur":92,"name":"v8.compile","ph":"X","pid":56001,"tdur":92,"tid":775,"ts":47786049489,"tts":590120}, + {"args":{},"cat":"v8","dur":1,"name":"v8.compile","ph":"X","pid":56001,"tdur":2,"tid":775,"ts":47786049753,"tts":590384}, + {"args":{"data":{"columnNumber":1,"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A","lineNumber":1,"url":""}},"cat":"devtools.timeline","dur":150,"name":"EvaluateScript","ph":"X","pid":56001,"tdur":150,"tid":775,"ts":47786049762,"tts":590394}, + {"args":{"data":{"columnNumber":1,"lineNumber":1,"notStreamedReason":"inline script","streamed":false,"url":""},"fileName":""},"cat":"v8,devtools.timeline","dur":90,"name":"v8.compile","ph":"X","pid":56001,"tdur":89,"tid":775,"ts":47786049766,"tts":590398}, + {"args":{},"cat":"v8","dur":2,"name":"v8.compile","ph":"X","pid":56001,"tdur":2,"tid":775,"ts":47786049909,"tts":590540}, + {"args":{"data":{"columnNumber":1,"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A","lineNumber":1,"url":""}},"cat":"devtools.timeline","dur":120,"name":"EvaluateScript","ph":"X","pid":56001,"tdur":119,"tid":775,"ts":47786049918,"tts":590550}, + {"args":{"data":{"columnNumber":1,"lineNumber":1,"notStreamedReason":"inline script","streamed":false,"url":""},"fileName":""},"cat":"v8,devtools.timeline","dur":87,"name":"v8.compile","ph":"X","pid":56001,"tdur":86,"tid":775,"ts":47786049921,"tts":590553}, + {"args":{},"cat":"v8","dur":1,"name":"v8.compile","ph":"X","pid":56001,"tdur":0,"tid":775,"ts":47786050035,"tts":590667}, + {"args":{"data":{"columnNumber":1,"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A","lineNumber":1,"url":""}},"cat":"devtools.timeline","dur":269,"name":"EvaluateScript","ph":"X","pid":56001,"tdur":269,"tid":775,"ts":47786050043,"tts":590675}, + {"args":{"data":{"columnNumber":1,"lineNumber":1,"notStreamedReason":"inline script","streamed":false,"url":""},"fileName":""},"cat":"v8,devtools.timeline","dur":70,"name":"v8.compile","ph":"X","pid":56001,"tdur":70,"tid":775,"ts":47786050046,"tts":590678}, + {"args":{},"cat":"v8","dur":1,"name":"v8.compile","ph":"X","pid":56001,"tdur":2,"tid":775,"ts":47786050309,"tts":590940}, + {"args":{"data":{"encodedDataLength":330,"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A","requestId":"DA13668C4781FCB2BF6F3AB0F3313AB7"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56001,"s":"t","tid":775,"ts":47786055211,"tts":591566}, + {"args":{"data":{"decodedBodyLength":330,"didFail":false,"encodedDataLength":515,"finishTime":47786.044624,"requestId":"DA13668C4781FCB2BF6F3AB0F3313AB7"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56001,"s":"t","tid":775,"ts":47786056173,"tts":592528}, + {"args":{},"cat":"disabled-by-default-devtools.timeline","dur":2992,"name":"RunTask","ph":"X","pid":56001,"tdur":2597,"tid":775,"ts":47786056342,"tts":592696}, + {"args":{"beginData":{"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A","startLine":0,"url":"http://localhost:8686/yt-embed.html"},"endData":{"endLine":9}},"cat":"devtools.timeline","dur":2957,"name":"ParseHTML","ph":"X","pid":56001,"tdur":2562,"tid":775,"ts":47786056351,"tts":592705}, + {"args":{"beginData":{"frame":"D215705AC29C284D9BB2459B7020E798","startLine":0,"url":"about:blank"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":57,"name":"ParseHTML","ph":"X","pid":56001,"tdur":57,"tid":775,"ts":47786057615,"tts":593747}, + {"args":{"data":{"type":"readystatechange"}},"cat":"devtools.timeline","dur":5,"name":"EventDispatch","ph":"X","pid":56001,"tdur":5,"tid":775,"ts":47786057725,"tts":593857}, + {"args":{"data":{"type":"DOMContentLoaded"}},"cat":"devtools.timeline","dur":3,"name":"EventDispatch","ph":"X","pid":56001,"tdur":3,"tid":775,"ts":47786057737,"tts":593869}, + {"args":{"data":{"type":"readystatechange"}},"cat":"devtools.timeline","dur":8,"name":"EventDispatch","ph":"X","pid":56001,"tdur":8,"tid":775,"ts":47786057920,"tts":594036}, + {"args":{"data":{"type":"beforeunload"}},"cat":"devtools.timeline","dur":5,"name":"EventDispatch","ph":"X","pid":56001,"tdur":5,"tid":775,"ts":47786058000,"tts":594116}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","startLine":0,"url":"about:blank"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":43,"name":"ParseHTML","ph":"X","pid":56001,"tdur":43,"tid":775,"ts":47786058893,"tts":594853}, + {"args":{"data":{"type":"readystatechange"}},"cat":"devtools.timeline","dur":4,"name":"EventDispatch","ph":"X","pid":56001,"tdur":4,"tid":775,"ts":47786058974,"tts":594934}, + {"args":{"data":{"type":"DOMContentLoaded"}},"cat":"devtools.timeline","dur":3,"name":"EventDispatch","ph":"X","pid":56001,"tdur":3,"tid":775,"ts":47786058984,"tts":594943}, + {"args":{"data":{"type":"readystatechange"}},"cat":"devtools.timeline","dur":5,"name":"EventDispatch","ph":"X","pid":56001,"tdur":5,"tid":775,"ts":47786059110,"tts":595070}, + {"args":{"data":{"type":"beforeunload"}},"cat":"devtools.timeline","dur":4,"name":"EventDispatch","ph":"X","pid":56001,"tdur":4,"tid":775,"ts":47786059157,"tts":595116}, + {"args":{"beginData":{"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A","startLine":10,"url":"http://localhost:8686/yt-embed.html"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":703,"name":"ParseHTML","ph":"X","pid":56001,"tdur":704,"tid":775,"ts":47786059578,"tts":595537}, + {"args":{"data":{"type":"readystatechange"}},"cat":"devtools.timeline","dur":4,"name":"EventDispatch","ph":"X","pid":56001,"tdur":5,"tid":775,"ts":47786059602,"tts":595561}, + {"args":{"data":{"type":"DOMContentLoaded"}},"cat":"devtools.timeline","dur":4,"name":"EventDispatch","ph":"X","pid":56001,"tdur":4,"tid":775,"ts":47786059631,"tts":595591}, + {"args":{},"cat":"disabled-by-default-devtools.timeline","dur":86926,"name":"RunTask","ph":"X","pid":56001,"tdur":43699,"tid":775,"ts":47786063859,"tts":596474}, + {"args":{"beginData":{"dirtyObjects":10,"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A","partialLayout":false,"totalObjects":10},"endData":{"root":[0,0,980,0,980,1743,0,1743],"rootNode":4}},"cat":"devtools.timeline","dur":85713,"name":"Layout","ph":"X","pid":56001,"tdur":42562,"tid":775,"ts":47786064030,"tts":596644}, + {"args":{"data":{"frame":"D215705AC29C284D9BB2459B7020E798"}},"cat":"disabled-by-default-devtools.timeline","name":"InvalidateLayout","ph":"I","pid":56001,"s":"t","tid":775,"ts":47786149698,"tts":639163}, + {"args":{"data":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9"}},"cat":"disabled-by-default-devtools.timeline","name":"InvalidateLayout","ph":"I","pid":56001,"s":"t","tid":775,"ts":47786149730,"tts":639192}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","startLine":0,"url":"about:blank"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":220,"name":"ParseHTML","ph":"X","pid":56010,"tdur":221,"tid":775,"ts":47786299712,"tts":62722}, + {"args":{"data":{"type":"readystatechange"}},"cat":"devtools.timeline","dur":12,"name":"EventDispatch","ph":"X","pid":56010,"tdur":11,"tid":775,"ts":47786300023,"tts":63034}, + {"args":{"data":{"type":"DOMContentLoaded"}},"cat":"devtools.timeline","dur":4,"name":"EventDispatch","ph":"X","pid":56010,"tdur":4,"tid":775,"ts":47786300060,"tts":63070}, + {"args":{"data":{"type":"readystatechange"}},"cat":"devtools.timeline","dur":5,"name":"EventDispatch","ph":"X","pid":56010,"tdur":6,"tid":775,"ts":47786300198,"tts":63208}, + {"args":{"data":{"type":"pagehide"}},"cat":"devtools.timeline","dur":6,"name":"EventDispatch","ph":"X","pid":56010,"tdur":6,"tid":775,"ts":47786305159,"tts":66347}, + {"args":{"data":{"type":"visibilitychange"}},"cat":"devtools.timeline","dur":5,"name":"EventDispatch","ph":"X","pid":56010,"tdur":4,"tid":775,"ts":47786305207,"tts":66396}, + {"args":{"data":{"type":"webkitvisibilitychange"}},"cat":"devtools.timeline","dur":2,"name":"EventDispatch","ph":"X","pid":56010,"tdur":3,"tid":775,"ts":47786305222,"tts":66409}, + {"args":{"data":{"type":"unload"}},"cat":"devtools.timeline","dur":3,"name":"EventDispatch","ph":"X","pid":56010,"tdur":3,"tid":775,"ts":47786305227,"tts":66415}, + {"args":{"data":{"encodedDataLength":2928,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","fromCache":false,"fromServiceWorker":false,"mimeType":"text/html","requestId":"51B3229F5358F49D44871ADE7185528C","responseTime":1600197632040.066,"statusCode":200,"timing":{"connectEnd":149.581,"connectStart":54.756,"dnsEnd":54.756,"dnsStart":0.189,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":217.141,"requestTime":47786.074447,"sendEnd":149.694,"sendStart":149.64,"sslEnd":149.576,"sslStart":82.328,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786305768,"tts":66916}, + {"args":{"data":{"type":"pagehide"}},"cat":"devtools.timeline","dur":7,"name":"EventDispatch","ph":"X","pid":56007,"tdur":8,"tid":775,"ts":47786309510,"tts":106108}, + {"args":{"data":{"type":"visibilitychange"}},"cat":"devtools.timeline","dur":4,"name":"EventDispatch","ph":"X","pid":56007,"tdur":4,"tid":775,"ts":47786309550,"tts":106149}, + {"args":{"data":{"type":"webkitvisibilitychange"}},"cat":"devtools.timeline","dur":3,"name":"EventDispatch","ph":"X","pid":56007,"tdur":3,"tid":775,"ts":47786309562,"tts":106161}, + {"args":{"data":{"type":"unload"}},"cat":"devtools.timeline","dur":2,"name":"EventDispatch","ph":"X","pid":56007,"tdur":1,"tid":775,"ts":47786309568,"tts":106167}, + {"args":{"data":{"encodedDataLength":760,"frame":"D215705AC29C284D9BB2459B7020E798","fromCache":false,"fromServiceWorker":false,"mimeType":"text/html","requestId":"7409A683C44F8397F7103BD7E03CB6C9","responseTime":1600197632052.458,"statusCode":200,"timing":{"connectEnd":127.561,"connectStart":36.584,"dnsEnd":36.584,"dnsStart":0.163,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":237.647,"requestTime":47786.066226,"sendEnd":127.8,"sendStart":127.682,"sslEnd":127.557,"sslStart":90.384,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786309918,"tts":106514}, + {"args":{"data":{"type":"pagehide"}},"cat":"devtools.timeline","dur":6,"name":"EventDispatch","ph":"X","pid":56001,"tdur":6,"tid":775,"ts":47786310167,"tts":641911}, + {"args":{"data":{"type":"visibilitychange"}},"cat":"devtools.timeline","dur":4,"name":"EventDispatch","ph":"X","pid":56001,"tdur":4,"tid":775,"ts":47786310180,"tts":641924}, + {"args":{"data":{"type":"webkitvisibilitychange"}},"cat":"devtools.timeline","dur":2,"name":"EventDispatch","ph":"X","pid":56001,"tdur":2,"tid":775,"ts":47786310187,"tts":641931}, + {"args":{"data":{"type":"unload"}},"cat":"devtools.timeline","dur":3,"name":"EventDispatch","ph":"X","pid":56001,"tdur":2,"tid":775,"ts":47786310191,"tts":641936}, + {"args":{"data":{"type":"pagehide"}},"cat":"devtools.timeline","dur":6,"name":"EventDispatch","ph":"X","pid":56001,"tdur":7,"tid":775,"ts":47786314014,"tts":643279}, + {"args":{"data":{"type":"visibilitychange"}},"cat":"devtools.timeline","dur":3,"name":"EventDispatch","ph":"X","pid":56001,"tdur":4,"tid":775,"ts":47786314028,"tts":643293}, + {"args":{"data":{"type":"webkitvisibilitychange"}},"cat":"devtools.timeline","dur":2,"name":"EventDispatch","ph":"X","pid":56001,"tdur":2,"tid":775,"ts":47786314039,"tts":643304}, + {"args":{"data":{"type":"unload"}},"cat":"devtools.timeline","dur":2,"name":"EventDispatch","ph":"X","pid":56001,"tdur":3,"tid":775,"ts":47786314045,"tts":643309}, + {"args":{"data":{"encodedDataLength":16850,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"51B3229F5358F49D44871ADE7185528C"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786316342,"tts":75939}, + {"args":{"data":{"decodedBodyLength":16850,"didFail":false,"encodedDataLength":8300,"finishTime":47786.292956,"requestId":"51B3229F5358F49D44871ADE7185528C"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786319084,"tts":78385}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":0}},"cat":"devtools.timeline","dur":5056,"name":"ParseHTML","ph":"X","pid":56010,"tdur":5018,"tid":775,"ts":47786319252,"tts":78553}, + {"args":{"data":{"encodedDataLength":29781,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"7409A683C44F8397F7103BD7E03CB6C9"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786320928,"tts":115941}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":14821,"functionName":"","lineNumber":1,"scriptId":"7","url":"https://player.vimeo.com/video/336812660"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":122,"name":"ParseHTML","ph":"X","pid":56010,"tdur":122,"tid":775,"ts":47786322238,"tts":81526}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":14821,"functionName":"","lineNumber":1,"scriptId":"7","url":"https://player.vimeo.com/video/336812660"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":5,"name":"ParseHTML","ph":"X","pid":56010,"tdur":5,"tid":775,"ts":47786322386,"tts":81674}, + {"args":{"data":{"decodedBodyLength":29781,"didFail":false,"encodedDataLength":10703,"finishTime":47786.30509,"requestId":"7409A683C44F8397F7103BD7E03CB6C9"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786323163,"tts":118096}, + {"args":{"beginData":{"frame":"D215705AC29C284D9BB2459B7020E798","startLine":0,"url":"https://www.youtube.com/embed/tgbNymZ7vqY"},"endData":{"endLine":1}},"cat":"devtools.timeline","dur":2182,"name":"ParseHTML","ph":"X","pid":56007,"tdur":2146,"tid":775,"ts":47786323374,"tts":118307}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","startLine":1,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":244,"name":"ParseHTML","ph":"X","pid":56010,"tdur":221,"tid":775,"ts":47786326855,"tts":85855}, + {"args":{"data":{"type":"readystatechange"}},"cat":"devtools.timeline","dur":5,"name":"EventDispatch","ph":"X","pid":56010,"tdur":4,"tid":775,"ts":47786326880,"tts":85881}, + {"args":{"data":{"type":"DOMContentLoaded"}},"cat":"devtools.timeline","dur":4,"name":"EventDispatch","ph":"X","pid":56010,"tdur":3,"tid":775,"ts":47786326907,"tts":85907}, + {"args":{"data":{"encodedDataLength":167,"frame":"D215705AC29C284D9BB2459B7020E798","fromCache":false,"fromServiceWorker":false,"mimeType":"text/javascript","requestId":"56007.4","responseTime":1600197632096.377,"statusCode":200,"timing":{"connectEnd":-1,"connectStart":-1,"dnsEnd":-1,"dnsStart":-1,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":21.507,"requestTime":47786.326268,"sendEnd":1.593,"sendStart":1.2,"sslEnd":-1,"sslStart":-1,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786348470,"tts":122023}, + {"args":{"data":{"encodedDataLength":8415,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786350072,"tts":122290}, + {"args":{"data":{"encodedDataLength":9954,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786351528,"tts":122414}, + {"args":{"data":{"encodedDataLength":8206,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786352666,"tts":122526}, + {"args":{"data":{"encodedDataLength":65536,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786362271,"tts":122647}, + {"args":{"data":{"encodedDataLength":10513,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786365565,"tts":123031}, + {"args":{"data":{"encodedDataLength":62570,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786374732,"tts":123157}, + {"args":{"data":{"encodedDataLength":9686,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786381257,"tts":123335}, + {"args":{"data":{"encodedDataLength":31661,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786384737,"tts":123482}, + {"args":{"data":{"encodedDataLength":11259,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786385849,"tts":123571}, + {"args":{"data":{"encodedDataLength":65536,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786391419,"tts":123684}, + {"args":{"data":{"encodedDataLength":51807,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786393047,"tts":123953}, + {"args":{"data":{"encodedDataLength":65536,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786397924,"tts":124102}, + {"args":{"data":{"encodedDataLength":30600,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786399498,"tts":124219}, + {"args":{"data":{"encodedDataLength":68914,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786401894,"tts":124355}, + {"args":{"data":{"encodedDataLength":24095,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786405191,"tts":124508}, + {"args":{"data":{"encodedDataLength":17208,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786405666,"tts":124669}, + {"args":{"data":{"encodedDataLength":19424,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786405970,"tts":124798}, + {"args":{"data":{"encodedDataLength":18344,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786406883,"tts":124901}, + {"args":{"data":{"encodedDataLength":49991,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786410362,"tts":125022}, + {"args":{"data":{"encodedDataLength":65536,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786414018,"tts":125126}, + {"args":{"data":{"encodedDataLength":34053,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786415327,"tts":125253}, + {"args":{"data":{"encodedDataLength":155,"frame":"D215705AC29C284D9BB2459B7020E798","fromCache":false,"fromServiceWorker":false,"mimeType":"text/javascript","requestId":"56007.5","responseTime":1600197632163.337,"statusCode":200,"timing":{"connectEnd":-1,"connectStart":-1,"dnsEnd":-1,"dnsStart":-1,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":88.147,"requestTime":47786.326585,"sendEnd":1.277,"sendStart":0.945,"sslEnd":-1,"sslStart":-1,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786415582,"tts":125508}, + {"args":{"data":{"encodedDataLength":8543,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.5"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786415690,"tts":125615}, + {"args":{"data":{"decodedBodyLength":8543,"didFail":false,"encodedDataLength":3191,"finishTime":47786.415028,"requestId":"56007.5"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786415965,"tts":125891}, + {"args":{"data":{"encodedDataLength":65536,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786416974,"tts":125974}, + {"args":{"data":{"encodedDataLength":90694,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786418180,"tts":126184}, + {"args":{"data":{"encodedDataLength":289,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","fromCache":false,"fromServiceWorker":false,"mimeType":"image/jpeg","requestId":"56010.2","responseTime":1600197632165.812,"statusCode":200,"timing":{"connectEnd":70.426,"connectStart":27.853,"dnsEnd":27.853,"dnsStart":0.163,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":95.714,"requestTime":47786.32147,"sendEnd":70.787,"sendStart":70.706,"sslEnd":70.422,"sslStart":45.436,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786418805,"tts":87020}, + {"args":{"data":{"encodedDataLength":777,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.2"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786418942,"tts":87157}, + {"args":{"data":{"decodedBodyLength":777,"didFail":false,"encodedDataLength":1075,"finishTime":47786.417381,"requestId":"56010.2"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786419269,"tts":87483}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":489,"name":"EventDispatch","ph":"X","pid":56010,"tdur":475,"tid":775,"ts":47786419441,"tts":87645}, + {"args":{"data":{"encodedDataLength":152922,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786420779,"tts":126470}, + {"args":{"data":{"encodedDataLength":217,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","fromCache":false,"fromServiceWorker":false,"mimeType":"text/css","requestId":"56010.4","responseTime":1600197632170.908,"statusCode":200,"timing":{"connectEnd":70.258,"connectStart":24.443,"dnsEnd":24.443,"dnsStart":0,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":97.784,"requestTime":47786.324528,"sendEnd":71.11,"sendStart":70.923,"sslEnd":70.254,"sslStart":42.505,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786423058,"tts":89233}, + {"args":{"data":{"encodedDataLength":65536,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786425001,"tts":89567}, + {"args":{"data":{"encodedDataLength":1119,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786425173,"tts":89739}, + {"args":{"data":{"encodedDataLength":10580,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786425478,"tts":126784}, + {"args":{"data":{"encodedDataLength":201007,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786425964,"tts":126973}, + {"args":{"data":{"encodedDataLength":17434,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786430177,"tts":127275}, + {"args":{"data":{"encodedDataLength":65536,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786436134,"tts":127372}, + {"args":{"data":{"encodedDataLength":53,"frame":"D215705AC29C284D9BB2459B7020E798","fromCache":false,"fromServiceWorker":false,"mimeType":"text/javascript","requestId":"56007.3","responseTime":1600197632184.859,"statusCode":200,"timing":{"connectEnd":-1,"connectStart":-1,"dnsEnd":-1,"dnsStart":-1,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":110.272,"requestTime":47786.325979,"sendEnd":1.88,"sendStart":1.3,"sslEnd":-1,"sslStart":-1,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786436949,"tts":127757}, + {"args":{"data":{"encodedDataLength":65536,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.3"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786437718,"tts":128116}, + {"args":{"data":{"encodedDataLength":90250,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786437965,"tts":128291}, + {"args":{"data":{"encodedDataLength":46544,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.3"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786439950,"tts":128432}, + {"args":{"data":{"encodedDataLength":29124,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.3"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786441459,"tts":128571}, + {"args":{"data":{"encodedDataLength":88,"frame":"D215705AC29C284D9BB2459B7020E798","fromCache":false,"fromServiceWorker":false,"mimeType":"text/css","requestId":"56007.2","responseTime":1600197632189.804,"statusCode":200,"timing":{"connectEnd":-1,"connectStart":-1,"dnsEnd":-1,"dnsStart":-1,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":117.126,"requestTime":47786.324095,"sendEnd":3.469,"sendStart":2.597,"sslEnd":-1,"sslStart":-1,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786441969,"tts":128922}, + {"args":{"data":{"encodedDataLength":55417,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786442084,"tts":89851}, + {"args":{"data":{"decodedBodyLength":141204,"didFail":false,"encodedDataLength":50213,"finishTime":47786.440933,"requestId":"56007.3"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786442998,"tts":129283}, + {"args":{"data":{"encodedDataLength":65536,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.2"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786443063,"tts":129348}, + {"args":{"data":{"encodedDataLength":65536,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.2"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786443165,"tts":129450}, + {"args":{"data":{"encodedDataLength":40710,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.4"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786443413,"tts":90024}, + {"args":{"data":{"encodedDataLength":65536,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.2"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786443758,"tts":129683}, + {"args":{"data":{"encodedDataLength":20456,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.2"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786443872,"tts":129798}, + {"args":{"data":{"encodedDataLength":65536,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.2"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786444103,"tts":129893}, + {"args":{"data":{"encodedDataLength":37144,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.2"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786444209,"tts":129999}, + {"args":{"data":{"decodedBodyLength":162782,"didFail":false,"encodedDataLength":17633,"finishTime":47786.4434,"requestId":"56010.4"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786447424,"tts":93791}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":98,"name":"EventDispatch","ph":"X","pid":56010,"tdur":98,"tid":775,"ts":47786447526,"tts":93893}, + {"args":{"data":{"encodedDataLength":371,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","fromCache":false,"fromServiceWorker":false,"mimeType":"application/javascript","requestId":"56010.3","responseTime":1600197632170.613,"statusCode":200,"timing":{"connectEnd":-1,"connectStart":-1,"dnsEnd":-1,"dnsStart":-1,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":98.192,"requestTime":47786.323843,"sendEnd":71.796,"sendStart":71.657,"sslEnd":-1,"sslStart":-1,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786449300,"tts":95605}, + {"args":{"data":{"encodedDataLength":49186,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.3"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786449417,"tts":95723}, + {"args":{"data":{"decodedBodyLength":319744,"didFail":false,"encodedDataLength":46813,"finishTime":47786.444266,"requestId":"56007.2"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786449510,"tts":135146}, + {"args":{"data":{"decodedBodyLength":1422803,"didFail":false,"encodedDataLength":459603,"finishTime":47786.436996,"requestId":"56007.4"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786449670,"tts":135306}, + {"args":{"beginData":{"frame":"D215705AC29C284D9BB2459B7020E798","startLine":2,"url":"https://www.youtube.com/embed/tgbNymZ7vqY"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":38855,"name":"ParseHTML","ph":"X","pid":56007,"tdur":38816,"tid":775,"ts":47786450416,"tts":136052}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":9,"name":"EventDispatch","ph":"X","pid":56007,"tdur":9,"tid":775,"ts":47786454191,"tts":139827}, + {"args":{"data":{"encodedDataLength":131072,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.3"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786468288,"tts":96012}, + {"args":{"data":{"encodedDataLength":50408,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.3"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786471434,"tts":96151}, + {"args":{"data":{"encodedDataLength":46058,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.3"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786472724,"tts":96339}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":6,"name":"EventDispatch","ph":"X","pid":56007,"tdur":6,"tid":775,"ts":47786482199,"tts":167814}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":5,"name":"EventDispatch","ph":"X","pid":56007,"tdur":5,"tid":775,"ts":47786482652,"tts":168267}, + {"args":{"data":{"type":"readystatechange"}},"cat":"devtools.timeline","dur":5,"name":"EventDispatch","ph":"X","pid":56007,"tdur":5,"tid":775,"ts":47786487626,"tts":173229}, + {"args":{"data":{"type":"DOMContentLoaded"}},"cat":"devtools.timeline","dur":7,"name":"EventDispatch","ph":"X","pid":56007,"tdur":8,"tid":775,"ts":47786487672,"tts":173272}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":6,"name":"EventDispatch","ph":"X","pid":56007,"tdur":5,"tid":775,"ts":47786490117,"tts":175665}, + {"args":{"data":{"encodedDataLength":29303,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.3"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786490761,"tts":96492}, + {"args":{"data":{"encodedDataLength":139511,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.3"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786492376,"tts":96662}, + {"args":{"data":{"encodedDataLength":16840,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.3"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786494469,"tts":96878}, + {"args":{"data":{"encodedDataLength":61910,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.3"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786496529,"tts":96980}, + {"args":{"data":{"encodedDataLength":241,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","fromCache":false,"fromServiceWorker":false,"mimeType":"text/javascript","requestId":"56010.5","responseTime":1600197632219.138,"statusCode":200,"timing":{"connectEnd":-1,"connectStart":-1,"dnsEnd":-1,"dnsStart":-1,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":144.838,"requestTime":47786.325692,"sendEnd":69.949,"sendStart":69.843,"sslEnd":-1,"sslStart":-1,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786497068,"tts":97377}, + {"args":{"data":{"encodedDataLength":2641,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.5"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786497187,"tts":97495}, + {"args":{"data":{"decodedBodyLength":2641,"didFail":false,"encodedDataLength":1474,"finishTime":47786.496546,"requestId":"56010.5"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786497418,"tts":97726}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":4,"name":"EventDispatch","ph":"X","pid":56010,"tdur":5,"tid":775,"ts":47786499329,"tts":99288}, + {"args":{"data":{"encodedDataLength":93529,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.3"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786499425,"tts":99384}, + {"args":{"data":{"decodedBodyLength":617817,"didFail":false,"encodedDataLength":145772,"finishTime":47786.497091,"requestId":"56010.3"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786501325,"tts":99753}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":86439,"name":"EventDispatch","ph":"X","pid":56010,"tdur":81152,"tid":775,"ts":47786522501,"tts":120599}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":456434,"functionName":"wd","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":295,"name":"ParseHTML","ph":"X","pid":56010,"tdur":295,"tid":775,"ts":47786524746,"tts":122833}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":456434,"functionName":"wd","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":5,"name":"ParseHTML","ph":"X","pid":56010,"tdur":5,"tid":775,"ts":47786525068,"tts":123154}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":484830,"functionName":"St","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":627,"name":"ParseHTML","ph":"X","pid":56010,"tdur":627,"tid":775,"ts":47786531886,"tts":129969}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":484830,"functionName":"St","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":5,"name":"ParseHTML","ph":"X","pid":56010,"tdur":6,"tid":775,"ts":47786532556,"tts":130638}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":579872,"functionName":"I","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":265,"name":"ParseHTML","ph":"X","pid":56010,"tdur":264,"tid":775,"ts":47786536651,"tts":134670}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":579872,"functionName":"I","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":7,"name":"ParseHTML","ph":"X","pid":56010,"tdur":6,"tid":775,"ts":47786536973,"tts":134992}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":586111,"functionName":"w","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":29,"name":"ParseHTML","ph":"X","pid":56010,"tdur":29,"tid":775,"ts":47786537810,"tts":135824}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":586111,"functionName":"w","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":8,"name":"ParseHTML","ph":"X","pid":56010,"tdur":9,"tid":775,"ts":47786537861,"tts":135874}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":588860,"functionName":"","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":66,"name":"ParseHTML","ph":"X","pid":56010,"tdur":65,"tid":775,"ts":47786538356,"tts":136370}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":588860,"functionName":"","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":5,"name":"ParseHTML","ph":"X","pid":56010,"tdur":4,"tid":775,"ts":47786538442,"tts":136456}, + {"args":{"data":{"type":"volumechange"}},"cat":"devtools.timeline","dur":9,"name":"EventDispatch","ph":"X","pid":56007,"tdur":9,"tid":775,"ts":47786564974,"tts":233138}, + {"args":{"data":{"encodedDataLength":0,"frame":"D215705AC29C284D9BB2459B7020E798","fromCache":false,"fromServiceWorker":false,"mimeType":"image/png","requestId":"56007.17","statusCode":200}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786568015,"tts":236172}, + {"args":{"data":{"encodedDataLength":175,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.17"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786568027,"tts":236183}, + {"args":{"data":{"decodedBodyLength":0,"didFail":false,"encodedDataLength":0,"requestId":"56007.17"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786568032,"tts":236188}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":601194,"functionName":"n.Ed","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":59,"name":"ParseHTML","ph":"X","pid":56010,"tdur":58,"tid":775,"ts":47786605419,"tts":198373}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":601194,"functionName":"n.Ed","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":5,"name":"ParseHTML","ph":"X","pid":56010,"tdur":5,"tid":775,"ts":47786605504,"tts":198457}, + {"args":{"data":{"encodedDataLength":383,"frame":"D215705AC29C284D9BB2459B7020E798","fromCache":false,"fromServiceWorker":false,"mimeType":"text/javascript","requestId":"56007.16","responseTime":1600197632329.537,"statusCode":200,"timing":{"connectEnd":0,"connectStart":0,"dnsEnd":0,"dnsStart":0,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":19.711,"requestTime":47786.561199,"sendEnd":0.455,"sendStart":0.283,"sslEnd":0,"sslStart":0,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786609057,"tts":274454}, + {"args":{"data":{"encodedDataLength":35953,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.16"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786609202,"tts":274597}, + {"args":{"data":{"decodedBodyLength":35953,"didFail":false,"encodedDataLength":11477,"finishTime":47786.581515,"requestId":"56007.16"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786610337,"tts":275525}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":401,"name":"EventDispatch","ph":"X","pid":56007,"tdur":401,"tid":775,"ts":47786610798,"tts":275983}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":484830,"functionName":"St","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":570,"name":"ParseHTML","ph":"X","pid":56010,"tdur":570,"tid":775,"ts":47786613488,"tts":206212}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":484830,"functionName":"St","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":5,"name":"ParseHTML","ph":"X","pid":56010,"tdur":5,"tid":775,"ts":47786614084,"tts":206808}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":484830,"functionName":"St","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":497,"name":"ParseHTML","ph":"X","pid":56010,"tdur":497,"tid":775,"ts":47786614675,"tts":207399}, + {"args":{"beginData":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9","stackTrace":[{"columnNumber":484830,"functionName":"St","lineNumber":10,"scriptId":"8","url":"https://f.vimeocdn.com/p/3.22.3/js/player.js"}],"startLine":0,"url":"https://player.vimeo.com/video/336812660"},"endData":{"endLine":-1}},"cat":"devtools.timeline","dur":5,"name":"ParseHTML","ph":"X","pid":56010,"tdur":4,"tid":775,"ts":47786615197,"tts":207922}, + {"args":{"data":{"type":"volumechange"}},"cat":"devtools.timeline","dur":6,"name":"EventDispatch","ph":"X","pid":56010,"tdur":6,"tid":775,"ts":47786615715,"tts":208439}, + {"args":{"data":{"type":"volumechange"}},"cat":"devtools.timeline","dur":3,"name":"EventDispatch","ph":"X","pid":56010,"tdur":3,"tid":775,"ts":47786615730,"tts":208454}, + {"args":{"data":{"type":"ratechange"}},"cat":"devtools.timeline","dur":2,"name":"EventDispatch","ph":"X","pid":56010,"tdur":3,"tid":775,"ts":47786615742,"tts":208466}, + {"args":{"data":{"type":"ratechange"}},"cat":"devtools.timeline","dur":2,"name":"EventDispatch","ph":"X","pid":56010,"tdur":3,"tid":775,"ts":47786615753,"tts":208476}, + {"args":{"data":{"type":"volumechange"}},"cat":"devtools.timeline","dur":3,"name":"EventDispatch","ph":"X","pid":56010,"tdur":3,"tid":775,"ts":47786615771,"tts":208495}, + {"args":{"data":{"type":"ratechange"}},"cat":"devtools.timeline","dur":2,"name":"EventDispatch","ph":"X","pid":56010,"tdur":3,"tid":775,"ts":47786615783,"tts":208506}, + {"args":{"data":{"type":"ratechange"}},"cat":"devtools.timeline","dur":3,"name":"EventDispatch","ph":"X","pid":56010,"tdur":1,"tid":775,"ts":47786615793,"tts":208518}, + {"args":{"data":{"encodedDataLength":377,"frame":"D215705AC29C284D9BB2459B7020E798","fromCache":false,"fromServiceWorker":false,"mimeType":"text/javascript","requestId":"56007.15","responseTime":1600197632378.034,"statusCode":200,"timing":{"connectEnd":116.683,"connectStart":48.513,"dnsEnd":48.513,"dnsStart":0.117,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":142.036,"requestTime":47786.487395,"sendEnd":116.857,"sendStart":116.781,"sslEnd":116.68,"sslStart":74.387,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786630165,"tts":280242}, + {"args":{"data":{"encodedDataLength":29,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.15"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786630281,"tts":280357}, + {"args":{"data":{"decodedBodyLength":29,"didFail":false,"encodedDataLength":415,"finishTime":47786.629669,"requestId":"56007.15"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786630526,"tts":280603}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":160,"name":"EventDispatch","ph":"X","pid":56007,"tdur":160,"tid":775,"ts":47786630724,"tts":280800}, + {"args":{"data":{"encodedDataLength":176,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","fromCache":false,"fromServiceWorker":false,"mimeType":"image/webp","requestId":"56010.8","responseTime":1600197632382.678,"statusCode":200,"timing":{"connectEnd":-1,"connectStart":-1,"dnsEnd":-1,"dnsStart":-1,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":27.927,"requestTime":47786.606134,"sendEnd":0.28,"sendStart":0.179,"sslEnd":-1,"sslStart":-1,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786635749,"tts":210456}, + {"args":{"data":{"encodedDataLength":9128,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","requestId":"56010.8"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786635863,"tts":210568}, + {"args":{"data":{"decodedBodyLength":9128,"didFail":false,"encodedDataLength":9313,"finishTime":47786.63528,"requestId":"56010.8"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786636061,"tts":210767}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":884,"name":"EventDispatch","ph":"X","pid":56010,"tdur":884,"tid":775,"ts":47786636464,"tts":211170}, + {"args":{"data":{"type":"readystatechange"}},"cat":"devtools.timeline","dur":4,"name":"EventDispatch","ph":"X","pid":56010,"tdur":4,"tid":775,"ts":47786637368,"tts":212074}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":164,"name":"EventDispatch","ph":"X","pid":56010,"tdur":164,"tid":775,"ts":47786637392,"tts":212098}, + {"args":{"data":{"type":"pageshow"}},"cat":"devtools.timeline","dur":5,"name":"EventDispatch","ph":"X","pid":56010,"tdur":5,"tid":775,"ts":47786637591,"tts":212297}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":6,"name":"EventDispatch","ph":"X","pid":56001,"tdur":5,"tid":775,"ts":47786637772,"tts":646107}, + {"args":{"data":{"encodedDataLength":429,"frame":"D215705AC29C284D9BB2459B7020E798","fromCache":false,"fromServiceWorker":false,"mimeType":"image/jpeg","requestId":"56007.18","responseTime":1600197632428.292,"statusCode":200,"timing":{"connectEnd":89.697,"connectStart":37.824,"dnsEnd":37.824,"dnsStart":0.18,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":110.806,"requestTime":47786.568895,"sendEnd":89.932,"sendStart":89.842,"sslEnd":89.691,"sslStart":55.068,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786682135,"tts":284907}, + {"args":{"data":{"encodedDataLength":2639,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.18"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786682245,"tts":285018}, + {"args":{"data":{"decodedBodyLength":2639,"didFail":false,"encodedDataLength":3077,"finishTime":47786.681621,"requestId":"56007.18"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786682473,"tts":285245}, + {"args":{"data":{"encodedDataLength":355,"frame":"D215705AC29C284D9BB2459B7020E798","fromCache":false,"fromServiceWorker":false,"mimeType":"image/jpeg","requestId":"56007.19","responseTime":1600197632441.314,"statusCode":200,"timing":{"connectEnd":91.177,"connectStart":35.828,"dnsEnd":35.828,"dnsStart":0.182,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":122.919,"requestTime":47786.569798,"sendEnd":91.352,"sendStart":91.272,"sslEnd":91.173,"sslStart":52.472,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786695299,"tts":285676}, + {"args":{"data":{"encodedDataLength":5575,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.19"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786695417,"tts":285794}, + {"args":{"data":{"encodedDataLength":6980,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.19"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786696707,"tts":285989}, + {"args":{"data":{"encodedDataLength":8367,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.19"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786699243,"tts":286149}, + {"args":{"data":{"encodedDataLength":6980,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.19"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786701501,"tts":286311}, + {"args":{"data":{"encodedDataLength":1396,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.19"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786703157,"tts":286597}, + {"args":{"data":{"encodedDataLength":110,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","fromCache":false,"fromServiceWorker":false,"mimeType":"text/plain","requestId":"56010.9","responseTime":1600197632452.174,"statusCode":200,"timing":{"connectEnd":44.498,"connectStart":0.118,"dnsEnd":0.118,"dnsStart":0.113,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":94.751,"requestTime":47786.608785,"sendEnd":44.701,"sendStart":44.601,"sslEnd":44.493,"sslStart":15.325,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786704132,"tts":215192}, + {"args":{"data":{"decodedBodyLength":0,"didFail":false,"encodedDataLength":110,"finishTime":47786.703717,"requestId":"56010.9"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56010,"s":"t","tid":775,"ts":47786704355,"tts":215415}, + {"args":{"data":{"encodedDataLength":16025,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.19"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786726549,"tts":287728}, + {"args":{"data":{"encodedDataLength":2792,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.19"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786727894,"tts":288013}, + {"args":{"data":{"encodedDataLength":397,"frame":"D215705AC29C284D9BB2459B7020E798","fromCache":false,"fromServiceWorker":false,"mimeType":"font/ttf","requestId":"56007.6","responseTime":1600197632478.239,"statusCode":200,"timing":{"connectEnd":95.703,"connectStart":35.412,"dnsEnd":35.412,"dnsStart":0.131,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":119.779,"requestTime":47786.609857,"sendEnd":95.882,"sendStart":95.8,"sslEnd":95.699,"sslStart":63.471,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786730141,"tts":288290}, + {"args":{"data":{"encodedDataLength":11159,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.19"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786731437,"tts":288517}, + {"args":{"data":{"encodedDataLength":6599,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.19"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786733814,"tts":289587}, + {"args":{"data":{"decodedBodyLength":65873,"didFail":false,"encodedDataLength":66273,"finishTime":47786.733333,"requestId":"56007.19"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786734100,"tts":289873}, + {"args":{"data":{"encodedDataLength":17329,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.6"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786734897,"tts":290001}, + {"args":{"data":{"encodedDataLength":3535,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.6"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786743982,"tts":290227}, + {"args":{"data":{"decodedBodyLength":20864,"didFail":false,"encodedDataLength":14759,"finishTime":47786.743963,"requestId":"56007.6"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786759480,"tts":294386}, + {"args":{"data":{"type":"readystatechange"}},"cat":"devtools.timeline","dur":5,"name":"EventDispatch","ph":"X","pid":56007,"tdur":4,"tid":775,"ts":47786759519,"tts":294426}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":13256,"name":"EventDispatch","ph":"X","pid":56007,"tdur":1213,"tid":775,"ts":47786759548,"tts":294455}, + {"args":{"data":{"type":"pageshow"}},"cat":"devtools.timeline","dur":3,"name":"EventDispatch","ph":"X","pid":56007,"tdur":3,"tid":775,"ts":47786772842,"tts":295706}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":7,"name":"EventDispatch","ph":"X","pid":56001,"tdur":7,"tid":775,"ts":47786773096,"tts":646596}, + {"args":{"data":{"type":"readystatechange"}},"cat":"devtools.timeline","dur":7,"name":"EventDispatch","ph":"X","pid":56001,"tdur":7,"tid":775,"ts":47786774364,"tts":646705}, + {"args":{"data":{"type":"load"}},"cat":"devtools.timeline","dur":3,"name":"EventDispatch","ph":"X","pid":56001,"tdur":3,"tid":775,"ts":47786774385,"tts":646726}, + {"args":{"data":{"type":"pageshow"}},"cat":"devtools.timeline","dur":5,"name":"EventDispatch","ph":"X","pid":56001,"tdur":5,"tid":775,"ts":47786774469,"tts":646810}, + {"args":{"data":{"encodedDataLength":184,"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A","fromCache":false,"fromServiceWorker":false,"mimeType":"text/html","requestId":"56001.2","responseTime":1600197632526.586,"statusCode":404,"timing":{"connectEnd":-1,"connectStart":-1,"dnsEnd":-1,"dnsStart":-1,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":0.927,"requestTime":47786.77703,"sendEnd":0.221,"sendStart":0.176,"sslEnd":-1,"sslStart":-1,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56001,"s":"t","tid":775,"ts":47786778369,"tts":648032}, + {"args":{"data":{"encodedDataLength":469,"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A","requestId":"56001.2"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56001,"s":"t","tid":775,"ts":47786778617,"tts":648277}, + {"args":{"data":{"decodedBodyLength":469,"didFail":false,"encodedDataLength":653,"finishTime":47786.778266,"requestId":"56001.2"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56001,"s":"t","tid":775,"ts":47786778868,"tts":648528}, + {"args":{"data":{"type":"transitionend"}},"cat":"devtools.timeline","dur":6,"name":"EventDispatch","ph":"X","pid":56010,"tdur":6,"tid":775,"ts":47786779938,"tts":218018}, + {"args":{"data":{"type":"transitionend"}},"cat":"devtools.timeline","dur":3,"name":"EventDispatch","ph":"X","pid":56010,"tdur":4,"tid":775,"ts":47786779948,"tts":218028}, + {"args":{"data":{"encodedDataLength":1121,"frame":"D215705AC29C284D9BB2459B7020E798","fromCache":false,"fromServiceWorker":false,"mimeType":"application/json","requestId":"56007.14","responseTime":1600197632537.57,"statusCode":200,"timing":{"connectEnd":67.778,"connectStart":0.328,"dnsEnd":0.12,"dnsStart":0.112,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":114.785,"requestTime":47786.674157,"sendEnd":37.086,"sendStart":36.97,"sslEnd":67.778,"sslStart":0.328,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786789796,"tts":300092}, + {"args":{"data":{"encodedDataLength":113,"frame":"D215705AC29C284D9BB2459B7020E798","requestId":"56007.14"}},"cat":"devtools.timeline","name":"ResourceReceivedData","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786789960,"tts":300257}, + {"args":{"data":{"decodedBodyLength":113,"didFail":false,"encodedDataLength":1254,"finishTime":47786.789606,"requestId":"56007.14"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56007,"s":"t","tid":775,"ts":47786791212,"tts":301508}, + {"args":{"data":{"type":"transitionend"}},"cat":"devtools.timeline","dur":858,"name":"EventDispatch","ph":"X","pid":56010,"tdur":841,"tid":775,"ts":47786872592,"tts":222271}, + {"args":{"data":{"type":"transitionend"}},"cat":"devtools.timeline","dur":5,"name":"EventDispatch","ph":"X","pid":56010,"tdur":5,"tid":775,"ts":47786873465,"tts":223127}, + {"args":{"data":{"encodedDataLength":818,"frame":"A0D1CEFE4B294AB844A8912CA96784F9","fromCache":false,"fromServiceWorker":false,"mimeType":"text/plain","requestId":"56010.7","responseTime":1600197633390.104,"statusCode":204,"timing":{"connectEnd":77.571,"connectStart":25.829,"dnsEnd":25.829,"dnsStart":0.097,"proxyEnd":-1,"proxyStart":-1,"pushEnd":0,"pushStart":0,"receiveHeadersEnd":1142.011,"requestTime":47786.499527,"sendEnd":77.682,"sendStart":77.624,"sslEnd":77.567,"sslStart":44.659,"workerReady":-1,"workerStart":-1}}},"cat":"devtools.timeline","name":"ResourceReceiveResponse","ph":"I","pid":56010,"s":"t","tid":775,"ts":47787642896,"tts":227636}, + {"args":{"data":{"decodedBodyLength":0,"didFail":false,"encodedDataLength":818,"finishTime":47787.64191,"requestId":"56010.7"}},"cat":"devtools.timeline","name":"ResourceFinish","ph":"I","pid":56010,"s":"t","tid":775,"ts":47787643328,"tts":228068}, + {"args":{},"cat":"disabled-by-default-devtools.timeline","dur":1342,"name":"RunTask","ph":"X","pid":56001,"tdur":1342,"tid":775,"ts":47787781586,"tts":650151}, + {"args":{},"cat":"disabled-by-default-devtools.timeline","dur":1200,"name":"EvaluateScript","ph":"X","pid":56001,"tdur":1201,"tid":775,"ts":47787781647,"tts":650211}, + {"args":{"data":{"columnNumber":1,"lineNumber":1,"notStreamedReason":"inline script","streamed":false,"url":""},"fileName":""},"cat":"v8,devtools.timeline","dur":163,"name":"v8.compile","ph":"X","pid":56001,"tdur":162,"tid":775,"ts":47787781794,"tts":650360}, + {"args":{"data":{"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A","singleShot":true,"stackTrace":[{"columnNumber":5,"functionName":"","lineNumber":12,"scriptId":"15","url":""}],"timeout":50,"timerId":1}},"cat":"devtools.timeline","name":"TimerInstall","ph":"I","pid":56001,"s":"t","tid":775,"ts":47787782704,"tts":651269}, + {"args":{"snapshot":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAHyARgDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAII/8QAGRABAAIDAAAAAAAAAAAAAAAAAAECAzNx/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwDVICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcmu3JDJrtyQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJrtyQya7ckBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJya7ckMmu3JAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcmu3JDJrtyQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJrtyQya7ckBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJya7ckMmu3JAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcmu3JDJrtyQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJrtyQya7ckBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJya7ckMmu3JAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcmu3JDJrtyQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJrtyQya7ckBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJya7ckMmu3JAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcmu3JDJrtyQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJrtyQya7ckBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJya7ckMmu3JAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcmu3JDJrtyQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJrtyQya7ckBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJya7ckMmu3JAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcmu3JDJrtyQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJrtyQya7ckBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJya7ckMmu3JAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcmu3JDJrtyQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJrtyQya7ckBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJya7ckMmu3JAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcmu3JDJrtyQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJrtyQya7ckBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJya7ckMmu3JAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcmu3JDJrtyQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJrtyQya7ckBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJya7ckMmu3JAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcmu3JDJrtyQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJrtyQAf/2Q=="},"cat":"disabled-by-default-devtools.screenshot","id":"0x1","name":"Screenshot","ph":"O","pid":55969,"tid":775,"ts":47786037920}, + {"args":{"data":{"documentLoaderURL":"http://localhost:8686/yt-embed.html","isLoadingMainFrame":true,"navigationId":"DA13668C4781FCB2BF6F3AB0F3313AB7"},"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A"},"cat":"blink.user_timing","name":"navigationStart","ph":"R","pid":56001,"tid":775,"ts":47786040954}, + {"args":{"data":{"documentLoaderURL":"","isLoadingMainFrame":false,"navigationId":"4128E72F76ADE3A94BAEE1D2D1778B34"},"frame":"D215705AC29C284D9BB2459B7020E798"},"cat":"blink.user_timing","name":"navigationStart","ph":"R","pid":56001,"tid":775,"ts":47786057234}, + {"args":{"frame":"D215705AC29C284D9BB2459B7020E798"},"cat":"blink.user_timing,rail","name":"domContentLoadedEventEnd","ph":"R","pid":56001,"tid":775,"ts":47786057742}, + {"args":{"data":{"documentLoaderURL":"https://www.youtube.com/embed/tgbNymZ7vqY","isLoadingMainFrame":false,"navigationId":"7409A683C44F8397F7103BD7E03CB6C9"},"frame":"D215705AC29C284D9BB2459B7020E798"},"cat":"blink.user_timing","name":"navigationStart","ph":"R","pid":56007,"tid":775,"ts":47786058113}, + {"args":{"data":{"documentLoaderURL":"","isLoadingMainFrame":false,"navigationId":"FB4672AF3C2DC8E3D150CB86D14D72B5"},"frame":"A0D1CEFE4B294AB844A8912CA96784F9"},"cat":"blink.user_timing","name":"navigationStart","ph":"R","pid":56001,"tid":775,"ts":47786058670}, + {"args":{"frame":"A0D1CEFE4B294AB844A8912CA96784F9"},"cat":"blink.user_timing,rail","name":"domContentLoadedEventEnd","ph":"R","pid":56001,"tid":775,"ts":47786058989}, + {"args":{"data":{"documentLoaderURL":"http://player.vimeo.com/video/336812660","isLoadingMainFrame":false,"navigationId":"51B3229F5358F49D44871ADE7185528C"},"frame":"A0D1CEFE4B294AB844A8912CA96784F9"},"cat":"blink.user_timing","name":"navigationStart","ph":"R","pid":56010,"tid":775,"ts":47786059251}, + {"args":{"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A"},"cat":"blink.user_timing,rail","name":"domContentLoadedEventEnd","ph":"R","pid":56001,"tid":775,"ts":47786059637}, + {"args":{"data":{"navigationId":"DA13668C4781FCB2BF6F3AB0F3313AB7"},"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A"},"cat":"loading,rail,devtools.timeline","name":"firstPaint","ph":"R","pid":56001,"tid":775,"ts":47786179669}, + {"args":{"data":{"navigationId":"DA13668C4781FCB2BF6F3AB0F3313AB7"},"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A"},"cat":"loading,rail,devtools.timeline","name":"firstContentfulPaint","ph":"R","pid":56001,"tid":775,"ts":47786179669}, + {"args":{"data":{"navigationId":"DA13668C4781FCB2BF6F3AB0F3313AB7"},"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A"},"cat":"loading,rail,devtools.timeline","name":"firstMeaningfulPaintCandidate","ph":"R","pid":56001,"tid":775,"ts":47786179669}, + {"args":{"data":{"candidateIndex":1,"isMainFrame":true,"navigationId":"DA13668C4781FCB2BF6F3AB0F3313AB7","nodeId":5,"size":332,"type":"text"},"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A"},"cat":"loading,rail,devtools.timeline","name":"largestContentfulPaint::Candidate","ph":"R","pid":56001,"tid":775,"ts":47786179669}, + {"args":{"data":{"navigationId":"DA13668C4781FCB2BF6F3AB0F3313AB7"},"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A"},"cat":"loading,rail,devtools.timeline","name":"firstMeaningfulPaint","ph":"R","pid":56001,"tid":775,"ts":47786179669}, + {"args":{"afterUserInput":0,"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A"},"cat":"loading,rail,devtools.timeline","name":"firstMeaningfulPaint","ph":"R","pid":56001,"tid":775,"ts":47786179669}, + {"args":{"data":{"documentLoaderURL":"","isLoadingMainFrame":false,"navigationId":"179B3002EE9A908E8BD12254B86ACBFC"},"frame":"A0D1CEFE4B294AB844A8912CA96784F9"},"cat":"blink.user_timing","name":"navigationStart","ph":"R","pid":56010,"tid":775,"ts":47786298402}, + {"args":{"snapshot":"/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAHyARgDASIAAhEBAxEB/8QAHQABAAMAAwEBAQAAAAAAAAAAAAIFBwEGCAQDCf/EAD0QAQABAgEGCwcCBgIDAAAAAAABAgMEBQYRM3GSCBIUGCE1N1NydbExUVWUs9LTFiIHMkFSYZETFSNDYv/EABoBAQADAQEBAAAAAAAAAAAAAAABAgMEBgX/xAAoEQEAAQEGBwEAAwEAAAAAAAAAAQIDERITUVIEFBUxMjNxISIjQWH/2gAMAwEAAhEDEQA/ALLhBfxozqzCz+/6fIfIZwc4W3e/89jj1RVVp09OmOjoZpznc/vdkn5WfuOGJ2ux5fZ9amGoG5c53P73ZJ+Vn7jnO5/e7JPys/cw0SNy5zuf3uyT8rP3HOdz+92SflZ+5hoDcuc7n97sk/Kz9xznc/vdkn5WfuYaA3LnO5/e7JPys/cc53P73ZJ+Vn7mGgNy5zuf3uyT8rP3HOdz+92SflZ+5hoDcuc7n97sk/Kz9xznc/vdkn5WfuYaA3LnO5/e7JPys/c9IcHXPjK+f+Y+Jytl7k/KreOrw9P/AAW+JTxYoomOjTPTpql/P17a4GHZTjvNbv07SBvQAAAAAAAAAAAAAAAAAI3NXVskLmrq2SA8P8MTtdjy+z61MNblwxO12PL7PrUw1IAAAAAAAAAAAAPbXAw7Kcd5rd+naeJXtrgYdlOO81u/TtA3oBAAAAAAAAAAAAAAAAAjc1dWyQuaurZIDw/wxO12PL7PrUw1uXDE7XY8vs+tTDUgAAAAAAAAAAAA9tcDDspx3mt36dp4le2uBh2U47zW79O0DegEAAAAAAAAAAAAAAAACNzV1bJC5q6tkgPD/DE7XY8vs+tTDW5cMTtdjy+z61MNSAAAAAAAAAAAAD21wMOynHea3fp2niV7a4GHZTjvNbv07QN6AQAAAAAAAAAAAAAAAAI3NXVskLmrq2SA8P8ADE7XY8vs+tTDW5cMTtdjy+z61MNSAAAAAAAAAAAAD21wMOynHea3fp2niV7a4GHZTjvNbv07QN6AQAAAAAAAAAAAAAAAAI3NXVskLmrq2SA8P8MTtdjy+z61MNeteEN/CjK2ev8AEKrKeT8fk7D2acLbs8TEVXIq0xpnT+2mY0dPvZlzes4vjGRd69+NeKatGU29nE3TVDFxtHN6zi+MZF3r34zm9ZxfGMi7178Zgq0RzFluhi42jm9ZxfGMi7178Zzes4vjGRd69+MwVaHMWW6GLjaOb1nF8YyLvXvxnN6zi+MZF3r34zBVocxZboYuNo5vWcXxjIu9e/Gc3rOL4xkXevfjMFWhzFluhi42jm9ZxfGMi7178Zzes4vjGRd69+MwVaHMWW6GLjaOb1nF8YyLvXvxnN6zi+MZF3r34zBVocxZboYu9tcDDspx3mt36dphvN6zi+MZF3r343ob+AGR6v4dZlYjI+WMTYxGIuY2vExXhoqmni1UUUxH7oidP7ZMFWhzFluhswpP1Nk/+65un6myf/dc3UYKtDmLLdC7FJ+psn/3XN0/U2T/AO65umCrQ5iy3Qux8+BxdrG4eL1jTNEzMRpjQ+hWYuaxMTF8AAkAAAAAAAAABG5q6tkhc1dWyQHRs6+ubvhp9FMuM6+urvhp9FQ7qI/jDz1vH9tX1w50ONPS50rMnAAgAACQLgAAAAAAAAAHfM0+prfiq9Vwp80+prfiq9Vw4a/KXoeH9VPwAVbAAAAAAAAAAI3NXVskLmrq2SA6LnX11d8NPop1xnX1zd8NPop3bR4w87b+2r65iNJxZfTgqYrr0StORUcVMyrFF6imBcVYGlGMnxoMS2VKpcxEz7FlXgYpplPCWKNE8YxIy5VXFn3HEn3LynCUV6UeS009GhXEtk/ikmNDh9mOtRRV0PkXiWU03OAEoAAAAAAd8zT6mt+Kr1XCnzT6mt+Kr1XDhr8peh4f1U/ABVsAAAAAAAAAAjc1dWyQuaurZIDoudfXN3w0+inXGdfXN3w0+indtHjDz3Eeyr6/HEY6nBU8eqdDjC5z0Xp/m6FXnNZuXcLMW/a6lh8HiaaZiIq0pwoo7NJuZftxGnjx/txYzit3OiK4ZzdwWN4k9NT57eGx1ETxeNpRctf/ANalVlu3NM/vj/b5Iy9ZpqmOPDPKLGUOnjTU/KcJjePM/u0F0Hf/AFpFvOW3x+LFcf7fbby7amNM1wyenA43/l008Z9V+zjbFvTpqMJfOrSbmNoxVX7aokdLzWvX672i5p0f5d0j+Vbsxr7kuASgAAAAAB3zNPqa34qvVcKfNPqa34qvVcOGvyl6Hh/VT8AFWwAAAAAAAAACNzV1bJC5q6tkgOi519dXfDT6Kdc519c3fDT6KZ3UeMPO2/tq+vhypiKbFqZrjTDr85bsU1aKaYXuWcNOJw800+1R2M3Imj93tSiLkqcuWJidNMJ4PKdrEXZimiOh+dWbUaOiX35LyLRhZmZ9oj8fHjsq2bEzTxY0q25ly3xJ0UxpXeOyDRiL01y+KvNimeiAiYfJhs4LOiIqpjS/bEZZsXKNFVMaH6UZq0ROl+n6ap9gt+P0yBirFy5MW4iJdmj2KPJeRowd3jQu4jRBcpU5ASqAAAAAA75mn1Nb8VXquFPmn1Nb8VXquHDX5S9Dw/qp+ACrYAAAAAAAAABG5q6tkhc1dWyQHRc6+ubvhp9FOuM6+urvhp9FO7qPGHnuI9tX0NALMQAAAAAAAAAAAAAAAHfM0+prfiq9Vwp80+prfiq9Vw4a/KXoeH9VPwAVbAAAAAAAAAAI3NXVskLmrq2SA6TnRZu15Yu1UW66o0U9MU/4VPJr/c3N2Xcsq5zYPJeUqcJjLWIo43E0XoimaP3RXxfZPG/9dUex+tjOPJl6rCRbxGnlVVdNqZpmNNVM6Jj/AB0totrouufPtOAiuqasXd0jk1/ubm7Jya/3Nzdl279X5Hqwl/EYfEVYiizoiqLdE6dM01TERp0adPFn/SE565AimiqrHcWKtHttV9HRp6ejo6JTnzor06NzqnJr/c3N2Tk1/ubm7LuGIzsyTh6rlN+9ctzRRTXHGtVRx4mmKo0dH/1EaJ0TpXtMxVETTMTE/wBYM+dDp0bmZcmv9zc3ZOTX+5ubstODPnQ6dG5mPJr/AHNzdk5Nf7m5uy04M+dDp0bmY8mv9zc3ZOTX+5ubstODPnQ6dG5mPJr/AHNzdk5Nf7m5uy04M+dDp0bmY8mv9zc3ZOTX+5ubstODPnQ6dG5mPJr/AHNzdk5Nf7m5uy04M+dDp0bmY8mv9zc3ZOTX+5ubstODPnQ6dG5UZq0VUZHtxXTNM8aromNH9VuDGqb5vd9nTgpinQAQuAAAAAAAAAAjc1dWyQuaurZIBXbornTXRTVP+Y0uItW40aKKI0ezo9iYD84sWYjRFq3Ee7iwcns91b3YfoAhNm3Ptt0T/T+WE4iIjREaIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEbmrq2SFzV1bJASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG5q6tkhc1dWyQEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARuaurZIXNXVskBIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEbmrq2SFzV1bJASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG5q6tkhc1dWyQEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARuaurZIXNXVskBIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEbmrq2SFzV1bJASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG5q6tkhc1dWyQEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARuaurZIXNXVskBIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEbmrq2SFzV1bJASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG5q6tkhc1dWyQEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARuaurZIXNXVskBIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEbmrq2SFzV1bJASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG5q6tkhc1dWyQEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARuaurZIXNXVskBIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEbmrq2SFzV1bJASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG5q6tkhc1dWyQEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARuaurZIXNXVskBIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEbmrq2SFzV1bJASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG5q6tkgA//Z"},"cat":"disabled-by-default-devtools.screenshot","id":"0x1","name":"Screenshot","ph":"O","pid":55969,"tid":775,"ts":47786554557}, + {"args":{"frame":"8ECEE70925EB8E7B8C2100384AFF4D1A"},"cat":"blink.user_timing","name":"loadEventEnd","ph":"R","pid":56001,"tid":775,"ts":47786774390}, + {"args":{"snapshot":"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"},"cat":"disabled-by-default-devtools.screenshot","id":"0x1","name":"Screenshot","ph":"O","pid":55969,"tid":775,"ts":47787071203}, + {"args":{"snapshot":"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"},"cat":"disabled-by-default-devtools.screenshot","id":"0x1","name":"Screenshot","ph":"O","pid":55969,"tid":775,"ts":47787487853} + ] +} \ No newline at end of file From 446f2d33cfe803e1866aea6d8fe40492192b2415 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 15 Sep 2020 17:43:24 -0400 Subject: [PATCH 38/82] update smoke test --- .../test-definitions/perf/expectations.js | 46 ++----------------- 1 file changed, 4 insertions(+), 42 deletions(-) diff --git a/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js b/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js index 11bd783232eb..f22aa3b3fd7d 100644 --- a/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js +++ b/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js @@ -361,50 +361,12 @@ module.exports = [ url: 'https://github.com/paulirish/lite-youtube-embed', }, blockingTime: 0, + transferSize: '651128 +/- 5000', subItems: { type: 'subitems', - items: [ - { - url: 'https://www.youtube.com/s/player/8c24a503/player_ias.vflset/en_US/base.js', - mainThreadTime: 0, - blockingTime: 0, - }, - { - url: 'https://i.ytimg.com/vi/tgbNymZ7vqY/maxresdefault.jpg', - mainThreadTime: 0, - blockingTime: 0, - }, - { - url: 'https://www.youtube.com/s/player/8c24a503/www-embed-player.vflset/www-embed-player.js', - mainThreadTime: 0, - blockingTime: 0, - }, - { - url: 'https://www.youtube.com/s/player/8c24a503/www-player.css', - mainThreadTime: 0, - blockingTime: 0, - }, - { - url: 'https://www.youtube.com/embed/tgbNymZ7vqY', - mainThreadTime: 0, - blockingTime: 0, - }, - { - url: 'https://www.youtube.com/s/player/8c24a503/player_ias.vflset/en_US/embed.js', - mainThreadTime: 0, - blockingTime: 0, - }, - { - url: 'https://www.youtube.com/yts/jsbin/fetch-polyfill-vfl6MZH8P/fetch-polyfill.js', - mainThreadTime: 0, - blockingTime: 0, - }, - { - url: 'https://yt3.ggpht.com/a/AATXAJxtCYVD65XPtigYUOad-Nd2v3EvnXnz__MkJrg=s68-c-k-c0x00ffffff-no-rj', - mainThreadTime: 0, - blockingTime: 0, - }, - ], + items: { + length: 8, + }, }, }, ], From 085fb7e384e4b4ede50a4c08939ccc60d88b0642 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 15 Sep 2020 17:55:06 -0400 Subject: [PATCH 39/82] smoke --- .../test/smokehouse/test-definitions/perf/expectations.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js b/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js index f22aa3b3fd7d..9df30b983d45 100644 --- a/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js +++ b/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js @@ -361,7 +361,7 @@ module.exports = [ url: 'https://github.com/paulirish/lite-youtube-embed', }, blockingTime: 0, - transferSize: '651128 +/- 5000', + transferSize: '651128 +/- 100000', subItems: { type: 'subitems', items: { From 812affaa386b816b302183d779b5651eb06964c9 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 16 Sep 2020 11:09:04 -0400 Subject: [PATCH 40/82] revert --- lighthouse-core/audits/third-party-summary.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lighthouse-core/audits/third-party-summary.js b/lighthouse-core/audits/third-party-summary.js index 125ba8418f32..8453ffeef14a 100644 --- a/lighthouse-core/audits/third-party-summary.js +++ b/lighthouse-core/audits/third-party-summary.js @@ -106,11 +106,7 @@ class ThirdPartySummary extends Audit { const byURL = new Map(); /** @type {Map} */ const byEntity = new Map(); - const defaultSummary = { - mainThreadTime: 0, - blockingTime: 0, - transferSize: 0, - }; + const defaultSummary = {mainThreadTime: 0, blockingTime: 0, transferSize: 0}; for (const request of networkRecords) { const urlSummary = byURL.get(request.url) || From db17a6656d365fc89c6f99c08d271d9b41848f10 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 16 Sep 2020 14:35:55 -0400 Subject: [PATCH 41/82] update devtools web tests --- .../devtools/lighthouse/lighthouse-export-run-expected.txt | 6 +++--- .../lighthouse/lighthouse-successful-run-expected.txt | 4 +++- .../lighthouse/lighthouse-view-trace-run-expected.txt | 1 + 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-export-run-expected.txt b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-export-run-expected.txt index 57304d5d24dc..c03cb6ed3825 100644 --- a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-export-run-expected.txt +++ b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-export-run-expected.txt @@ -2,11 +2,11 @@ Tests that exporting works. ++++++++ testExportHtml -# of .lh-audit divs (original): 136 +# of .lh-audit divs (original): 137 -# of .lh-audit divs (exported html): 136 +# of .lh-audit divs (exported html): 137 ++++++++ testExportJson -# of audits (json): 152 +# of audits (json): 153 diff --git a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-successful-run-expected.txt b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-successful-run-expected.txt index f80c6a402c7b..35f25f7b5052 100644 --- a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-successful-run-expected.txt +++ b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-successful-run-expected.txt @@ -241,6 +241,7 @@ Computing artifact: ResourceSummary Auditing: Timing budget Auditing: Keep request counts low and transfer sizes small Auditing: Minimize third-party usage +Auditing: Lazy load third-party resources with facade alternatives Auditing: Largest Contentful Paint element Auditing: Avoid large layout shifts Auditing: Avoid long main-thread tasks @@ -536,6 +537,7 @@ tap-targets: fail td-headers-attr: notApplicable th-has-data-cells: notApplicable themed-omnibox: fail +third-party-facades: notApplicable third-party-summary: notApplicable timing-budget: ERROR Chrome didn't collect any screenshots during the page load. Please make sure there is content visible on the page, and then try re-running Lighthouse. (NO_SCREENSHOTS) total-blocking-time: numeric @@ -566,5 +568,5 @@ visual-order-follows-dom: manual without-javascript: pass works-offline: fail -# of .lh-audit divs: 156 +# of .lh-audit divs: 157 diff --git a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-view-trace-run-expected.txt b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-view-trace-run-expected.txt index 8628b1c89fb0..2cfc9741a9f6 100644 --- a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-view-trace-run-expected.txt +++ b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-view-trace-run-expected.txt @@ -50,6 +50,7 @@ resource-summary screenshot-thumbnails server-response-time speed-index +third-party-facades third-party-summary timing-budget total-blocking-time From 4eb748111fe9780d1169888b01a4c9cb02414f7e Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Thu, 17 Sep 2020 13:24:16 -0400 Subject: [PATCH 42/82] change to category column --- lighthouse-core/audits/third-party-facades.js | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index e2ce61e420da..642532a889a2 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -36,8 +36,8 @@ const UIStrings = { =1 {# facade alternative available} other {# facade alternatives available} }`, - /** Label for a table column that displays the name of a facade alternative that lazy loads third party resource. Lazy loading means loading resources is deferred until they are needed. */ - columnFacade: 'Facade Alternative', + /** Label for a table column that displays the name of a category that the third party product falls intl. */ + columnCategory: 'Category', /** Label for a table column that displays the name of the third party product that a URL is used for. */ columnProduct: 'Product', }; @@ -49,7 +49,7 @@ const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings); /** @typedef {import("third-party-web").IFacade} ThirdPartyFacade*/ /** @typedef {{ - * product: ThirdPartyProduct & {facades: ThirdPartyFacade[]}, + * product: ThirdPartyProduct, * cutoffTime: number, * urlSummaries: Map * }} FacadableProductSummary @@ -157,9 +157,6 @@ class ThirdPartyFacades extends Audit { for (const productSummary of productSummaries) { const product = productSummary.product; - // The first facade should always be the best one. - const bestFacade = product.facades[0]; - const items = []; let transferSize = 0; let blockingTime = 0; @@ -175,11 +172,7 @@ class ThirdPartyFacades extends Audit { summary.wastedMs += blockingTime; results.push({ productName: product.name, - facade: /** @type {LH.Audit.Details.LinkValue} */ { - type: 'link', - text: bestFacade.name, - url: bestFacade.repo, - }, + category: product.categories[0], transferSize, blockingTime, subItems: {type: 'subitems', items}, @@ -197,7 +190,7 @@ class ThirdPartyFacades extends Audit { const headings = [ /* eslint-disable max-len */ {key: 'productName', itemType: 'text', subItemsHeading: {key: 'url', itemType: 'url'}, text: str_(UIStrings.columnProduct)}, - {key: 'facade', itemType: 'link', text: str_(UIStrings.columnFacade)}, + {key: 'category', itemType: 'text', text: str_(UIStrings.columnCategory)}, {key: 'transferSize', granularity: 1, itemType: 'bytes', subItemsHeading: {key: 'transferSize'}, text: str_(i18n.UIStrings.columnTransferSize)}, {key: 'blockingTime', granularity: 1, itemType: 'ms', subItemsHeading: {key: 'blockingTime'}, text: str_(i18n.UIStrings.columnBlockingTime)}, /* eslint-enable max-len */ From 4229b06defd41393f724dcd46252fa8ab7424df5 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Mon, 21 Sep 2020 16:18:08 -0400 Subject: [PATCH 43/82] move category to first column --- .../test-definitions/perf/expectations.js | 7 +- lighthouse-core/audits/third-party-facades.js | 29 ++++++-- lighthouse-core/lib/i18n/locales/en-US.json | 7 +- lighthouse-core/lib/i18n/locales/en-XL.json | 7 +- .../test/audits/third-party-facades-test.js | 67 +++++-------------- 5 files changed, 52 insertions(+), 65 deletions(-) diff --git a/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js b/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js index 8d32f439ab95..6e3a37deb6c7 100644 --- a/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js +++ b/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js @@ -365,12 +365,7 @@ module.exports = [ details: { items: [ { - productName: 'YouTube Embedded Player', - facade: { - type: 'link', - text: 'Lite YouTube', - url: 'https://github.com/paulirish/lite-youtube-embed', - }, + product: 'YouTube Embedded Player (Video)', blockingTime: 0, transferSize: '651128 +/- 100000', subItems: { diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 642532a889a2..46fa3f3399b2 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -36,13 +36,25 @@ const UIStrings = { =1 {# facade alternative available} other {# facade alternatives available} }`, - /** Label for a table column that displays the name of a category that the third party product falls intl. */ - columnCategory: 'Category', /** Label for a table column that displays the name of the third party product that a URL is used for. */ columnProduct: 'Product', + /** + * @description Template for an entry in the "Product" column for a third party product which is in the video category. + * @example {YouTube Embed} productName + */ + categoryVideo: '{productName} (Video)', + /** + * @description Template for an entry in the "Product" column for a third party product which is in the customer success category. + * @example {Intercom Widget} productName + */ + categoryCustomerSuccess: '{productName} (Customer Success)', }; const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings); +const CATEGORY_UI_MAP = new Map([ + ['video', UIStrings.categoryVideo], + ['customer-success', UIStrings.categoryCustomerSuccess], +]); /** @typedef {import("third-party-web").IEntity} ThirdPartyEntity */ /** @typedef {import("third-party-web").IProduct} ThirdPartyProduct*/ @@ -156,6 +168,13 @@ class ThirdPartyFacades extends Audit { const results = []; for (const productSummary of productSummaries) { const product = productSummary.product; + const categoryTemplate = CATEGORY_UI_MAP.get(product.categories[0]); + + // Display product name with category next to it in the same column + let productWithCategory = product.name; + if (categoryTemplate) { + productWithCategory = str_(categoryTemplate, {productName: product.name}); + } const items = []; let transferSize = 0; @@ -171,8 +190,7 @@ class ThirdPartyFacades extends Audit { summary.wastedBytes += transferSize; summary.wastedMs += blockingTime; results.push({ - productName: product.name, - category: product.categories[0], + product: productWithCategory, transferSize, blockingTime, subItems: {type: 'subitems', items}, @@ -189,8 +207,7 @@ class ThirdPartyFacades extends Audit { /** @type {LH.Audit.Details.Table['headings']} */ const headings = [ /* eslint-disable max-len */ - {key: 'productName', itemType: 'text', subItemsHeading: {key: 'url', itemType: 'url'}, text: str_(UIStrings.columnProduct)}, - {key: 'category', itemType: 'text', text: str_(UIStrings.columnCategory)}, + {key: 'product', itemType: 'text', subItemsHeading: {key: 'url', itemType: 'url'}, text: str_(UIStrings.columnProduct)}, {key: 'transferSize', granularity: 1, itemType: 'bytes', subItemsHeading: {key: 'transferSize'}, text: str_(i18n.UIStrings.columnTransferSize)}, {key: 'blockingTime', granularity: 1, itemType: 'ms', subItemsHeading: {key: 'blockingTime'}, text: str_(i18n.UIStrings.columnBlockingTime)}, /* eslint-enable max-len */ diff --git a/lighthouse-core/lib/i18n/locales/en-US.json b/lighthouse-core/lib/i18n/locales/en-US.json index 7b808955018a..d79d64be5396 100644 --- a/lighthouse-core/lib/i18n/locales/en-US.json +++ b/lighthouse-core/lib/i18n/locales/en-US.json @@ -1313,8 +1313,11 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Sets a theme color for the address bar." }, - "lighthouse-core/audits/third-party-facades.js | columnFacade": { - "message": "Facade Alternative" + "lighthouse-core/audits/third-party-facades.js | categoryCustomerSuccess": { + "message": "{productName} (Customer Success)" + }, + "lighthouse-core/audits/third-party-facades.js | categoryVideo": { + "message": "{productName} (Video)" }, "lighthouse-core/audits/third-party-facades.js | columnProduct": { "message": "Product" diff --git a/lighthouse-core/lib/i18n/locales/en-XL.json b/lighthouse-core/lib/i18n/locales/en-XL.json index f8b83785de1a..c973fe820068 100644 --- a/lighthouse-core/lib/i18n/locales/en-XL.json +++ b/lighthouse-core/lib/i18n/locales/en-XL.json @@ -1313,8 +1313,11 @@ "lighthouse-core/audits/themed-omnibox.js | title": { "message": "Ŝét̂ś â t́ĥém̂é ĉól̂ór̂ f́ôŕ t̂h́ê ád̂d́r̂éŝś b̂ár̂." }, - "lighthouse-core/audits/third-party-facades.js | columnFacade": { - "message": "F̂áĉád̂é Âĺt̂ér̂ńât́îv́ê" + "lighthouse-core/audits/third-party-facades.js | categoryCustomerSuccess": { + "message": "{productName} (Ĉúŝt́ôḿêŕ Ŝúĉćêśŝ)" + }, + "lighthouse-core/audits/third-party-facades.js | categoryVideo": { + "message": "{productName} (V̂íd̂éô)" }, "lighthouse-core/audits/third-party-facades.js | columnProduct": { "message": "P̂ŕôd́ûćt̂" diff --git a/lighthouse-core/test/audits/third-party-facades-test.js b/lighthouse-core/test/audits/third-party-facades-test.js index abf0f61a8657..58a605f7fdc7 100644 --- a/lighthouse-core/test/audits/third-party-facades-test.js +++ b/lighthouse-core/test/audits/third-party-facades-test.js @@ -67,14 +67,10 @@ describe('Third party facades audit', () => { expect(results.score).toBe(0); expect(results.displayValue).toBeDisplayString('1 facade alternative available'); - expect(results.details.items).toEqual([ + expect(results.details.items[0].product) + .toBeDisplayString('Intercom Widget (Customer Success)'); + expect(results.details.items).toMatchObject([ { - productName: 'Intercom Widget', - facade: { - type: 'link', - text: 'React Live Chat Loader', - url: 'https://github.com/calibreapp/react-live-chat-loader', - }, transferSize: 12000, blockingTime: 0, subItems: { @@ -122,14 +118,11 @@ describe('Third party facades audit', () => { expect(results.score).toBe(0); expect(results.displayValue).toBeDisplayString('2 facade alternatives available'); - expect(results.details.items).toEqual([ + expect(results.details.items[0].product) + .toBeDisplayString('Intercom Widget (Customer Success)'); + expect(results.details.items[1].product).toBeDisplayString('YouTube Embedded Player (Video)'); + expect(results.details.items).toMatchObject([ { - productName: 'Intercom Widget', - facade: { - type: 'link', - text: 'React Live Chat Loader', - url: 'https://github.com/calibreapp/react-live-chat-loader', - }, transferSize: 12000, blockingTime: 0, subItems: { @@ -155,12 +148,6 @@ describe('Third party facades audit', () => { }, }, { - productName: 'YouTube Embedded Player', - facade: { - type: 'link', - text: 'Lite YouTube', - url: 'https://github.com/paulirish/lite-youtube-embed', - }, transferSize: 10000, blockingTime: 0, subItems: { @@ -208,14 +195,10 @@ describe('Third party facades audit', () => { expect(results.score).toBe(0); expect(results.displayValue).toBeDisplayString('1 facade alternative available'); - expect(results.details.items).toEqual([ + expect(results.details.items[0].product) + .toBeDisplayString('Intercom Widget (Customer Success)'); + expect(results.details.items).toMatchObject([ { - productName: 'Intercom Widget', - facade: { - type: 'link', - text: 'React Live Chat Loader', - url: 'https://github.com/calibreapp/react-live-chat-loader', - }, transferSize: 12000, blockingTime: 0, subItems: { @@ -266,14 +249,10 @@ describe('Third party facades audit', () => { expect(results.score).toBe(0); expect(results.displayValue).toBeDisplayString('1 facade alternative available'); - expect(results.details.items).toEqual([ + expect(results.details.items[0].product) + .toBeDisplayString('Intercom Widget (Customer Success)'); + expect(results.details.items).toMatchObject([ { - productName: 'Intercom Widget', - facade: { - type: 'link', - text: 'React Live Chat Loader', - url: 'https://github.com/calibreapp/react-live-chat-loader', - }, transferSize: 12000, blockingTime: 0, subItems: { @@ -371,16 +350,13 @@ describe('Third party facades audit', () => { expect(results.score).toBe(0); expect(results.displayValue).toBeDisplayString('2 facade alternatives available'); - expect(results.details.items).toEqual( + expect(results.details.items[0].product).toBeDisplayString('YouTube Embedded Player (Video)'); + expect(results.details.items[1].product).toBeDisplayString('Vimeo Embedded Player (Video)'); + expect(results.details.items).toMatchObject( [ { + transferSize: 651350, blockingTime: 0, - facade: { - text: 'Lite YouTube', - type: 'link', - url: 'https://github.com/paulirish/lite-youtube-embed', - }, - productName: 'YouTube Embedded Player', subItems: { items: [ { @@ -450,16 +426,10 @@ describe('Third party facades audit', () => { ], type: 'subitems', }, - transferSize: 651350, }, { + transferSize: 184495, blockingTime: 0, - facade: { - text: 'Lite Vimeo', - type: 'link', - url: 'https://github.com/slightlyoff/lite-vimeo', - }, - productName: 'Vimeo Embedded Player', subItems: { items: [ { @@ -537,7 +507,6 @@ describe('Third party facades audit', () => { ], type: 'subitems', }, - transferSize: 184495, }, ] ); From 4c1d52870c4fad2e0584a89ebf063eaea6b7599e Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Mon, 21 Sep 2020 16:34:28 -0400 Subject: [PATCH 44/82] type check --- lighthouse-core/audits/third-party-facades.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 46fa3f3399b2..0286144652be 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -171,9 +171,11 @@ class ThirdPartyFacades extends Audit { const categoryTemplate = CATEGORY_UI_MAP.get(product.categories[0]); // Display product name with category next to it in the same column - let productWithCategory = product.name; + let productWithCategory; if (categoryTemplate) { productWithCategory = str_(categoryTemplate, {productName: product.name}); + } else { + productWithCategory = product.name; } const items = []; From 236fb9beccf3835fff14a351f310a8444c08481b Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Mon, 21 Sep 2020 18:28:36 -0400 Subject: [PATCH 45/82] update description --- lighthouse-core/audits/third-party-facades.js | 5 ++--- lighthouse-core/lib/i18n/locales/en-US.json | 2 +- lighthouse-core/lib/i18n/locales/en-XL.json | 2 +- lighthouse-core/test/results/sample_v2.json | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 0286144652be..2eb4672d56a9 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -28,9 +28,8 @@ const UIStrings = { /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded with a facade alternative. This descriptive title is shown to users when one or more third-party resources have available facade alternatives. Lazy loading means loading resources is deferred until they are needed. */ failureTitle: 'Some third-party resources can be lazy loaded with a facade alternative', /** Description of a Lighthouse audit that identifies the third party code on the page that can be lazy loaded with a facade alternative. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. Lazy loading means loading resources is deferred until they are needed. */ - description: 'Some third-party resources can be fetched after the page loads. ' + - 'These third-party resources are used by embedded elements which can be replaced by a facade ' + - 'until the user needs to use them. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).', + description: 'Some third party embeds can be lazy loaded. ' + + 'Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).', /** Summary text for the result of a Lighthouse audit that identifies the third party code on a web page that can be lazy loaded with a facade alternative. This text summarizes the number of lazy loading facades that can be used on the page. Lazy loading means loading resources is deferred until they are needed. */ displayValue: `{itemCount, plural, =1 {# facade alternative available} diff --git a/lighthouse-core/lib/i18n/locales/en-US.json b/lighthouse-core/lib/i18n/locales/en-US.json index d79d64be5396..919b457df399 100644 --- a/lighthouse-core/lib/i18n/locales/en-US.json +++ b/lighthouse-core/lib/i18n/locales/en-US.json @@ -1323,7 +1323,7 @@ "message": "Product" }, "lighthouse-core/audits/third-party-facades.js | description": { - "message": "Some third-party resources can be fetched after the page loads. These third-party resources are used by embedded elements which can be replaced by a facade until the user needs to use them. [Learn more](https://web.dev/efficiently-load-third-party-javascript/)." + "message": "Some third party embeds can be lazy loaded. Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/)." }, "lighthouse-core/audits/third-party-facades.js | displayValue": { "message": "{itemCount, plural,\n =1 {# facade alternative available}\n other {# facade alternatives available}\n }" diff --git a/lighthouse-core/lib/i18n/locales/en-XL.json b/lighthouse-core/lib/i18n/locales/en-XL.json index c973fe820068..fbdad7241539 100644 --- a/lighthouse-core/lib/i18n/locales/en-XL.json +++ b/lighthouse-core/lib/i18n/locales/en-XL.json @@ -1323,7 +1323,7 @@ "message": "P̂ŕôd́ûćt̂" }, "lighthouse-core/audits/third-party-facades.js | description": { - "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ćâń b̂é f̂ét̂ćĥéd̂ áf̂t́êŕ t̂h́ê ṕâǵê ĺôád̂ś. T̂h́êśê t́ĥír̂d́-p̂ár̂t́ŷ ŕêśôúr̂ćêś âŕê úŝéd̂ b́ŷ ém̂b́êd́d̂éd̂ él̂ém̂én̂t́ŝ ẃĥíĉh́ ĉán̂ b́ê ŕêṕl̂áĉéd̂ b́ŷ á f̂áĉád̂é ûńt̂íl̂ t́ĥé ûśêŕ n̂éêd́ŝ t́ô úŝé t̂h́êḿ. [L̂éâŕn̂ ḿôŕê](https://web.dev/efficiently-load-third-party-javascript/)." + "message": "Ŝóm̂é t̂h́îŕd̂ ṕâŕt̂ý êḿb̂éd̂ś ĉán̂ b́ê ĺâźŷ ĺôád̂éd̂. Ćôńŝíd̂ér̂ ŕêṕl̂áĉín̂ǵ t̂h́êḿ ŵít̂h́ â f́âćâd́ê ún̂t́îĺ t̂h́êý âŕê ŕêq́ûír̂éd̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/efficiently-load-third-party-javascript/)." }, "lighthouse-core/audits/third-party-facades.js | displayValue": { "message": "{itemCount, plural,\n =1 {# f̂áĉád̂é âĺt̂ér̂ńât́îv́ê áv̂áîĺâb́l̂é}\n other {# f̂áĉád̂é âĺt̂ér̂ńât́îv́êś âv́âíl̂áb̂ĺê}\n }" diff --git a/lighthouse-core/test/results/sample_v2.json b/lighthouse-core/test/results/sample_v2.json index ea08f5a6ed3b..01d5c06aa03b 100644 --- a/lighthouse-core/test/results/sample_v2.json +++ b/lighthouse-core/test/results/sample_v2.json @@ -1778,7 +1778,7 @@ "third-party-facades": { "id": "third-party-facades", "title": "Lazy load third-party resources with facade alternatives", - "description": "Some third-party resources can be fetched after the page loads. These third-party resources are used by embedded elements which can be replaced by a facade until the user needs to use them. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).", + "description": "Some third party embeds can be lazy loaded. Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).", "score": null, "scoreDisplayMode": "notApplicable" }, From 3008fa85fbc93f839e4b6fabfd536c302cb2f741 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 22 Sep 2020 13:46:42 -0400 Subject: [PATCH 46/82] add strings --- lighthouse-core/audits/third-party-facades.js | 17 +++++++++++++++-- lighthouse-core/lib/i18n/locales/en-US.json | 6 ++++++ lighthouse-core/lib/i18n/locales/en-XL.json | 6 ++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 2eb4672d56a9..9a464de05171 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -39,7 +39,7 @@ const UIStrings = { columnProduct: 'Product', /** * @description Template for an entry in the "Product" column for a third party product which is in the video category. - * @example {YouTube Embed} productName + * @example {YouTube Embedded Player} productName */ categoryVideo: '{productName} (Video)', /** @@ -47,12 +47,24 @@ const UIStrings = { * @example {Intercom Widget} productName */ categoryCustomerSuccess: '{productName} (Customer Success)', + /** + * @description Template for an entry in the "Product" column for a third party product which is in the marketing category. + * @example {Drift Live Chat} productName + */ + categoryMarketing: '{productName} (Marketing)', + /** + * @description Template for an entry in the "Product" column for a third party product which is in the social category. + * @example {Facebook Messenger Customer Chat} productName + */ + categorySocial: '{productName} (Social)', }; const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings); const CATEGORY_UI_MAP = new Map([ ['video', UIStrings.categoryVideo], ['customer-success', UIStrings.categoryCustomerSuccess], + ['marketing', UIStrings.categoryMarketing], + ['social', UIStrings.categorySocial], ]); /** @typedef {import("third-party-web").IEntity} ThirdPartyEntity */ @@ -169,11 +181,12 @@ class ThirdPartyFacades extends Audit { const product = productSummary.product; const categoryTemplate = CATEGORY_UI_MAP.get(product.categories[0]); - // Display product name with category next to it in the same column let productWithCategory; if (categoryTemplate) { + // Display product name with category next to it in the same column productWithCategory = str_(categoryTemplate, {productName: product.name}); } else { + // Just display product name if no category is found productWithCategory = product.name; } diff --git a/lighthouse-core/lib/i18n/locales/en-US.json b/lighthouse-core/lib/i18n/locales/en-US.json index 919b457df399..49dff9c77cea 100644 --- a/lighthouse-core/lib/i18n/locales/en-US.json +++ b/lighthouse-core/lib/i18n/locales/en-US.json @@ -1316,6 +1316,12 @@ "lighthouse-core/audits/third-party-facades.js | categoryCustomerSuccess": { "message": "{productName} (Customer Success)" }, + "lighthouse-core/audits/third-party-facades.js | categoryMarketing": { + "message": "{productName} (Marketing)" + }, + "lighthouse-core/audits/third-party-facades.js | categorySocial": { + "message": "{productName} (Social)" + }, "lighthouse-core/audits/third-party-facades.js | categoryVideo": { "message": "{productName} (Video)" }, diff --git a/lighthouse-core/lib/i18n/locales/en-XL.json b/lighthouse-core/lib/i18n/locales/en-XL.json index fbdad7241539..318f7896f9c7 100644 --- a/lighthouse-core/lib/i18n/locales/en-XL.json +++ b/lighthouse-core/lib/i18n/locales/en-XL.json @@ -1316,6 +1316,12 @@ "lighthouse-core/audits/third-party-facades.js | categoryCustomerSuccess": { "message": "{productName} (Ĉúŝt́ôḿêŕ Ŝúĉćêśŝ)" }, + "lighthouse-core/audits/third-party-facades.js | categoryMarketing": { + "message": "{productName} (M̂ár̂ḱêt́îńĝ)" + }, + "lighthouse-core/audits/third-party-facades.js | categorySocial": { + "message": "{productName} (Ŝóĉíâĺ)" + }, "lighthouse-core/audits/third-party-facades.js | categoryVideo": { "message": "{productName} (V̂íd̂éô)" }, From 26c463ba5ae8851afef35018dc9ce65dfa6e857f Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 22 Sep 2020 14:10:54 -0400 Subject: [PATCH 47/82] update strings --- lighthouse-core/audits/third-party-facades.js | 4 ++-- lighthouse-core/lib/i18n/locales/en-US.json | 4 ++-- lighthouse-core/lib/i18n/locales/en-XL.json | 4 ++-- lighthouse-core/test/results/sample_v2.json | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 9a464de05171..de2a76c60ff2 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -24,9 +24,9 @@ const ThirdPartySummary = require('./third-party-summary.js'); const UIStrings = { /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded with a facade alternative. This descriptive title is shown to users when no resources have facade alternatives available. Lazy loading means loading resources is deferred until they are needed. */ - title: 'Lazy load third-party resources with facade alternatives', + title: 'Lazy load third-party resources with facades', /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded with a facade alternative. This descriptive title is shown to users when one or more third-party resources have available facade alternatives. Lazy loading means loading resources is deferred until they are needed. */ - failureTitle: 'Some third-party resources can be lazy loaded with a facade alternative', + failureTitle: 'Some third-party resources can be lazy loaded with a facade', /** Description of a Lighthouse audit that identifies the third party code on the page that can be lazy loaded with a facade alternative. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. Lazy loading means loading resources is deferred until they are needed. */ description: 'Some third party embeds can be lazy loaded. ' + 'Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).', diff --git a/lighthouse-core/lib/i18n/locales/en-US.json b/lighthouse-core/lib/i18n/locales/en-US.json index 49dff9c77cea..d3414bc8b2af 100644 --- a/lighthouse-core/lib/i18n/locales/en-US.json +++ b/lighthouse-core/lib/i18n/locales/en-US.json @@ -1335,10 +1335,10 @@ "message": "{itemCount, plural,\n =1 {# facade alternative available}\n other {# facade alternatives available}\n }" }, "lighthouse-core/audits/third-party-facades.js | failureTitle": { - "message": "Some third-party resources can be lazy loaded with a facade alternative" + "message": "Some third-party resources can be lazy loaded with a facade" }, "lighthouse-core/audits/third-party-facades.js | title": { - "message": "Lazy load third-party resources with facade alternatives" + "message": "Lazy load third-party resources with facades" }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "Third-Party" diff --git a/lighthouse-core/lib/i18n/locales/en-XL.json b/lighthouse-core/lib/i18n/locales/en-XL.json index 318f7896f9c7..24d2a124610b 100644 --- a/lighthouse-core/lib/i18n/locales/en-XL.json +++ b/lighthouse-core/lib/i18n/locales/en-XL.json @@ -1335,10 +1335,10 @@ "message": "{itemCount, plural,\n =1 {# f̂áĉád̂é âĺt̂ér̂ńât́îv́ê áv̂áîĺâb́l̂é}\n other {# f̂áĉád̂é âĺt̂ér̂ńât́îv́êś âv́âíl̂áb̂ĺê}\n }" }, "lighthouse-core/audits/third-party-facades.js | failureTitle": { - "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ćâń b̂é l̂áẑý l̂óâd́êd́ ŵít̂h́ â f́âćâd́ê ál̂t́êŕn̂át̂ív̂é" + "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ćâń b̂é l̂áẑý l̂óâd́êd́ ŵít̂h́ â f́âćâd́ê" }, "lighthouse-core/audits/third-party-facades.js | title": { - "message": "L̂áẑý l̂óâd́ t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ẃît́ĥ f́âćâd́ê ál̂t́êŕn̂át̂ív̂éŝ" + "message": "L̂áẑý l̂óâd́ t̂h́îŕd̂-ṕâŕt̂ý r̂éŝóûŕĉéŝ ẃît́ĥ f́âćâd́êś" }, "lighthouse-core/audits/third-party-summary.js | columnThirdParty": { "message": "T̂h́îŕd̂-Ṕâŕt̂ý" diff --git a/lighthouse-core/test/results/sample_v2.json b/lighthouse-core/test/results/sample_v2.json index 01d5c06aa03b..9d36685a973a 100644 --- a/lighthouse-core/test/results/sample_v2.json +++ b/lighthouse-core/test/results/sample_v2.json @@ -1777,7 +1777,7 @@ }, "third-party-facades": { "id": "third-party-facades", - "title": "Lazy load third-party resources with facade alternatives", + "title": "Lazy load third-party resources with facades", "description": "Some third party embeds can be lazy loaded. Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).", "score": null, "scoreDisplayMode": "notApplicable" From 974491cafd3373bd2c7b2f98eaeb510b8a012a4a Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 22 Sep 2020 16:25:12 -0400 Subject: [PATCH 48/82] rebaseline devtools --- .../devtools/lighthouse/lighthouse-export-run-expected.txt | 6 +++--- .../lighthouse/lighthouse-successful-run-expected.txt | 4 +--- .../lighthouse/lighthouse-view-trace-run-expected.txt | 1 - 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-export-run-expected.txt b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-export-run-expected.txt index c03cb6ed3825..57304d5d24dc 100644 --- a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-export-run-expected.txt +++ b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-export-run-expected.txt @@ -2,11 +2,11 @@ Tests that exporting works. ++++++++ testExportHtml -# of .lh-audit divs (original): 137 +# of .lh-audit divs (original): 136 -# of .lh-audit divs (exported html): 137 +# of .lh-audit divs (exported html): 136 ++++++++ testExportJson -# of audits (json): 153 +# of audits (json): 152 diff --git a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-successful-run-expected.txt b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-successful-run-expected.txt index 35f25f7b5052..f80c6a402c7b 100644 --- a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-successful-run-expected.txt +++ b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-successful-run-expected.txt @@ -241,7 +241,6 @@ Computing artifact: ResourceSummary Auditing: Timing budget Auditing: Keep request counts low and transfer sizes small Auditing: Minimize third-party usage -Auditing: Lazy load third-party resources with facade alternatives Auditing: Largest Contentful Paint element Auditing: Avoid large layout shifts Auditing: Avoid long main-thread tasks @@ -537,7 +536,6 @@ tap-targets: fail td-headers-attr: notApplicable th-has-data-cells: notApplicable themed-omnibox: fail -third-party-facades: notApplicable third-party-summary: notApplicable timing-budget: ERROR Chrome didn't collect any screenshots during the page load. Please make sure there is content visible on the page, and then try re-running Lighthouse. (NO_SCREENSHOTS) total-blocking-time: numeric @@ -568,5 +566,5 @@ visual-order-follows-dom: manual without-javascript: pass works-offline: fail -# of .lh-audit divs: 157 +# of .lh-audit divs: 156 diff --git a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-view-trace-run-expected.txt b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-view-trace-run-expected.txt index 2cfc9741a9f6..8628b1c89fb0 100644 --- a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-view-trace-run-expected.txt +++ b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-view-trace-run-expected.txt @@ -50,7 +50,6 @@ resource-summary screenshot-thumbnails server-response-time speed-index -third-party-facades third-party-summary timing-budget total-blocking-time From 5e5179ab6bf194db723544653f73373c49ba2c11 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 29 Sep 2020 14:54:23 -0400 Subject: [PATCH 49/82] rebaseline devtools --- .../devtools/lighthouse/lighthouse-emulate-run-expected.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-emulate-run-expected.txt b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-emulate-run-expected.txt index ec6063810c2f..88586cd42689 100644 --- a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-emulate-run-expected.txt +++ b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-emulate-run-expected.txt @@ -25,5 +25,5 @@ ViewportDimensions: { } -content-width: pass undefined +content-width: pass From 36ea5aa7d0a4ca01e9369fe67078fed5b8910ce2 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Thu, 1 Oct 2020 14:07:36 -0400 Subject: [PATCH 50/82] rebaseline devtools --- .../devtools/lighthouse/lighthouse-emulate-run-expected.txt | 2 +- .../devtools/lighthouse/lighthouse-export-run-expected.txt | 6 +++--- .../lighthouse/lighthouse-successful-run-expected.txt | 4 +++- .../lighthouse/lighthouse-view-trace-run-expected.txt | 1 + 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-emulate-run-expected.txt b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-emulate-run-expected.txt index 88586cd42689..ec6063810c2f 100644 --- a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-emulate-run-expected.txt +++ b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-emulate-run-expected.txt @@ -25,5 +25,5 @@ ViewportDimensions: { } -content-width: pass +content-width: pass undefined diff --git a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-export-run-expected.txt b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-export-run-expected.txt index 57304d5d24dc..c03cb6ed3825 100644 --- a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-export-run-expected.txt +++ b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-export-run-expected.txt @@ -2,11 +2,11 @@ Tests that exporting works. ++++++++ testExportHtml -# of .lh-audit divs (original): 136 +# of .lh-audit divs (original): 137 -# of .lh-audit divs (exported html): 136 +# of .lh-audit divs (exported html): 137 ++++++++ testExportJson -# of audits (json): 152 +# of audits (json): 153 diff --git a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-successful-run-expected.txt b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-successful-run-expected.txt index f80c6a402c7b..02c372d10859 100644 --- a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-successful-run-expected.txt +++ b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-successful-run-expected.txt @@ -241,6 +241,7 @@ Computing artifact: ResourceSummary Auditing: Timing budget Auditing: Keep request counts low and transfer sizes small Auditing: Minimize third-party usage +Auditing: Lazy load third-party resources with facades Auditing: Largest Contentful Paint element Auditing: Avoid large layout shifts Auditing: Avoid long main-thread tasks @@ -536,6 +537,7 @@ tap-targets: fail td-headers-attr: notApplicable th-has-data-cells: notApplicable themed-omnibox: fail +third-party-facades: notApplicable third-party-summary: notApplicable timing-budget: ERROR Chrome didn't collect any screenshots during the page load. Please make sure there is content visible on the page, and then try re-running Lighthouse. (NO_SCREENSHOTS) total-blocking-time: numeric @@ -566,5 +568,5 @@ visual-order-follows-dom: manual without-javascript: pass works-offline: fail -# of .lh-audit divs: 156 +# of .lh-audit divs: 157 diff --git a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-view-trace-run-expected.txt b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-view-trace-run-expected.txt index 8628b1c89fb0..2cfc9741a9f6 100644 --- a/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-view-trace-run-expected.txt +++ b/third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/lighthouse-view-trace-run-expected.txt @@ -50,6 +50,7 @@ resource-summary screenshot-thumbnails server-response-time speed-index +third-party-facades third-party-summary timing-budget total-blocking-time From fb8b5a388ad96524d596e818ef58058a04d32c42 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Thu, 1 Oct 2020 16:32:22 -0400 Subject: [PATCH 51/82] cleanup --- lighthouse-core/audits/third-party-facades.js | 66 +++++++++---------- lighthouse-core/audits/third-party-summary.js | 44 ++++++------- 2 files changed, 53 insertions(+), 57 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index de2a76c60ff2..87b6149bea39 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -35,25 +35,25 @@ const UIStrings = { =1 {# facade alternative available} other {# facade alternatives available} }`, - /** Label for a table column that displays the name of the third party product that a URL is used for. */ + /** Label for a table column that displays the name of the product that a URL is used for. A product is a piece of software used on the page. */ columnProduct: 'Product', /** - * @description Template for an entry in the "Product" column for a third party product which is in the video category. + * @description Template for a table entry that gives the name of a product which we categorize as video related. * @example {YouTube Embedded Player} productName */ categoryVideo: '{productName} (Video)', /** - * @description Template for an entry in the "Product" column for a third party product which is in the customer success category. + * @description Template for a table entry that gives the name of a product which we categorize as customer success related. Customer success means the product supports customers by offering chat and contact solutions. * @example {Intercom Widget} productName */ categoryCustomerSuccess: '{productName} (Customer Success)', /** - * @description Template for an entry in the "Product" column for a third party product which is in the marketing category. + * @description Template for a table entry that gives the name of a product which we categorize as marketing related. * @example {Drift Live Chat} productName */ categoryMarketing: '{productName} (Marketing)', /** - * @description Template for an entry in the "Product" column for a third party product which is in the social category. + * @description Template for a table entry that gives the name of a product which we categorize as social related. * @example {Facebook Messenger Customer Chat} productName */ categorySocial: '{productName} (Social)', @@ -101,47 +101,51 @@ class ThirdPartyFacades extends Audit { /** @type {Map>} */ const entitySummaries = new Map(); + // The first pass finds all requests to products that have a facade. for (const [url, urlSummary] of byURL) { const entity = thirdPartyWeb.getEntity(url); if (!entity || thirdPartyWeb.isFirstParty(url, mainEntity)) continue; - const productSummaries = entitySummaries.get(entity.name) || new Map(); const product = thirdPartyWeb.getProduct(url); - if (product && product.facades && product.facades.length) { - // Record new url if product has a facade. + if (!product || !product.facades || !product.facades.length) continue; - /** @type {FacadableProductSummary} */ - const productSummary = productSummaries.get(product.name) || { - product, - cutoffTime: Infinity, - urlSummaries: new Map(), - }; + /** @type {Map} */ + const productSummaries = entitySummaries.get(entity.name) || new Map(); + /** @type {FacadableProductSummary} */ + const productSummary = productSummaries.get(product.name) || { + product, + cutoffTime: Infinity, + urlSummaries: new Map(), + }; - productSummary.urlSummaries.set(url, urlSummary); + productSummary.urlSummaries.set(url, urlSummary); - // This is the time the product resource is fetched. - // Any resources of the same entity fetched after this point are considered as part of this product. - productSummary.cutoffTime = Math.min(productSummary.cutoffTime, urlSummary.firstEndTime); + // This is the time the product resource is fetched. + // Any resources of the same entity fetched after this point are considered as part of this product. + productSummary.cutoffTime = Math.min(productSummary.cutoffTime, urlSummary.firstEndTime); - productSummaries.set(product.name, productSummary); - } + productSummaries.set(product.name, productSummary); entitySummaries.set(entity.name, productSummaries); } + // The second pass finds all other resources belonging to one of the products found above. for (const [url, urlSummary] of byURL) { const entity = thirdPartyWeb.getEntity(url); if (!entity || thirdPartyWeb.isFirstParty(url, mainEntity)) continue; - const productSummaries = entitySummaries.get(entity.name) || new Map(); const product = thirdPartyWeb.getProduct(url); - if (!product || !product.facades || !product.facades.length) { - // If the url does not have a facade but one or more products on its entity do, - // we still want to record this url because it was probably fetched by a product with a facade. - for (const productSummary of productSummaries.values()) { - if (urlSummary.firstStartTime < productSummary.cutoffTime) continue; - productSummary.urlSummaries.set(url, urlSummary); - } + if (product && product.facades && product.facades.length) continue; + + const productSummaries = entitySummaries.get(entity.name); + if (!productSummaries) continue; + + // If the url does not have a facade but one or more products on its entity do, + // we still want to record this url because it was probably fetched by a product with a facade. + for (const productSummary of productSummaries.values()) { + if (urlSummary.firstStartTime < productSummary.cutoffTime) continue; + productSummary.urlSummaries.set(url, urlSummary); } + entitySummaries.set(entity.name, productSummaries); } @@ -173,8 +177,6 @@ class ThirdPartyFacades extends Audit { const productSummaries = ThirdPartyFacades.getFacadableProductSummaries(thirdPartySummaries.byURL, mainEntity); - const summary = {wastedBytes: 0, wastedMs: 0}; - /** @type {LH.Audit.Details.TableItem[]} */ const results = []; for (const productSummary of productSummaries) { @@ -201,8 +203,6 @@ class ThirdPartyFacades extends Audit { items.sort((a, b) => { return b.transferSize - a.transferSize; }); - summary.wastedBytes += transferSize; - summary.wastedMs += blockingTime; results.push({ product: productWithCategory, transferSize, @@ -232,7 +232,7 @@ class ThirdPartyFacades extends Audit { displayValue: str_(UIStrings.displayValue, { itemCount: results.length, }), - details: Audit.makeTableDetails(headings, results, summary), + details: Audit.makeTableDetails(headings, results), }; } } diff --git a/lighthouse-core/audits/third-party-summary.js b/lighthouse-core/audits/third-party-summary.js index fe568c575270..9c9c9bc3f8f6 100644 --- a/lighthouse-core/audits/third-party-summary.js +++ b/lighthouse-core/audits/third-party-summary.js @@ -39,36 +39,32 @@ const PASS_THRESHOLD_IN_MS = 250; /** @typedef {import("third-party-web").IEntity} ThirdPartyEntity */ /** - * @typedef {{ - * mainThreadTime: number, - * transferSize: number, - * blockingTime: number, - * firstStartTime: number, - * firstEndTime: number, - * }} Summary + * @typedef Summary + * @property {number} mainThreadTime + * @property {number} transferSize + * @property {number} blockingTime + * @property {number} firstStartTime Start time of the first network request. + * @property {number} firstEndTime End time of the first network request. */ /** - * @typedef {{ - * mainThreadTime: number, - * transferSize: number, - * blockingTime: number, - * }} EntitySummary + * @typedef EntitySummary + * @property {number} mainThreadTime + * @property {number} transferSize + * @property {number} blockingTime */ /** - * @typedef {{ - * transferSize: number, - * blockingTime: number, - * url: string | LH.IcuMessage, - * }} URLSummary + * @typedef URLSummary + * @property {number} transferSize + * @property {number} blockingTime + * @property {string | LH.IcuMessage} url */ -/** @typedef {{ - * byEntity: Map, - * byURL: Map, - * urls: Map - * }} SummaryMap +/** @typedef SummaryMaps + * @property {Map} byEntity Map of impact summaries for each entity. + * @property {Map} byURL Map of impact summaries for each URL. + * @property {Map} urls Map of URLs under each entity. */ /** @@ -99,7 +95,7 @@ class ThirdPartySummary extends Audit { * @param {Array} networkRecords * @param {Array} mainThreadTasks * @param {number} cpuMultiplier - * @return {SummaryMap} + * @return {SummaryMaps} */ static getSummaries(networkRecords, mainThreadTasks, cpuMultiplier) { /** @type {Map} */ @@ -166,7 +162,7 @@ class ThirdPartySummary extends Audit { /** * @param {ThirdPartyEntity} entity - * @param {SummaryMap} summaries + * @param {SummaryMaps} summaries * @param {EntitySummary} stats * @return {Array} */ From aa307021c973bf47711a8cd5494d8fda73e4be10 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Thu, 1 Oct 2020 16:39:23 -0400 Subject: [PATCH 52/82] rename cutoff --- lighthouse-core/audits/third-party-facades.js | 9 +++++---- lighthouse-core/test/audits/third-party-facades-test.js | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 87b6149bea39..e9e49facc856 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -73,7 +73,7 @@ const CATEGORY_UI_MAP = new Map([ /** @typedef {{ * product: ThirdPartyProduct, - * cutoffTime: number, + * startOfProductRequests: number, * urlSummaries: Map * }} FacadableProductSummary */ @@ -114,7 +114,7 @@ class ThirdPartyFacades extends Audit { /** @type {FacadableProductSummary} */ const productSummary = productSummaries.get(product.name) || { product, - cutoffTime: Infinity, + startOfProductRequests: Infinity, urlSummaries: new Map(), }; @@ -122,7 +122,8 @@ class ThirdPartyFacades extends Audit { // This is the time the product resource is fetched. // Any resources of the same entity fetched after this point are considered as part of this product. - productSummary.cutoffTime = Math.min(productSummary.cutoffTime, urlSummary.firstEndTime); + productSummary.startOfProductRequests + = Math.min(productSummary.startOfProductRequests, urlSummary.firstEndTime); productSummaries.set(product.name, productSummary); entitySummaries.set(entity.name, productSummaries); @@ -142,7 +143,7 @@ class ThirdPartyFacades extends Audit { // If the url does not have a facade but one or more products on its entity do, // we still want to record this url because it was probably fetched by a product with a facade. for (const productSummary of productSummaries.values()) { - if (urlSummary.firstStartTime < productSummary.cutoffTime) continue; + if (urlSummary.firstStartTime < productSummary.startOfProductRequests) continue; productSummary.urlSummaries.set(url, urlSummary); } diff --git a/lighthouse-core/test/audits/third-party-facades-test.js b/lighthouse-core/test/audits/third-party-facades-test.js index 58a605f7fdc7..d65bb1da6444 100644 --- a/lighthouse-core/test/audits/third-party-facades-test.js +++ b/lighthouse-core/test/audits/third-party-facades-test.js @@ -180,7 +180,7 @@ describe('Third party facades audit', () => { devtoolsLogs: { defaultPass: networkRecordsToDevtoolsLog([ resourceEntry(100, 101, 102, 2000, 'https://example.com'), - // The first product entry is used for the cutoff time + // The first product entry is used to mark the start of product requests intercomProductEntry(200, 201, 202, 2000, '1'), intercomResourceEntry(300, 301, 302, 8000, 'a'), intercomProductEntry(400, 401, 402, 2000, '1'), @@ -226,7 +226,7 @@ describe('Third party facades audit', () => { ]); }); - it('uses receiveHeadersEnd as cutoff', async () => { + it('uses receiveHeadersEnd to mark start of product requests', async () => { const artifacts = { devtoolsLogs: { defaultPass: networkRecordsToDevtoolsLog([ From 8c861745c0bf62a703fe71795a0c10ab2df148c5 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Thu, 1 Oct 2020 17:35:05 -0400 Subject: [PATCH 53/82] more cleanup --- lighthouse-core/audits/third-party-facades.js | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index e9e49facc856..ee84e3d6c440 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -74,6 +74,8 @@ const CATEGORY_UI_MAP = new Map([ /** @typedef {{ * product: ThirdPartyProduct, * startOfProductRequests: number, + * transferSize: number, + * blockingTime: number, * urlSummaries: Map * }} FacadableProductSummary */ @@ -114,11 +116,15 @@ class ThirdPartyFacades extends Audit { /** @type {FacadableProductSummary} */ const productSummary = productSummaries.get(product.name) || { product, + transferSize: 0, + blockingTime: 0, startOfProductRequests: Infinity, urlSummaries: new Map(), }; productSummary.urlSummaries.set(url, urlSummary); + productSummary.transferSize += urlSummary.transferSize; + productSummary.blockingTime += urlSummary.blockingTime; // This is the time the product resource is fetched. // Any resources of the same entity fetched after this point are considered as part of this product. @@ -145,6 +151,8 @@ class ThirdPartyFacades extends Audit { for (const productSummary of productSummaries.values()) { if (urlSummary.firstStartTime < productSummary.startOfProductRequests) continue; productSummary.urlSummaries.set(url, urlSummary); + productSummary.transferSize += urlSummary.transferSize; + productSummary.blockingTime += urlSummary.blockingTime; } entitySummaries.set(entity.name, productSummaries); @@ -193,21 +201,15 @@ class ThirdPartyFacades extends Audit { productWithCategory = product.name; } - const items = []; - let transferSize = 0; - let blockingTime = 0; - for (const [url, urlStats] of productSummary.urlSummaries) { - items.push({url, ...urlStats}); - transferSize += urlStats.transferSize; - blockingTime += urlStats.blockingTime; - } - items.sort((a, b) => { - return b.transferSize - a.transferSize; - }); + const items = Array.from(productSummary.urlSummaries) + .map(([url, urlStats]) => { + return {url, ...urlStats}; + }) + .sort((a, b) => b.transferSize - a.transferSize); results.push({ product: productWithCategory, - transferSize, - blockingTime, + transferSize: productSummary.transferSize, + blockingTime: productSummary.blockingTime, subItems: {type: 'subitems', items}, }); } From 088f73c3e99ba862b0d294eaaf0b8a86f26d81a8 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Mon, 5 Oct 2020 18:17:31 -0400 Subject: [PATCH 54/82] identify first resource in LH --- lighthouse-core/audits/third-party-facades.js | 89 ++++++++++++++----- 1 file changed, 67 insertions(+), 22 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index ee84e3d6c440..8022f45d3f16 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -60,12 +60,24 @@ const UIStrings = { }; const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings); -const CATEGORY_UI_MAP = new Map([ - ['video', UIStrings.categoryVideo], - ['customer-success', UIStrings.categoryCustomerSuccess], - ['marketing', UIStrings.categoryMarketing], - ['social', UIStrings.categorySocial], -]); + +/** @type {Record} */ +const CATEGORY_UI_MAP = { + 'video': UIStrings.categoryVideo, + 'customer-success': UIStrings.categoryCustomerSuccess, + 'marketing': UIStrings.categoryMarketing, + 'social': UIStrings.categorySocial, +}; + +/** @type {Record} */ +const DEFERRABLE_PRODUCT_FIRST_RESOURCE = { + 'Facebook Messenger Customer Chat': /connect\.facebook.net\/.*\/sdk\/xfbml\.customerchat\.js/, + 'YouTube Embedded Player': /youtube\.com\/embed\//, + 'Help Scout Beacon': /beacon-v2\.helpscout\.net/, + 'Vimeo Embedded Player': /player\.vimeo\.com\/video\//, + 'Drift Live Chat': /js\.driftt\.com\/include\/.*\/.*\.js/, + 'Intercom Widget': /widget\.intercom\.io\/widget\/.*/, +}; /** @typedef {import("third-party-web").IEntity} ThirdPartyEntity */ /** @typedef {import("third-party-web").IProduct} ThirdPartyProduct*/ @@ -94,6 +106,18 @@ class ThirdPartyFacades extends Audit { }; } + /** + * @param {string} url + * @return {string[]} + */ + static firstResourceProductNames(url) { + const productNames = []; + for (const [name, regex] of Object.entries(DEFERRABLE_PRODUCT_FIRST_RESOURCE)) { + if (regex.test(url)) productNames.push(name); + } + return productNames; + } + /** * @param {Map} byURL * @param {ThirdPartyEntity | undefined} mainEntity @@ -104,7 +128,7 @@ class ThirdPartyFacades extends Audit { const entitySummaries = new Map(); // The first pass finds all requests to products that have a facade. - for (const [url, urlSummary] of byURL) { + for (const url of byURL.keys()) { const entity = thirdPartyWeb.getEntity(url); if (!entity || thirdPartyWeb.isFirstParty(url, mainEntity)) continue; @@ -113,35 +137,54 @@ class ThirdPartyFacades extends Audit { /** @type {Map} */ const productSummaries = entitySummaries.get(entity.name) || new Map(); - /** @type {FacadableProductSummary} */ - const productSummary = productSummaries.get(product.name) || { + if (productSummaries.has(product.name)) continue; + + productSummaries.set(product.name, { product, transferSize: 0, blockingTime: 0, startOfProductRequests: Infinity, urlSummaries: new Map(), - }; + }); + entitySummaries.set(entity.name, productSummaries); + } - productSummary.urlSummaries.set(url, urlSummary); - productSummary.transferSize += urlSummary.transferSize; - productSummary.blockingTime += urlSummary.blockingTime; + // The second pass finds the first request for any products found in the first pass. + for (const [url, urlSummary] of byURL) { + const entity = thirdPartyWeb.getEntity(url); + if (!entity || thirdPartyWeb.isFirstParty(url, mainEntity)) continue; + + const productSummaries = entitySummaries.get(entity.name); + if (!productSummaries) continue; + + const productNames = this.firstResourceProductNames(url); + if (!productNames.length) continue; - // This is the time the product resource is fetched. - // Any resources of the same entity fetched after this point are considered as part of this product. - productSummary.startOfProductRequests - = Math.min(productSummary.startOfProductRequests, urlSummary.firstEndTime); + for (const productName of productNames) { + const productSummary = productSummaries.get(productName); + if (!productSummary) continue; - productSummaries.set(product.name, productSummary); + productSummary.urlSummaries.set(url, urlSummary); + productSummary.transferSize += urlSummary.transferSize; + productSummary.blockingTime += urlSummary.blockingTime; + + // This is the time the product resource is fetched. + // Any resources of the same entity fetched after this point are considered as part of this product. + productSummary.startOfProductRequests + = Math.min(productSummary.startOfProductRequests, urlSummary.firstEndTime); + + productSummaries.set(productName, productSummary); + } entitySummaries.set(entity.name, productSummaries); } - // The second pass finds all other resources belonging to one of the products found above. + // The third pass finds all other resources belonging to one of the products found above. for (const [url, urlSummary] of byURL) { const entity = thirdPartyWeb.getEntity(url); if (!entity || thirdPartyWeb.isFirstParty(url, mainEntity)) continue; - const product = thirdPartyWeb.getProduct(url); - if (product && product.facades && product.facades.length) continue; + // The first resource was already counted. + if (this.firstResourceProductNames(url).length) continue; const productSummaries = entitySummaries.get(entity.name); if (!productSummaries) continue; @@ -161,6 +204,8 @@ class ThirdPartyFacades extends Audit { const allProductSummaries = []; for (const productSummaries of entitySummaries.values()) { for (const productSummary of productSummaries.values()) { + // Ignore any product where a first request could not be found. + if (productSummary.startOfProductRequests === Infinity) continue; allProductSummaries.push(productSummary); } } @@ -190,7 +235,7 @@ class ThirdPartyFacades extends Audit { const results = []; for (const productSummary of productSummaries) { const product = productSummary.product; - const categoryTemplate = CATEGORY_UI_MAP.get(product.categories[0]); + const categoryTemplate = CATEGORY_UI_MAP[product.categories[0]]; let productWithCategory; if (categoryTemplate) { From 703bd72fde551c1782dac84626347352389f378f Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Mon, 5 Oct 2020 18:36:47 -0400 Subject: [PATCH 55/82] rename firstEndTime --- lighthouse-core/audits/third-party-facades.js | 2 +- lighthouse-core/audits/third-party-summary.js | 13 ++--- .../test/audits/third-party-facades-test.js | 54 +++++++++---------- .../test/audits/third-party-summary-test.js | 4 +- 4 files changed, 37 insertions(+), 36 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 8022f45d3f16..56fa7c76ecb1 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -171,7 +171,7 @@ class ThirdPartyFacades extends Audit { // This is the time the product resource is fetched. // Any resources of the same entity fetched after this point are considered as part of this product. productSummary.startOfProductRequests - = Math.min(productSummary.startOfProductRequests, urlSummary.firstEndTime); + = Math.min(productSummary.startOfProductRequests, urlSummary.firstContentAvailable); productSummaries.set(productName, productSummary); } diff --git a/lighthouse-core/audits/third-party-summary.js b/lighthouse-core/audits/third-party-summary.js index 9c9c9bc3f8f6..7146f28113e5 100644 --- a/lighthouse-core/audits/third-party-summary.js +++ b/lighthouse-core/audits/third-party-summary.js @@ -44,7 +44,7 @@ const PASS_THRESHOLD_IN_MS = 250; * @property {number} transferSize * @property {number} blockingTime * @property {number} firstStartTime Start time of the first network request. - * @property {number} firstEndTime End time of the first network request. + * @property {number} firstContentAvailable First time when content is available. If that time is unavailable, use end time. */ /** @@ -106,15 +106,16 @@ class ThirdPartySummary extends Audit { for (const request of networkRecords) { const urlSummary = byURL.get(request.url) || - {...defaultSummary, firstStartTime: Infinity, firstEndTime: Infinity}; + {...defaultSummary, firstStartTime: Infinity, firstContentAvailable: Infinity}; urlSummary.transferSize += request.transferSize; urlSummary.firstStartTime = Math.min(urlSummary.firstStartTime, request.startTime); if (request.timing) { - // Lookahead preparser may start requests before entire HTML is loaded const receiveHeadersEndTime = request.startTime + request.timing.receiveHeadersEnd / 1000; - urlSummary.firstEndTime = Math.min(urlSummary.firstEndTime, receiveHeadersEndTime); + urlSummary.firstContentAvailable + = Math.min(urlSummary.firstContentAvailable, receiveHeadersEndTime); } else { - urlSummary.firstEndTime = Math.min(urlSummary.firstEndTime, request.endTime); + urlSummary.firstContentAvailable + = Math.min(urlSummary.firstContentAvailable, request.endTime); } byURL.set(request.url, urlSummary); } @@ -125,7 +126,7 @@ class ThirdPartySummary extends Audit { const attributableURL = BootupTime.getAttributableURLForTask(task, jsURLs); const urlSummary = byURL.get(attributableURL) || - {...defaultSummary, firstStartTime: Infinity, firstEndTime: Infinity}; + {...defaultSummary, firstStartTime: Infinity, firstContentAvailable: Infinity}; const taskDuration = task.selfTime * cpuMultiplier; // The amount of time spent on main thread is the sum of all durations. urlSummary.mainThreadTime += taskDuration; diff --git a/lighthouse-core/test/audits/third-party-facades-test.js b/lighthouse-core/test/audits/third-party-facades-test.js index d65bb1da6444..6a9c135d796e 100644 --- a/lighthouse-core/test/audits/third-party-facades-test.js +++ b/lighthouse-core/test/audits/third-party-facades-test.js @@ -82,7 +82,7 @@ describe('Third party facades audit', () => { blockingTime: 0, transferSize: 8000, firstStartTime: 300, - firstEndTime: 301, + firstContentAvailable: 301, }, { url: 'https://widget.intercom.io/widget/1', @@ -90,7 +90,7 @@ describe('Third party facades audit', () => { blockingTime: 0, transferSize: 4000, firstStartTime: 200, - firstEndTime: 201, + firstContentAvailable: 201, }, ], }, @@ -134,7 +134,7 @@ describe('Third party facades audit', () => { blockingTime: 0, transferSize: 8000, firstStartTime: 300, - firstEndTime: 301, + firstContentAvailable: 301, }, { url: 'https://widget.intercom.io/widget/1', @@ -142,7 +142,7 @@ describe('Third party facades audit', () => { blockingTime: 0, transferSize: 4000, firstStartTime: 200, - firstEndTime: 201, + firstContentAvailable: 201, }, ], }, @@ -159,7 +159,7 @@ describe('Third party facades audit', () => { blockingTime: 0, transferSize: 7000, firstStartTime: 310, - firstEndTime: 311, + firstContentAvailable: 311, }, { url: 'https://www.youtube.com/embed/2', @@ -167,7 +167,7 @@ describe('Third party facades audit', () => { blockingTime: 0, transferSize: 3000, firstStartTime: 210, - firstEndTime: 211, + firstContentAvailable: 211, }, ], }, @@ -210,7 +210,7 @@ describe('Third party facades audit', () => { blockingTime: 0, transferSize: 8000, firstStartTime: 300, - firstEndTime: 301, + firstContentAvailable: 301, }, { url: 'https://widget.intercom.io/widget/1', @@ -218,7 +218,7 @@ describe('Third party facades audit', () => { blockingTime: 0, transferSize: 4000, firstStartTime: 200, - firstEndTime: 201, + firstContentAvailable: 201, }, ], }, @@ -264,7 +264,7 @@ describe('Third party facades audit', () => { blockingTime: 0, transferSize: 8000, firstStartTime: 206, - firstEndTime: 208, + firstContentAvailable: 208, }, { url: 'https://widget.intercom.io/widget/1', @@ -272,7 +272,7 @@ describe('Third party facades audit', () => { blockingTime: 0, transferSize: 4000, firstStartTime: 200, - firstEndTime: 205, + firstContentAvailable: 205, }, ], }, @@ -361,7 +361,7 @@ describe('Third party facades audit', () => { items: [ { blockingTime: 0, - firstEndTime: 47786.347774999995, + firstContentAvailable: 47786.347774999995, firstStartTime: 47786.326268, mainThreadTime: 0, transferSize: 459603, @@ -369,7 +369,7 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstEndTime: 47786.692717, + firstContentAvailable: 47786.692717, firstStartTime: 47786.569798, mainThreadTime: 0, transferSize: 66273, @@ -377,7 +377,7 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstEndTime: 47786.436251, + firstContentAvailable: 47786.436251, firstStartTime: 47786.325979, mainThreadTime: 0, transferSize: 50213, @@ -385,7 +385,7 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstEndTime: 47786.441221, + firstContentAvailable: 47786.441221, firstStartTime: 47786.324095, mainThreadTime: 0, transferSize: 46813, @@ -393,7 +393,7 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstEndTime: 47786.580910000004, + firstContentAvailable: 47786.580910000004, firstStartTime: 47786.561199, mainThreadTime: 0, transferSize: 11477, @@ -401,7 +401,7 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstEndTime: 47786.303873000004, + firstContentAvailable: 47786.303873000004, firstStartTime: 47786.066226, mainThreadTime: 0, transferSize: 10703, @@ -409,7 +409,7 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstEndTime: 47786.414732000005, + firstContentAvailable: 47786.414732000005, firstStartTime: 47786.326585, mainThreadTime: 0, transferSize: 3191, @@ -417,7 +417,7 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstEndTime: 47786.679700999994, + firstContentAvailable: 47786.679700999994, firstStartTime: 47786.568895, mainThreadTime: 0, transferSize: 3077, @@ -434,7 +434,7 @@ describe('Third party facades audit', () => { items: [ { blockingTime: 0, - firstEndTime: 47786.422034999996, + firstContentAvailable: 47786.422034999996, firstStartTime: 47786.323843, mainThreadTime: 0, transferSize: 145772, @@ -442,7 +442,7 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstEndTime: 47786.422311999995, + firstContentAvailable: 47786.422311999995, firstStartTime: 47786.324528, mainThreadTime: 0, transferSize: 17633, @@ -450,7 +450,7 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstEndTime: 47786.634061000004, + firstContentAvailable: 47786.634061000004, firstStartTime: 47786.606134, mainThreadTime: 0, transferSize: 9313, @@ -458,7 +458,7 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstEndTime: 47786.291588, + firstContentAvailable: 47786.291588, firstStartTime: 47786.074447, mainThreadTime: 0, transferSize: 8300, @@ -466,7 +466,7 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstEndTime: 47786.47053, + firstContentAvailable: 47786.47053, firstStartTime: 47786.325692, mainThreadTime: 0, transferSize: 1474, @@ -474,7 +474,7 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstEndTime: 47786.417184000005, + firstContentAvailable: 47786.417184000005, firstStartTime: 47786.32147, mainThreadTime: 0, transferSize: 1075, @@ -482,7 +482,7 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstEndTime: 47787.641538, + firstContentAvailable: 47787.641538, firstStartTime: 47786.499527, mainThreadTime: 0, transferSize: 818, @@ -490,7 +490,7 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstEndTime: 47786.70353599999, + firstContentAvailable: 47786.70353599999, firstStartTime: 47786.608785, mainThreadTime: 0, transferSize: 110, @@ -498,7 +498,7 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstEndTime: 47786.06986, + firstContentAvailable: 47786.06986, firstStartTime: 47786.069794, mainThreadTime: 0, transferSize: 0, diff --git a/lighthouse-core/test/audits/third-party-summary-test.js b/lighthouse-core/test/audits/third-party-summary-test.js index 2894a4974128..4dab7079c676 100644 --- a/lighthouse-core/test/audits/third-party-summary-test.js +++ b/lighthouse-core/test/audits/third-party-summary-test.js @@ -44,7 +44,7 @@ describe('Third party summary', () => { mainThreadTime: 127.15300000000003, transferSize: 30827, firstStartTime: 225414.728913, - firstEndTime: 225414.940324, + firstContentAvailable: 225414.940324, url: 'https://www.googletagmanager.com/gtm.js?id=GTM-Q5SW', }, ], @@ -67,7 +67,7 @@ describe('Third party summary', () => { mainThreadTime: 55.246999999999986, transferSize: 12906, firstStartTime: 225415.251281, - firstEndTime: 225415.469618, + firstContentAvailable: 225415.469618, url: 'https://www.google-analytics.com/analytics.js', }, { From 5bee091e96428585ed8af5f9f5abbed034d53297 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Mon, 5 Oct 2020 18:55:31 -0400 Subject: [PATCH 56/82] update sample --- lighthouse-core/test/results/sample_v2.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-core/test/results/sample_v2.json b/lighthouse-core/test/results/sample_v2.json index 3f78e57922eb..5850b154e811 100644 --- a/lighthouse-core/test/results/sample_v2.json +++ b/lighthouse-core/test/results/sample_v2.json @@ -1785,7 +1785,7 @@ "blockingTime": 22.918000000000006, "transferSize": 30174, "firstStartTime": 185607.195975, - "firstEndTime": 185607.822806 + "firstContentAvailable": 185607.822806 } ] } From b9328f392f09d9f5fbaed353f69b6e5bdd5e590b Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 6 Oct 2020 14:29:40 -0400 Subject: [PATCH 57/82] condense last row --- lighthouse-core/audits/third-party-facades.js | 20 +++++ lighthouse-core/audits/third-party-summary.js | 4 +- lighthouse-core/lib/i18n/i18n.js | 2 + .../test/audits/third-party-facades-test.js | 82 ++++++++++++++----- 4 files changed, 85 insertions(+), 23 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 56fa7c76ecb1..f026c189c445 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -118,6 +118,25 @@ class ThirdPartyFacades extends Audit { return productNames; } + /** + * @param {(ThirdPartySummary.Summary & {url: string | LH.IcuMessage})[]} items + */ + static condenseItems(items) { + const splitIndex = items.findIndex((item) => item.transferSize < 1000); + if (splitIndex === -1) return; + + const remainder = items.splice(splitIndex); + const finalItem = remainder.reduce((result, item) => { + result.transferSize += item.transferSize; + result.blockingTime += item.blockingTime; + result.mainThreadTime += item.mainThreadTime; + return result; + }); + finalItem.url = str_(i18n.UIStrings.otherValue); + finalItem.firstStartTime = finalItem.firstContentAvailable = 0; + items.push(finalItem); + } + /** * @param {Map} byURL * @param {ThirdPartyEntity | undefined} mainEntity @@ -251,6 +270,7 @@ class ThirdPartyFacades extends Audit { return {url, ...urlStats}; }) .sort((a, b) => b.transferSize - a.transferSize); + this.condenseItems(items); results.push({ product: productWithCategory, transferSize: productSummary.transferSize, diff --git a/lighthouse-core/audits/third-party-summary.js b/lighthouse-core/audits/third-party-summary.js index 7146f28113e5..5f71b648cb16 100644 --- a/lighthouse-core/audits/third-party-summary.js +++ b/lighthouse-core/audits/third-party-summary.js @@ -27,8 +27,6 @@ const UIStrings = { /** Summary text for the result of a Lighthouse audit that identifies the code on a web page that the user doesn't control (referred to as "third-party code"). This text summarizes the number of distinct entities that were found on the page. */ displayValue: 'Third-party code blocked the main thread for ' + `{timeInMs, number, milliseconds}\xa0ms`, - /** Label used to identify a value in a table where many individual values are aggregated to a single value, for brevity. "Other resources" could also be read as "the rest of the resources". Resource refers to network resources requested by the browser. */ - otherValue: 'Other resources', }; const str_ = i18n.createMessageInstanceIdFn(__filename, UIStrings); @@ -200,7 +198,7 @@ class ThirdPartySummary extends Audit { // we'll replace the tail entries with single remainder entry. items = items.slice(0, numSubItems); const remainder = { - url: str_(UIStrings.otherValue), + url: str_(i18n.UIStrings.otherValue), transferSize: stats.transferSize - subitemSummary.transferSize, blockingTime: stats.blockingTime - subitemSummary.blockingTime, }; diff --git a/lighthouse-core/lib/i18n/i18n.js b/lighthouse-core/lib/i18n/i18n.js index f43ca1b8a92c..2a1f40cc34a8 100644 --- a/lighthouse-core/lib/i18n/i18n.js +++ b/lighthouse-core/lib/i18n/i18n.js @@ -110,6 +110,8 @@ const UIStrings = { otherResourceType: 'Other', /** Label for a row in a data table; entries will be the total number and byte size of all third-party resources loaded by a web page. 'Third-party resources are items loaded from URLs that aren't controlled by the owner of the web page. */ thirdPartyResourceType: 'Third-party', + /** Label used to identify a value in a table where many individual values are aggregated to a single value, for brevity. "Other resources" could also be read as "the rest of the resources". Resource refers to network resources requested by the browser. */ + otherValue: 'Other resources', /** The name of the metric that marks the time at which the first text or image is painted by the browser. Shown to users as the label for the numeric metric value. Ideally fits within a ~40 character limit. */ firstContentfulPaintMetric: 'First Contentful Paint', /** The name of the metric that marks when the page has displayed content and the CPU is not busy executing the page's scripts. Shown to users as the label for the numeric metric value. Ideally fits within a ~40 character limit. */ diff --git a/lighthouse-core/test/audits/third-party-facades-test.js b/lighthouse-core/test/audits/third-party-facades-test.js index 6a9c135d796e..d2457298e05c 100644 --- a/lighthouse-core/test/audits/third-party-facades-test.js +++ b/lighthouse-core/test/audits/third-party-facades-test.js @@ -280,6 +280,62 @@ describe('Third party facades audit', () => { ]); }); + it('condenses items under 1KB', async () => { + const artifacts = { + devtoolsLogs: { + defaultPass: networkRecordsToDevtoolsLog([ + resourceEntry(100, 101, 102, 2000, 'https://example.com'), + intercomProductEntry(200, 201, 202, 4000, '1'), + intercomResourceEntry(300, 301, 302, 2000, 'a'), + intercomResourceEntry(310, 311, 312, 800, 'b'), + intercomResourceEntry(320, 321, 322, 0, 'c'), + ]), + }, + traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, + URL: {finalUrl: 'https://example.com'}, + }; + + const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; + const results = await ThirdPartyFacades.audit(artifacts, {computedCache: new Map(), settings}); + expect(results.details.items).toMatchObject([ + { + transferSize: 6800, + blockingTime: 0, + subItems: { + type: 'subitems', + items: [ + { + url: 'https://widget.intercom.io/widget/1', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 4000, + firstStartTime: 200, + firstContentAvailable: 201, + }, + { + url: 'https://js.intercomcdn.com/frame-modern.a.js', + mainThreadTime: 0, + blockingTime: 0, + transferSize: 2000, + firstStartTime: 300, + firstContentAvailable: 301, + }, + { + url: { + formattedDefault: 'Other resources', + }, + mainThreadTime: 0, + blockingTime: 0, + transferSize: 800, + firstStartTime: 0, + firstContentAvailable: 0, + }, + ], + }, + }, + ]); + }); + it('does not report first party resources', async () => { const artifacts = { devtoolsLogs: { @@ -482,27 +538,13 @@ describe('Third party facades audit', () => { }, { blockingTime: 0, - firstContentAvailable: 47787.641538, - firstStartTime: 47786.499527, - mainThreadTime: 0, - transferSize: 818, - url: 'https://vimeo.com/ablincoln/vuid?pid=a88cdaf56540a693f597632ffeeaf6a38f56542a1600197631', - }, - { - blockingTime: 0, - firstContentAvailable: 47786.70353599999, - firstStartTime: 47786.608785, - mainThreadTime: 0, - transferSize: 110, - url: 'https://fresnel.vimeocdn.com/add/player-stats?beacon=1&session-id=a88cdaf56540a693f597632ffeeaf6a38f56542a1600197631', - }, - { - blockingTime: 0, - firstContentAvailable: 47786.06986, - firstStartTime: 47786.069794, + firstContentAvailable: 0, + firstStartTime: 0, mainThreadTime: 0, - transferSize: 0, - url: 'http://player.vimeo.com/video/336812660', + transferSize: 928, + url: { + formattedDefault: 'Other resources', + }, }, ], type: 'subitems', From 8ae660866a4556d5f864610e7d4bfaaf16326ee3 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 6 Oct 2020 17:10:31 -0400 Subject: [PATCH 58/82] use entire entity --- lighthouse-core/audits/third-party-facades.js | 143 +++--------------- lighthouse-core/audits/third-party-summary.js | 17 +-- .../test/audits/third-party-facades-test.js | 106 ------------- .../test/audits/third-party-summary-test.js | 4 - 4 files changed, 26 insertions(+), 244 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index f026c189c445..a012904edcf3 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -69,27 +69,14 @@ const CATEGORY_UI_MAP = { 'social': UIStrings.categorySocial, }; -/** @type {Record} */ -const DEFERRABLE_PRODUCT_FIRST_RESOURCE = { - 'Facebook Messenger Customer Chat': /connect\.facebook.net\/.*\/sdk\/xfbml\.customerchat\.js/, - 'YouTube Embedded Player': /youtube\.com\/embed\//, - 'Help Scout Beacon': /beacon-v2\.helpscout\.net/, - 'Vimeo Embedded Player': /player\.vimeo\.com\/video\//, - 'Drift Live Chat': /js\.driftt\.com\/include\/.*\/.*\.js/, - 'Intercom Widget': /widget\.intercom\.io\/widget\/.*/, -}; - /** @typedef {import("third-party-web").IEntity} ThirdPartyEntity */ /** @typedef {import("third-party-web").IProduct} ThirdPartyProduct*/ /** @typedef {import("third-party-web").IFacade} ThirdPartyFacade*/ /** @typedef {{ * product: ThirdPartyProduct, - * startOfProductRequests: number, - * transferSize: number, - * blockingTime: number, - * urlSummaries: Map - * }} FacadableProductSummary + * entity: ThirdPartyEntity, + * }} FacadableProduct */ class ThirdPartyFacades extends Audit { @@ -107,19 +94,7 @@ class ThirdPartyFacades extends Audit { } /** - * @param {string} url - * @return {string[]} - */ - static firstResourceProductNames(url) { - const productNames = []; - for (const [name, regex] of Object.entries(DEFERRABLE_PRODUCT_FIRST_RESOURCE)) { - if (regex.test(url)) productNames.push(name); - } - return productNames; - } - - /** - * @param {(ThirdPartySummary.Summary & {url: string | LH.IcuMessage})[]} items + * @param {(ThirdPartySummary.URLSummary & {url: string | LH.IcuMessage})[]} items */ static condenseItems(items) { const splitIndex = items.findIndex((item) => item.transferSize < 1000); @@ -129,24 +104,20 @@ class ThirdPartyFacades extends Audit { const finalItem = remainder.reduce((result, item) => { result.transferSize += item.transferSize; result.blockingTime += item.blockingTime; - result.mainThreadTime += item.mainThreadTime; return result; }); finalItem.url = str_(i18n.UIStrings.otherValue); - finalItem.firstStartTime = finalItem.firstContentAvailable = 0; items.push(finalItem); } /** * @param {Map} byURL * @param {ThirdPartyEntity | undefined} mainEntity - * @return {FacadableProductSummary[]} + * @return {FacadableProduct[]} */ - static getFacadableProductSummaries(byURL, mainEntity) { - /** @type {Map>} */ - const entitySummaries = new Map(); - - // The first pass finds all requests to products that have a facade. + static getFacadableProducts(byURL, mainEntity) { + /** @type {Map} */ + const facadableProductMap = new Map(); for (const url of byURL.keys()) { const entity = thirdPartyWeb.getEntity(url); if (!entity || thirdPartyWeb.isFirstParty(url, mainEntity)) continue; @@ -154,81 +125,11 @@ class ThirdPartyFacades extends Audit { const product = thirdPartyWeb.getProduct(url); if (!product || !product.facades || !product.facades.length) continue; - /** @type {Map} */ - const productSummaries = entitySummaries.get(entity.name) || new Map(); - if (productSummaries.has(product.name)) continue; - - productSummaries.set(product.name, { - product, - transferSize: 0, - blockingTime: 0, - startOfProductRequests: Infinity, - urlSummaries: new Map(), - }); - entitySummaries.set(entity.name, productSummaries); + if (facadableProductMap.has(product.name)) continue; + facadableProductMap.set(product.name, {product, entity}); } - // The second pass finds the first request for any products found in the first pass. - for (const [url, urlSummary] of byURL) { - const entity = thirdPartyWeb.getEntity(url); - if (!entity || thirdPartyWeb.isFirstParty(url, mainEntity)) continue; - - const productSummaries = entitySummaries.get(entity.name); - if (!productSummaries) continue; - - const productNames = this.firstResourceProductNames(url); - if (!productNames.length) continue; - - for (const productName of productNames) { - const productSummary = productSummaries.get(productName); - if (!productSummary) continue; - - productSummary.urlSummaries.set(url, urlSummary); - productSummary.transferSize += urlSummary.transferSize; - productSummary.blockingTime += urlSummary.blockingTime; - - // This is the time the product resource is fetched. - // Any resources of the same entity fetched after this point are considered as part of this product. - productSummary.startOfProductRequests - = Math.min(productSummary.startOfProductRequests, urlSummary.firstContentAvailable); - - productSummaries.set(productName, productSummary); - } - entitySummaries.set(entity.name, productSummaries); - } - - // The third pass finds all other resources belonging to one of the products found above. - for (const [url, urlSummary] of byURL) { - const entity = thirdPartyWeb.getEntity(url); - if (!entity || thirdPartyWeb.isFirstParty(url, mainEntity)) continue; - - // The first resource was already counted. - if (this.firstResourceProductNames(url).length) continue; - - const productSummaries = entitySummaries.get(entity.name); - if (!productSummaries) continue; - - // If the url does not have a facade but one or more products on its entity do, - // we still want to record this url because it was probably fetched by a product with a facade. - for (const productSummary of productSummaries.values()) { - if (urlSummary.firstStartTime < productSummary.startOfProductRequests) continue; - productSummary.urlSummaries.set(url, urlSummary); - productSummary.transferSize += urlSummary.transferSize; - productSummary.blockingTime += urlSummary.blockingTime; - } - - entitySummaries.set(entity.name, productSummaries); - } - - const allProductSummaries = []; - for (const productSummaries of entitySummaries.values()) { - for (const productSummary of productSummaries.values()) { - // Ignore any product where a first request could not be found. - if (productSummary.startOfProductRequests === Infinity) continue; - allProductSummaries.push(productSummary); - } - } - return allProductSummaries; + return Array.from(facadableProductMap.values()); } /** @@ -246,14 +147,13 @@ class ThirdPartyFacades extends Audit { const tasks = await MainThreadTasks.request(trace, context); const multiplier = settings.throttlingMethod === 'simulate' ? settings.throttling.cpuSlowdownMultiplier : 1; - const thirdPartySummaries = ThirdPartySummary.getSummaries(networkRecords, tasks, multiplier); - const productSummaries - = ThirdPartyFacades.getFacadableProductSummaries(thirdPartySummaries.byURL, mainEntity); + const summaries = ThirdPartySummary.getSummaries(networkRecords, tasks, multiplier); + const facadableProducts + = ThirdPartyFacades.getFacadableProducts(summaries.byURL, mainEntity); /** @type {LH.Audit.Details.TableItem[]} */ const results = []; - for (const productSummary of productSummaries) { - const product = productSummary.product; + for (const {product, entity} of facadableProducts) { const categoryTemplate = CATEGORY_UI_MAP[product.categories[0]]; let productWithCategory; @@ -265,16 +165,21 @@ class ThirdPartyFacades extends Audit { productWithCategory = product.name; } - const items = Array.from(productSummary.urlSummaries) - .map(([url, urlStats]) => { - return {url, ...urlStats}; + const urls = summaries.urls.get(entity); + const entitySummary = summaries.byEntity.get(entity); + if (!urls || !entitySummary) continue; + + const items = Array.from(urls) + .map((url) => { + const urlStats = summaries.byURL.get(url); + return /** @type {ThirdPartySummary.URLSummary} */ ({url, ...urlStats}); }) .sort((a, b) => b.transferSize - a.transferSize); this.condenseItems(items); results.push({ product: productWithCategory, - transferSize: productSummary.transferSize, - blockingTime: productSummary.blockingTime, + transferSize: entitySummary.transferSize, + blockingTime: entitySummary.blockingTime, subItems: {type: 'subitems', items}, }); } diff --git a/lighthouse-core/audits/third-party-summary.js b/lighthouse-core/audits/third-party-summary.js index 5f71b648cb16..ce31e2559af8 100644 --- a/lighthouse-core/audits/third-party-summary.js +++ b/lighthouse-core/audits/third-party-summary.js @@ -41,8 +41,6 @@ const PASS_THRESHOLD_IN_MS = 250; * @property {number} mainThreadTime * @property {number} transferSize * @property {number} blockingTime - * @property {number} firstStartTime Start time of the first network request. - * @property {number} firstContentAvailable First time when content is available. If that time is unavailable, use end time. */ /** @@ -103,18 +101,8 @@ class ThirdPartySummary extends Audit { const defaultSummary = {mainThreadTime: 0, blockingTime: 0, transferSize: 0}; for (const request of networkRecords) { - const urlSummary = byURL.get(request.url) || - {...defaultSummary, firstStartTime: Infinity, firstContentAvailable: Infinity}; + const urlSummary = byURL.get(request.url) || {...defaultSummary}; urlSummary.transferSize += request.transferSize; - urlSummary.firstStartTime = Math.min(urlSummary.firstStartTime, request.startTime); - if (request.timing) { - const receiveHeadersEndTime = request.startTime + request.timing.receiveHeadersEnd / 1000; - urlSummary.firstContentAvailable - = Math.min(urlSummary.firstContentAvailable, receiveHeadersEndTime); - } else { - urlSummary.firstContentAvailable - = Math.min(urlSummary.firstContentAvailable, request.endTime); - } byURL.set(request.url, urlSummary); } @@ -123,8 +111,7 @@ class ThirdPartySummary extends Audit { for (const task of mainThreadTasks) { const attributableURL = BootupTime.getAttributableURLForTask(task, jsURLs); - const urlSummary = byURL.get(attributableURL) || - {...defaultSummary, firstStartTime: Infinity, firstContentAvailable: Infinity}; + const urlSummary = byURL.get(attributableURL) || {...defaultSummary}; const taskDuration = task.selfTime * cpuMultiplier; // The amount of time spent on main thread is the sum of all durations. urlSummary.mainThreadTime += taskDuration; diff --git a/lighthouse-core/test/audits/third-party-facades-test.js b/lighthouse-core/test/audits/third-party-facades-test.js index d2457298e05c..2273077979a2 100644 --- a/lighthouse-core/test/audits/third-party-facades-test.js +++ b/lighthouse-core/test/audits/third-party-facades-test.js @@ -81,16 +81,12 @@ describe('Third party facades audit', () => { mainThreadTime: 0, blockingTime: 0, transferSize: 8000, - firstStartTime: 300, - firstContentAvailable: 301, }, { url: 'https://widget.intercom.io/widget/1', mainThreadTime: 0, blockingTime: 0, transferSize: 4000, - firstStartTime: 200, - firstContentAvailable: 201, }, ], }, @@ -133,16 +129,12 @@ describe('Third party facades audit', () => { mainThreadTime: 0, blockingTime: 0, transferSize: 8000, - firstStartTime: 300, - firstContentAvailable: 301, }, { url: 'https://widget.intercom.io/widget/1', mainThreadTime: 0, blockingTime: 0, transferSize: 4000, - firstStartTime: 200, - firstContentAvailable: 201, }, ], }, @@ -158,16 +150,12 @@ describe('Third party facades audit', () => { mainThreadTime: 0, blockingTime: 0, transferSize: 7000, - firstStartTime: 310, - firstContentAvailable: 311, }, { url: 'https://www.youtube.com/embed/2', mainThreadTime: 0, blockingTime: 0, transferSize: 3000, - firstStartTime: 210, - firstContentAvailable: 211, }, ], }, @@ -209,70 +197,12 @@ describe('Third party facades audit', () => { mainThreadTime: 0, blockingTime: 0, transferSize: 8000, - firstStartTime: 300, - firstContentAvailable: 301, }, { url: 'https://widget.intercom.io/widget/1', mainThreadTime: 0, blockingTime: 0, transferSize: 4000, - firstStartTime: 200, - firstContentAvailable: 201, - }, - ], - }, - }, - ]); - }); - - it('uses receiveHeadersEnd to mark start of product requests', async () => { - const artifacts = { - devtoolsLogs: { - defaultPass: networkRecordsToDevtoolsLog([ - resourceEntry(100, 101, 102, 2000, 'https://example.com'), - intercomProductEntry(200, 205, 210, 4000, '1'), - // Starts between product's startTime and startTime + receiveHeadersEnd, so it is ignored - intercomResourceEntry(201, 206, 208, 8000, 'a'), - // Starts between product's startTime + receiveHeadersEnd and endTime, so it is included - intercomResourceEntry(206, 208, 215, 8000, 'b'), - // Starts past the cutoff but previous call to same url was before cutoff, so it is ignored - intercomResourceEntry(300, 301, 303, 8000, 'a'), - ]), - }, - traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, - URL: {finalUrl: 'https://example.com'}, - }; - - const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; - const results = await ThirdPartyFacades.audit(artifacts, {computedCache: new Map(), settings}); - - expect(results.score).toBe(0); - expect(results.displayValue).toBeDisplayString('1 facade alternative available'); - expect(results.details.items[0].product) - .toBeDisplayString('Intercom Widget (Customer Success)'); - expect(results.details.items).toMatchObject([ - { - transferSize: 12000, - blockingTime: 0, - subItems: { - type: 'subitems', - items: [ - { - url: 'https://js.intercomcdn.com/frame-modern.b.js', - mainThreadTime: 0, - blockingTime: 0, - transferSize: 8000, - firstStartTime: 206, - firstContentAvailable: 208, - }, - { - url: 'https://widget.intercom.io/widget/1', - mainThreadTime: 0, - blockingTime: 0, - transferSize: 4000, - firstStartTime: 200, - firstContentAvailable: 205, }, ], }, @@ -309,16 +239,12 @@ describe('Third party facades audit', () => { mainThreadTime: 0, blockingTime: 0, transferSize: 4000, - firstStartTime: 200, - firstContentAvailable: 201, }, { url: 'https://js.intercomcdn.com/frame-modern.a.js', mainThreadTime: 0, blockingTime: 0, transferSize: 2000, - firstStartTime: 300, - firstContentAvailable: 301, }, { url: { @@ -327,8 +253,6 @@ describe('Third party facades audit', () => { mainThreadTime: 0, blockingTime: 0, transferSize: 800, - firstStartTime: 0, - firstContentAvailable: 0, }, ], }, @@ -417,64 +341,48 @@ describe('Third party facades audit', () => { items: [ { blockingTime: 0, - firstContentAvailable: 47786.347774999995, - firstStartTime: 47786.326268, mainThreadTime: 0, transferSize: 459603, url: 'https://www.youtube.com/s/player/e0d83c30/player_ias.vflset/en_US/base.js', }, { blockingTime: 0, - firstContentAvailable: 47786.692717, - firstStartTime: 47786.569798, mainThreadTime: 0, transferSize: 66273, url: 'https://i.ytimg.com/vi/tgbNymZ7vqY/maxresdefault.jpg', }, { blockingTime: 0, - firstContentAvailable: 47786.436251, - firstStartTime: 47786.325979, mainThreadTime: 0, transferSize: 50213, url: 'https://www.youtube.com/s/player/e0d83c30/www-embed-player.vflset/www-embed-player.js', }, { blockingTime: 0, - firstContentAvailable: 47786.441221, - firstStartTime: 47786.324095, mainThreadTime: 0, transferSize: 46813, url: 'https://www.youtube.com/s/player/e0d83c30/www-player.css', }, { blockingTime: 0, - firstContentAvailable: 47786.580910000004, - firstStartTime: 47786.561199, mainThreadTime: 0, transferSize: 11477, url: 'https://www.youtube.com/s/player/e0d83c30/player_ias.vflset/en_US/embed.js', }, { blockingTime: 0, - firstContentAvailable: 47786.303873000004, - firstStartTime: 47786.066226, mainThreadTime: 0, transferSize: 10703, url: 'https://www.youtube.com/embed/tgbNymZ7vqY', }, { blockingTime: 0, - firstContentAvailable: 47786.414732000005, - firstStartTime: 47786.326585, mainThreadTime: 0, transferSize: 3191, url: 'https://www.youtube.com/yts/jsbin/fetch-polyfill-vfl6MZH8P/fetch-polyfill.js', }, { blockingTime: 0, - firstContentAvailable: 47786.679700999994, - firstStartTime: 47786.568895, mainThreadTime: 0, transferSize: 3077, url: 'https://yt3.ggpht.com/a/AATXAJxtCYVD65XPtigYUOad-Nd2v3EvnXnz__MkJrg=s68-c-k-c0x00ffffff-no-rj', @@ -490,56 +398,42 @@ describe('Third party facades audit', () => { items: [ { blockingTime: 0, - firstContentAvailable: 47786.422034999996, - firstStartTime: 47786.323843, mainThreadTime: 0, transferSize: 145772, url: 'https://f.vimeocdn.com/p/3.22.3/js/player.js', }, { blockingTime: 0, - firstContentAvailable: 47786.422311999995, - firstStartTime: 47786.324528, mainThreadTime: 0, transferSize: 17633, url: 'https://f.vimeocdn.com/p/3.22.3/css/player.css', }, { blockingTime: 0, - firstContentAvailable: 47786.634061000004, - firstStartTime: 47786.606134, mainThreadTime: 0, transferSize: 9313, url: 'https://i.vimeocdn.com/video/784397921.webp?mw=1200&mh=675&q=70', }, { blockingTime: 0, - firstContentAvailable: 47786.291588, - firstStartTime: 47786.074447, mainThreadTime: 0, transferSize: 8300, url: 'https://player.vimeo.com/video/336812660', }, { blockingTime: 0, - firstContentAvailable: 47786.47053, - firstStartTime: 47786.325692, mainThreadTime: 0, transferSize: 1474, url: 'https://f.vimeocdn.com/js_opt/modules/utils/vuid.min.js', }, { blockingTime: 0, - firstContentAvailable: 47786.417184000005, - firstStartTime: 47786.32147, mainThreadTime: 0, transferSize: 1075, url: 'https://i.vimeocdn.com/video/784397921.jpg?mw=80&q=85', }, { blockingTime: 0, - firstContentAvailable: 0, - firstStartTime: 0, mainThreadTime: 0, transferSize: 928, url: { diff --git a/lighthouse-core/test/audits/third-party-summary-test.js b/lighthouse-core/test/audits/third-party-summary-test.js index 4dab7079c676..42183b95ff84 100644 --- a/lighthouse-core/test/audits/third-party-summary-test.js +++ b/lighthouse-core/test/audits/third-party-summary-test.js @@ -43,8 +43,6 @@ describe('Third party summary', () => { blockingTime: 18.186999999999998, mainThreadTime: 127.15300000000003, transferSize: 30827, - firstStartTime: 225414.728913, - firstContentAvailable: 225414.940324, url: 'https://www.googletagmanager.com/gtm.js?id=GTM-Q5SW', }, ], @@ -66,8 +64,6 @@ describe('Third party summary', () => { blockingTime: 0, mainThreadTime: 55.246999999999986, transferSize: 12906, - firstStartTime: 225415.251281, - firstContentAvailable: 225415.469618, url: 'https://www.google-analytics.com/analytics.js', }, { From fda9948aeac6c968486da93309c3ccee8511e84c Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 6 Oct 2020 17:29:48 -0400 Subject: [PATCH 59/82] update sample --- lighthouse-core/lib/i18n/locales/en-US.json | 6 +++--- lighthouse-core/lib/i18n/locales/en-XL.json | 6 +++--- lighthouse-core/test/results/sample_v2.json | 4 +--- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/lighthouse-core/lib/i18n/locales/en-US.json b/lighthouse-core/lib/i18n/locales/en-US.json index 6e475c3203ac..e3caea69bf48 100644 --- a/lighthouse-core/lib/i18n/locales/en-US.json +++ b/lighthouse-core/lib/i18n/locales/en-US.json @@ -1352,9 +1352,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Reduce the impact of third-party code" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Other resources" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Minimize third-party usage" }, @@ -1739,6 +1736,9 @@ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": { "message": "Other" }, + "lighthouse-core/lib/i18n/i18n.js | otherValue": { + "message": "Other resources" + }, "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": { "message": "Script" }, diff --git a/lighthouse-core/lib/i18n/locales/en-XL.json b/lighthouse-core/lib/i18n/locales/en-XL.json index dd9ceef69b02..8884c27a961d 100644 --- a/lighthouse-core/lib/i18n/locales/en-XL.json +++ b/lighthouse-core/lib/i18n/locales/en-XL.json @@ -1352,9 +1352,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "R̂éd̂úĉé t̂h́ê ím̂ṕâćt̂ óf̂ t́ĥír̂d́-p̂ár̂t́ŷ ćôd́ê" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Ôt́ĥér̂ ŕêśôúr̂ćêś" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "M̂ín̂ím̂íẑé t̂h́îŕd̂-ṕâŕt̂ý ûśâǵê" }, @@ -1739,6 +1736,9 @@ "lighthouse-core/lib/i18n/i18n.js | otherResourceType": { "message": "Ôt́ĥér̂" }, + "lighthouse-core/lib/i18n/i18n.js | otherValue": { + "message": "Ôt́ĥér̂ ŕêśôúr̂ćêś" + }, "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": { "message": "Ŝćr̂íp̂t́" }, diff --git a/lighthouse-core/test/results/sample_v2.json b/lighthouse-core/test/results/sample_v2.json index 5850b154e811..c1b8806e99e5 100644 --- a/lighthouse-core/test/results/sample_v2.json +++ b/lighthouse-core/test/results/sample_v2.json @@ -1783,9 +1783,7 @@ "url": "http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js", "mainThreadTime": 90.36300000000001, "blockingTime": 22.918000000000006, - "transferSize": 30174, - "firstStartTime": 185607.195975, - "firstContentAvailable": 185607.822806 + "transferSize": 30174 } ] } From fd97c9e496a97bc4e4bb5bf4c7057f550e98bb1f Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 6 Oct 2020 17:45:00 -0400 Subject: [PATCH 60/82] updates sample again --- lighthouse-core/lib/i18n/locales/ar-XB.json | 3 --- lighthouse-core/lib/i18n/locales/ar.json | 3 --- lighthouse-core/lib/i18n/locales/bg.json | 3 --- lighthouse-core/lib/i18n/locales/ca.json | 3 --- lighthouse-core/lib/i18n/locales/cs.json | 3 --- lighthouse-core/lib/i18n/locales/da.json | 3 --- lighthouse-core/lib/i18n/locales/de.json | 3 --- lighthouse-core/lib/i18n/locales/el.json | 3 --- lighthouse-core/lib/i18n/locales/en-GB.json | 3 --- lighthouse-core/lib/i18n/locales/en-XA.json | 3 --- lighthouse-core/lib/i18n/locales/es-419.json | 3 --- lighthouse-core/lib/i18n/locales/es.json | 3 --- lighthouse-core/lib/i18n/locales/fi.json | 3 --- lighthouse-core/lib/i18n/locales/fil.json | 3 --- lighthouse-core/lib/i18n/locales/fr.json | 3 --- lighthouse-core/lib/i18n/locales/he.json | 3 --- lighthouse-core/lib/i18n/locales/hi.json | 3 --- lighthouse-core/lib/i18n/locales/hr.json | 3 --- lighthouse-core/lib/i18n/locales/hu.json | 3 --- lighthouse-core/lib/i18n/locales/id.json | 3 --- lighthouse-core/lib/i18n/locales/it.json | 3 --- lighthouse-core/lib/i18n/locales/ja.json | 3 --- lighthouse-core/lib/i18n/locales/ko.json | 3 --- lighthouse-core/lib/i18n/locales/lt.json | 3 --- lighthouse-core/lib/i18n/locales/lv.json | 3 --- lighthouse-core/lib/i18n/locales/nl.json | 3 --- lighthouse-core/lib/i18n/locales/no.json | 3 --- lighthouse-core/lib/i18n/locales/pl.json | 3 --- lighthouse-core/lib/i18n/locales/pt-PT.json | 3 --- lighthouse-core/lib/i18n/locales/pt.json | 3 --- lighthouse-core/lib/i18n/locales/ro.json | 3 --- lighthouse-core/lib/i18n/locales/ru.json | 3 --- lighthouse-core/lib/i18n/locales/sk.json | 3 --- lighthouse-core/lib/i18n/locales/sl.json | 3 --- lighthouse-core/lib/i18n/locales/sr-Latn.json | 3 --- lighthouse-core/lib/i18n/locales/sr.json | 3 --- lighthouse-core/lib/i18n/locales/sv.json | 3 --- lighthouse-core/lib/i18n/locales/ta.json | 3 --- lighthouse-core/lib/i18n/locales/te.json | 3 --- lighthouse-core/lib/i18n/locales/th.json | 3 --- lighthouse-core/lib/i18n/locales/tr.json | 3 --- lighthouse-core/lib/i18n/locales/uk.json | 3 --- lighthouse-core/lib/i18n/locales/vi.json | 3 --- lighthouse-core/lib/i18n/locales/zh-HK.json | 3 --- lighthouse-core/lib/i18n/locales/zh-TW.json | 3 --- lighthouse-core/lib/i18n/locales/zh.json | 3 --- 46 files changed, 138 deletions(-) diff --git a/lighthouse-core/lib/i18n/locales/ar-XB.json b/lighthouse-core/lib/i18n/locales/ar-XB.json index d232fd8a0eb8..71b10b027331 100644 --- a/lighthouse-core/lib/i18n/locales/ar-XB.json +++ b/lighthouse-core/lib/i18n/locales/ar-XB.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "‏‮Reduce‬‏ ‏‮the‬‏ ‏‮impact‬‏ ‏‮of‬‏ ‏‮third‬‏-‏‮party‬‏ ‏‮code‬‏" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "‏‮Other‬‏ ‏‮resources‬‏" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "‏‮Minimize‬‏ ‏‮third‬‏-‏‮party‬‏ ‏‮usage‬‏" }, diff --git a/lighthouse-core/lib/i18n/locales/ar.json b/lighthouse-core/lib/i18n/locales/ar.json index baca98c2ca3b..e4ea182d7e80 100644 --- a/lighthouse-core/lib/i18n/locales/ar.json +++ b/lighthouse-core/lib/i18n/locales/ar.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "تقليل تأثير رمز الجهة الخارجية" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "موارد أخرى" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "تقليل استخدام الرموز التابعة لجهات خارجية" }, diff --git a/lighthouse-core/lib/i18n/locales/bg.json b/lighthouse-core/lib/i18n/locales/bg.json index d246c31f4faf..2872129ca0cc 100644 --- a/lighthouse-core/lib/i18n/locales/bg.json +++ b/lighthouse-core/lib/i18n/locales/bg.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Намалете влиянието на кода от трети страни" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Други ресурси" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Сведете до минимум използването на код на трети страни" }, diff --git a/lighthouse-core/lib/i18n/locales/ca.json b/lighthouse-core/lib/i18n/locales/ca.json index ed658c077bae..8413e7e3a74a 100644 --- a/lighthouse-core/lib/i18n/locales/ca.json +++ b/lighthouse-core/lib/i18n/locales/ca.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Redueix l'impacte del codi de tercers" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Altres recursos" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Redueix l'ús de tercers" }, diff --git a/lighthouse-core/lib/i18n/locales/cs.json b/lighthouse-core/lib/i18n/locales/cs.json index 3dd5160a5443..2198330431da 100644 --- a/lighthouse-core/lib/i18n/locales/cs.json +++ b/lighthouse-core/lib/i18n/locales/cs.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Snižte vliv kódu třetích stran" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Jiné zdroje" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Minimalizujte používání kódu od třetích stran" }, diff --git a/lighthouse-core/lib/i18n/locales/da.json b/lighthouse-core/lib/i18n/locales/da.json index faf17e210e3e..aa73c53f8019 100644 --- a/lighthouse-core/lib/i18n/locales/da.json +++ b/lighthouse-core/lib/i18n/locales/da.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Reducer virkningen af tredjepartskode" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Andre ressourcer" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Minimer brugen af tredjeparter" }, diff --git a/lighthouse-core/lib/i18n/locales/de.json b/lighthouse-core/lib/i18n/locales/de.json index 05a7a9674ecc..8742c8aa3fb4 100644 --- a/lighthouse-core/lib/i18n/locales/de.json +++ b/lighthouse-core/lib/i18n/locales/de.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Die Auswirkungen von Drittanbieter-Code minimieren" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Weitere Ressourcen" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Drittanbieternutzung minimieren" }, diff --git a/lighthouse-core/lib/i18n/locales/el.json b/lighthouse-core/lib/i18n/locales/el.json index a933013ba231..089cdf25010e 100644 --- a/lighthouse-core/lib/i18n/locales/el.json +++ b/lighthouse-core/lib/i18n/locales/el.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Μείωση αντίκτυπου του κώδικα τρίτου μέρους" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Άλλοι πόροι" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Ελαχιστοποίηση χρήσης τρίτων μερών" }, diff --git a/lighthouse-core/lib/i18n/locales/en-GB.json b/lighthouse-core/lib/i18n/locales/en-GB.json index 9c8bc403ee42..30e917ae20a6 100644 --- a/lighthouse-core/lib/i18n/locales/en-GB.json +++ b/lighthouse-core/lib/i18n/locales/en-GB.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Reduce the impact of third-party code" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Other resources" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Minimise third-party usage" }, diff --git a/lighthouse-core/lib/i18n/locales/en-XA.json b/lighthouse-core/lib/i18n/locales/en-XA.json index 8c4429ab9912..442e2a3351b9 100644 --- a/lighthouse-core/lib/i18n/locales/en-XA.json +++ b/lighthouse-core/lib/i18n/locales/en-XA.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "[Ŕéðûçé ţĥé îmþåçţ öƒ ţĥîŕð-þåŕţý çöðé one two three four five six seven eight]" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "[Öţĥéŕ ŕéšöûŕçéš one two]" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "[Mîñîmîžé ţĥîŕð-þåŕţý ûšåĝé one two three]" }, diff --git a/lighthouse-core/lib/i18n/locales/es-419.json b/lighthouse-core/lib/i18n/locales/es-419.json index 005d0e27ae2a..41d92ed9ff1f 100644 --- a/lighthouse-core/lib/i18n/locales/es-419.json +++ b/lighthouse-core/lib/i18n/locales/es-419.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Reduce el impacto del código de terceros" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Otros recursos" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Minimiza el uso del código de terceros" }, diff --git a/lighthouse-core/lib/i18n/locales/es.json b/lighthouse-core/lib/i18n/locales/es.json index 7b369882cf59..4b396a671779 100644 --- a/lighthouse-core/lib/i18n/locales/es.json +++ b/lighthouse-core/lib/i18n/locales/es.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Reduce el impacto del código de terceros" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Otros recursos" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Reducir el uso de código de terceros" }, diff --git a/lighthouse-core/lib/i18n/locales/fi.json b/lighthouse-core/lib/i18n/locales/fi.json index 57669e3d9220..2bdd4b1c437a 100644 --- a/lighthouse-core/lib/i18n/locales/fi.json +++ b/lighthouse-core/lib/i18n/locales/fi.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Vähennä kolmannen osapuolen koodin vaikutusta" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Muut resurssit" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Minimoi kolmannen osapuolen käyttö" }, diff --git a/lighthouse-core/lib/i18n/locales/fil.json b/lighthouse-core/lib/i18n/locales/fil.json index 44363cd0fb74..e56209f94ff2 100644 --- a/lighthouse-core/lib/i18n/locales/fil.json +++ b/lighthouse-core/lib/i18n/locales/fil.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Bawasan ang epekto ng code ng third party" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Iba pang resource" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Bawasan ang paggamit ng third-party" }, diff --git a/lighthouse-core/lib/i18n/locales/fr.json b/lighthouse-core/lib/i18n/locales/fr.json index 88ac420b1192..e88f06f95322 100644 --- a/lighthouse-core/lib/i18n/locales/fr.json +++ b/lighthouse-core/lib/i18n/locales/fr.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Réduire l'impact du code tiers" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Autres ressources" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Réduire au maximum l'utilisation de code tiers" }, diff --git a/lighthouse-core/lib/i18n/locales/he.json b/lighthouse-core/lib/i18n/locales/he.json index 695616ecbc4b..609901ded59a 100644 --- a/lighthouse-core/lib/i18n/locales/he.json +++ b/lighthouse-core/lib/i18n/locales/he.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "עליך להפחית את השפעת הקוד של צד שלישי" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "משאבים אחרים" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "צמצום השימוש בצדדים שלישיים" }, diff --git a/lighthouse-core/lib/i18n/locales/hi.json b/lighthouse-core/lib/i18n/locales/hi.json index 7f211e7da804..aff78a80dcfd 100644 --- a/lighthouse-core/lib/i18n/locales/hi.json +++ b/lighthouse-core/lib/i18n/locales/hi.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "तीसरे पक्ष के कोड का असर कम करें" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "अन्य संसाधन" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "तीसरे पक्ष के इस्तेमाल को कम करें" }, diff --git a/lighthouse-core/lib/i18n/locales/hr.json b/lighthouse-core/lib/i18n/locales/hr.json index 5cf304a3bd1f..28d0b9af9e36 100644 --- a/lighthouse-core/lib/i18n/locales/hr.json +++ b/lighthouse-core/lib/i18n/locales/hr.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Smanjite utjecaj koda trećih strana" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Ostali resursi" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Smanjenje upotrebe koda trećih strana" }, diff --git a/lighthouse-core/lib/i18n/locales/hu.json b/lighthouse-core/lib/i18n/locales/hu.json index c444a9df3368..12d20965b89e 100644 --- a/lighthouse-core/lib/i18n/locales/hu.json +++ b/lighthouse-core/lib/i18n/locales/hu.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Csökkentse a harmadik felek kódjai által kiváltott hatást" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Egyéb források" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Minimalizálja a harmadik felektől származó kódok használatát" }, diff --git a/lighthouse-core/lib/i18n/locales/id.json b/lighthouse-core/lib/i18n/locales/id.json index 77d36249c194..ec852e86ef4a 100644 --- a/lighthouse-core/lib/i18n/locales/id.json +++ b/lighthouse-core/lib/i18n/locales/id.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Kurangi dampak kode pihak ketiga" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Resource lainnya" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Meminimalkan penggunaan pihak ketiga" }, diff --git a/lighthouse-core/lib/i18n/locales/it.json b/lighthouse-core/lib/i18n/locales/it.json index 67d623daf5e4..856eae9d651c 100644 --- a/lighthouse-core/lib/i18n/locales/it.json +++ b/lighthouse-core/lib/i18n/locales/it.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Riduci l'impatto del codice di terze parti" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Altre risorse" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Riduci al minimo l'utilizzo di codice di terze parti" }, diff --git a/lighthouse-core/lib/i18n/locales/ja.json b/lighthouse-core/lib/i18n/locales/ja.json index 64b7702de073..db9cee8a696c 100644 --- a/lighthouse-core/lib/i18n/locales/ja.json +++ b/lighthouse-core/lib/i18n/locales/ja.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "第三者コードの影響を抑えてください" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "その他のリソース" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "第三者の使用の最小化" }, diff --git a/lighthouse-core/lib/i18n/locales/ko.json b/lighthouse-core/lib/i18n/locales/ko.json index 6c21fd36d1ab..ce128bb5faaa 100644 --- a/lighthouse-core/lib/i18n/locales/ko.json +++ b/lighthouse-core/lib/i18n/locales/ko.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "타사 코드의 영향을 줄임" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "기타 리소스" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "타사 사용량 최소화" }, diff --git a/lighthouse-core/lib/i18n/locales/lt.json b/lighthouse-core/lib/i18n/locales/lt.json index ae14d65eb532..298d7ad58343 100644 --- a/lighthouse-core/lib/i18n/locales/lt.json +++ b/lighthouse-core/lib/i18n/locales/lt.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Sumažina trečiosios šalies kodo poveikį" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Kiti ištekliai" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Trečiųjų šalių kodo naudojimo sumažinimas" }, diff --git a/lighthouse-core/lib/i18n/locales/lv.json b/lighthouse-core/lib/i18n/locales/lv.json index 25c21a355151..37f89386a164 100644 --- a/lighthouse-core/lib/i18n/locales/lv.json +++ b/lighthouse-core/lib/i18n/locales/lv.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Samaziniet trešo pušu koda ietekmi" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Citi resursi" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Samaziniet trešās puses koda lietojumu" }, diff --git a/lighthouse-core/lib/i18n/locales/nl.json b/lighthouse-core/lib/i18n/locales/nl.json index 3be33ab0257b..71b813835f51 100644 --- a/lighthouse-core/lib/i18n/locales/nl.json +++ b/lighthouse-core/lib/i18n/locales/nl.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "De impact van code van derden beperken" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Andere bronnen" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Gebruik door derden minimaliseren" }, diff --git a/lighthouse-core/lib/i18n/locales/no.json b/lighthouse-core/lib/i18n/locales/no.json index a79e1252424d..99dd89f6c86e 100644 --- a/lighthouse-core/lib/i18n/locales/no.json +++ b/lighthouse-core/lib/i18n/locales/no.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Reduser innvirkningen av tredjepartskode" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Andre ressurser" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Minimer bruken av tredjepartskode" }, diff --git a/lighthouse-core/lib/i18n/locales/pl.json b/lighthouse-core/lib/i18n/locales/pl.json index 27a03213939b..ac508a70bebb 100644 --- a/lighthouse-core/lib/i18n/locales/pl.json +++ b/lighthouse-core/lib/i18n/locales/pl.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Ogranicz wpływ kodu spoza witryny" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Inne zasoby" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Minimalizacja wykorzystania kodu zewnętrznego" }, diff --git a/lighthouse-core/lib/i18n/locales/pt-PT.json b/lighthouse-core/lib/i18n/locales/pt-PT.json index f79f936baa8e..d73e45d9f55d 100644 --- a/lighthouse-core/lib/i18n/locales/pt-PT.json +++ b/lighthouse-core/lib/i18n/locales/pt-PT.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Reduza o impacto do código de terceiros" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Outros recursos" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Minimize a utilização de terceiros" }, diff --git a/lighthouse-core/lib/i18n/locales/pt.json b/lighthouse-core/lib/i18n/locales/pt.json index 632c60d23951..ca8d6b1f1701 100644 --- a/lighthouse-core/lib/i18n/locales/pt.json +++ b/lighthouse-core/lib/i18n/locales/pt.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Reduza o impacto de códigos de terceiros" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Outros recursos" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Reduzir o uso de terceiros" }, diff --git a/lighthouse-core/lib/i18n/locales/ro.json b/lighthouse-core/lib/i18n/locales/ro.json index db48d689fec6..15dfb26874df 100644 --- a/lighthouse-core/lib/i18n/locales/ro.json +++ b/lighthouse-core/lib/i18n/locales/ro.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Redu impactul codului de la terți" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Alte resurse" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Minimalizează folosirea terțelor părți" }, diff --git a/lighthouse-core/lib/i18n/locales/ru.json b/lighthouse-core/lib/i18n/locales/ru.json index 626c21516a4d..a07a2c149baa 100644 --- a/lighthouse-core/lib/i18n/locales/ru.json +++ b/lighthouse-core/lib/i18n/locales/ru.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Уменьшите влияние стороннего кода" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Другие ресурсы" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Уменьшение использования стороннего кода" }, diff --git a/lighthouse-core/lib/i18n/locales/sk.json b/lighthouse-core/lib/i18n/locales/sk.json index 51aae2e2a061..841093bd5607 100644 --- a/lighthouse-core/lib/i18n/locales/sk.json +++ b/lighthouse-core/lib/i18n/locales/sk.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Zníženie vplyvu kódu tretích strán" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Ďalšie zdroje" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Minimalizujte použitie riešení tretích strán" }, diff --git a/lighthouse-core/lib/i18n/locales/sl.json b/lighthouse-core/lib/i18n/locales/sl.json index 921495416d58..62f91b0f75ca 100644 --- a/lighthouse-core/lib/i18n/locales/sl.json +++ b/lighthouse-core/lib/i18n/locales/sl.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Zmanjšanje vpliva kode drugega ponudnika" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Drugi viri" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Zmanjšajte uporabo komponent drugih ponudnikov" }, diff --git a/lighthouse-core/lib/i18n/locales/sr-Latn.json b/lighthouse-core/lib/i18n/locales/sr-Latn.json index d16b733bad5b..695ced79d5d3 100644 --- a/lighthouse-core/lib/i18n/locales/sr-Latn.json +++ b/lighthouse-core/lib/i18n/locales/sr-Latn.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Smanjite uticaj koda nezavisnog dobavljača" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Ostali resursi" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Smanjite korišćenje sadržaja treće strane" }, diff --git a/lighthouse-core/lib/i18n/locales/sr.json b/lighthouse-core/lib/i18n/locales/sr.json index ff60dc7f7fb2..687a76dfeb90 100644 --- a/lighthouse-core/lib/i18n/locales/sr.json +++ b/lighthouse-core/lib/i18n/locales/sr.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Смањите утицај кода независног добављача" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Остали ресурси" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Смањите коришћење садржаја треће стране" }, diff --git a/lighthouse-core/lib/i18n/locales/sv.json b/lighthouse-core/lib/i18n/locales/sv.json index 0a5d14ad6187..415f8a860976 100644 --- a/lighthouse-core/lib/i18n/locales/sv.json +++ b/lighthouse-core/lib/i18n/locales/sv.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Minska påverkan från tredjepartskod" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Övriga resurser" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Minimera användning av tredjepartskod" }, diff --git a/lighthouse-core/lib/i18n/locales/ta.json b/lighthouse-core/lib/i18n/locales/ta.json index da1b0e47f83f..ea70aa5fdb33 100644 --- a/lighthouse-core/lib/i18n/locales/ta.json +++ b/lighthouse-core/lib/i18n/locales/ta.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "மூன்றாம் தரப்புக் குறியீட்டின் பாதிப்பைக் குறைக்கவும்" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "இதர மூலங்கள்" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "மூன்றாம் தரப்பு உபயோகத்தைக் குறைத்தல்" }, diff --git a/lighthouse-core/lib/i18n/locales/te.json b/lighthouse-core/lib/i18n/locales/te.json index 8cb09bd0cdef..3963baa89834 100644 --- a/lighthouse-core/lib/i18n/locales/te.json +++ b/lighthouse-core/lib/i18n/locales/te.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "మూడవ పక్షం కోడ్ ప్రభావాన్ని తగ్గించండి" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "ఇతర రిసోర్స్‌లు" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "మూడవ పక్ష వినియోగాన్ని కనీస స్థాయికి తగ్గించండి" }, diff --git a/lighthouse-core/lib/i18n/locales/th.json b/lighthouse-core/lib/i18n/locales/th.json index c331ec26d054..c791a95fa08f 100644 --- a/lighthouse-core/lib/i18n/locales/th.json +++ b/lighthouse-core/lib/i18n/locales/th.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "ลดผลกระทบจากโค้ดของบุคคลที่สาม" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "ทรัพยากรอื่นๆ" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "ลดการใช้ของบุคคลที่สาม" }, diff --git a/lighthouse-core/lib/i18n/locales/tr.json b/lighthouse-core/lib/i18n/locales/tr.json index 656317f7017e..b92edfb9a28a 100644 --- a/lighthouse-core/lib/i18n/locales/tr.json +++ b/lighthouse-core/lib/i18n/locales/tr.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Üçüncü taraf kodun etkisini azaltın" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Diğer kaynaklar" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Üçüncü taraf kullanımını en aza indirme" }, diff --git a/lighthouse-core/lib/i18n/locales/uk.json b/lighthouse-core/lib/i18n/locales/uk.json index 40ff486eb5d1..638be4bda9fb 100644 --- a/lighthouse-core/lib/i18n/locales/uk.json +++ b/lighthouse-core/lib/i18n/locales/uk.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Зменште вплив стороннього коду" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Інші ресурси" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Зменште використання стороннього коду" }, diff --git a/lighthouse-core/lib/i18n/locales/vi.json b/lighthouse-core/lib/i18n/locales/vi.json index cc3ca927f9c1..681765e04994 100644 --- a/lighthouse-core/lib/i18n/locales/vi.json +++ b/lighthouse-core/lib/i18n/locales/vi.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "Giảm mức ảnh hưởng của mã bên thứ ba" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "Tài nguyên khác" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "Giảm thiểu mức sử dụng của bên thứ ba" }, diff --git a/lighthouse-core/lib/i18n/locales/zh-HK.json b/lighthouse-core/lib/i18n/locales/zh-HK.json index 010312486425..d1db36ded41b 100644 --- a/lighthouse-core/lib/i18n/locales/zh-HK.json +++ b/lighthouse-core/lib/i18n/locales/zh-HK.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "減低第三方程式碼的影響" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "其他資源" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "減少第三方程式碼使用量" }, diff --git a/lighthouse-core/lib/i18n/locales/zh-TW.json b/lighthouse-core/lib/i18n/locales/zh-TW.json index 777dfe394590..95da49c6fc8f 100644 --- a/lighthouse-core/lib/i18n/locales/zh-TW.json +++ b/lighthouse-core/lib/i18n/locales/zh-TW.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "降低第三方程式碼的影響" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "其他資源" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "盡量減少第三方程式碼的使用量" }, diff --git a/lighthouse-core/lib/i18n/locales/zh.json b/lighthouse-core/lib/i18n/locales/zh.json index 23ddc204bc68..5a7a43f6e555 100644 --- a/lighthouse-core/lib/i18n/locales/zh.json +++ b/lighthouse-core/lib/i18n/locales/zh.json @@ -1325,9 +1325,6 @@ "lighthouse-core/audits/third-party-summary.js | failureTitle": { "message": "降低第三方代码的影响" }, - "lighthouse-core/audits/third-party-summary.js | otherValue": { - "message": "其他资源" - }, "lighthouse-core/audits/third-party-summary.js | title": { "message": "尽量减少第三方使用" }, From 572a4e3963d5323202ab2d3a070da5459b05cc3c Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 6 Oct 2020 17:45:14 -0400 Subject: [PATCH 61/82] small nit --- lighthouse-core/audits/third-party-facades.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index a012904edcf3..55840d6f8c7c 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -94,7 +94,7 @@ class ThirdPartyFacades extends Audit { } /** - * @param {(ThirdPartySummary.URLSummary & {url: string | LH.IcuMessage})[]} items + * @param {(ThirdPartySummary.URLSummary)[]} items */ static condenseItems(items) { const splitIndex = items.findIndex((item) => item.transferSize < 1000); From d4a792dc74c93ab45a67351fff5083b98ea27991 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 6 Oct 2020 17:45:41 -0400 Subject: [PATCH 62/82] small nit 2 --- lighthouse-core/audits/third-party-facades.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 55840d6f8c7c..c0f5ccb2f6bd 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -94,7 +94,7 @@ class ThirdPartyFacades extends Audit { } /** - * @param {(ThirdPartySummary.URLSummary)[]} items + * @param {ThirdPartySummary.URLSummary[]} items */ static condenseItems(items) { const splitIndex = items.findIndex((item) => item.transferSize < 1000); From 2bbaf1282d4551266f3fd20ae02c03282d77a92a Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Tue, 6 Oct 2020 18:11:54 -0400 Subject: [PATCH 63/82] update tpw --- lighthouse-core/lib/third-party-web.js | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/lighthouse-core/lib/third-party-web.js b/lighthouse-core/lib/third-party-web.js index 28e38be808da..e2336cf90233 100644 --- a/lighthouse-core/lib/third-party-web.js +++ b/lighthouse-core/lib/third-party-web.js @@ -11,31 +11,19 @@ const thirdPartyWeb = require('third-party-web/httparchive-nostats-subset'); /** @typedef {import("third-party-web").IProduct} ThirdPartyProduct */ /** - * `third-party-web` throws when the passed in string doesn't appear to have any domain whatsoever. - * We pass in some not-so-url-like things, so make the dependent-code simpler by making this call safe. * @param {string} url * @return {ThirdPartyEntity|undefined} */ function getEntity(url) { - try { - return thirdPartyWeb.getEntity(url); - } catch (_) { - return undefined; - } + return thirdPartyWeb.getEntity(url); } /** - * `third-party-web` throws when the passed in string doesn't appear to have any domain whatsoever. - * We pass in some not-so-url-like things, so make the dependent-code simpler by making this call safe. * @param {string} url * @return {ThirdPartyProduct|undefined} */ function getProduct(url) { - try { - return thirdPartyWeb.getProduct(url); - } catch (_) { - return undefined; - } + return thirdPartyWeb.getProduct(url); } /** From 93969790efa2ac498b8813a794a79afce61510e0 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 7 Oct 2020 11:26:28 -0400 Subject: [PATCH 64/82] remove entity summary --- lighthouse-core/audits/third-party-summary.js | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/lighthouse-core/audits/third-party-summary.js b/lighthouse-core/audits/third-party-summary.js index ce31e2559af8..c972eed5f1b9 100644 --- a/lighthouse-core/audits/third-party-summary.js +++ b/lighthouse-core/audits/third-party-summary.js @@ -43,13 +43,6 @@ const PASS_THRESHOLD_IN_MS = 250; * @property {number} blockingTime */ -/** - * @typedef EntitySummary - * @property {number} mainThreadTime - * @property {number} transferSize - * @property {number} blockingTime - */ - /** * @typedef URLSummary * @property {number} transferSize @@ -58,7 +51,7 @@ const PASS_THRESHOLD_IN_MS = 250; */ /** @typedef SummaryMaps - * @property {Map} byEntity Map of impact summaries for each entity. + * @property {Map} byEntity Map of impact summaries for each entity. * @property {Map} byURL Map of impact summaries for each URL. * @property {Map} urls Map of URLs under each entity. */ @@ -96,7 +89,7 @@ class ThirdPartySummary extends Audit { static getSummaries(networkRecords, mainThreadTasks, cpuMultiplier) { /** @type {Map} */ const byURL = new Map(); - /** @type {Map} */ + /** @type {Map} */ const byEntity = new Map(); const defaultSummary = {mainThreadTime: 0, blockingTime: 0, transferSize: 0}; @@ -149,7 +142,7 @@ class ThirdPartySummary extends Audit { /** * @param {ThirdPartyEntity} entity * @param {SummaryMaps} summaries - * @param {EntitySummary} stats + * @param {Summary} stats * @return {Array} */ static makeSubItems(entity, summaries, stats) { From 3a41dd135548a7745917cc95df8ebc9b74730d31 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Fri, 9 Oct 2020 11:25:50 -0400 Subject: [PATCH 65/82] nits --- lighthouse-core/audits/third-party-facades.js | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index c0f5ccb2f6bd..d9f494050099 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -14,6 +14,12 @@ * Facade: Placeholder for a product which looks likes the actual product and replaces itself with that product when the user needs it. */ +/** @typedef {import("third-party-web").IEntity} ThirdPartyEntity */ +/** @typedef {import("third-party-web").IProduct} ThirdPartyProduct*/ +/** @typedef {import("third-party-web").IFacade} ThirdPartyFacade*/ + +/** @typedef {{product: ThirdPartyProduct, entity: ThirdPartyEntity}} FacadableProduct */ + const Audit = require('./audit.js'); const i18n = require('../lib/i18n/i18n.js'); const thirdPartyWeb = require('../lib/third-party-web.js'); @@ -69,16 +75,6 @@ const CATEGORY_UI_MAP = { 'social': UIStrings.categorySocial, }; -/** @typedef {import("third-party-web").IEntity} ThirdPartyEntity */ -/** @typedef {import("third-party-web").IProduct} ThirdPartyProduct*/ -/** @typedef {import("third-party-web").IFacade} ThirdPartyFacade*/ - -/** @typedef {{ - * product: ThirdPartyProduct, - * entity: ThirdPartyEntity, - * }} FacadableProduct - */ - class ThirdPartyFacades extends Audit { /** * @return {LH.Audit.Meta} @@ -115,7 +111,7 @@ class ThirdPartyFacades extends Audit { * @param {ThirdPartyEntity | undefined} mainEntity * @return {FacadableProduct[]} */ - static getFacadableProducts(byURL, mainEntity) { + static getProductsWithFacade(byURL, mainEntity) { /** @type {Map} */ const facadableProductMap = new Map(); for (const url of byURL.keys()) { @@ -148,8 +144,8 @@ class ThirdPartyFacades extends Audit { const multiplier = settings.throttlingMethod === 'simulate' ? settings.throttling.cpuSlowdownMultiplier : 1; const summaries = ThirdPartySummary.getSummaries(networkRecords, tasks, multiplier); - const facadableProducts - = ThirdPartyFacades.getFacadableProducts(summaries.byURL, mainEntity); + const facadableProducts = + ThirdPartyFacades.getProductsWithFacade(summaries.byURL, mainEntity); /** @type {LH.Audit.Details.TableItem[]} */ const results = []; @@ -195,8 +191,8 @@ class ThirdPartyFacades extends Audit { const headings = [ /* eslint-disable max-len */ {key: 'product', itemType: 'text', subItemsHeading: {key: 'url', itemType: 'url'}, text: str_(UIStrings.columnProduct)}, - {key: 'transferSize', granularity: 1, itemType: 'bytes', subItemsHeading: {key: 'transferSize'}, text: str_(i18n.UIStrings.columnTransferSize)}, - {key: 'blockingTime', granularity: 1, itemType: 'ms', subItemsHeading: {key: 'blockingTime'}, text: str_(i18n.UIStrings.columnBlockingTime)}, + {key: 'transferSize', itemType: 'bytes', subItemsHeading: {key: 'transferSize'}, granularity: 1, text: str_(i18n.UIStrings.columnTransferSize)}, + {key: 'blockingTime', itemType: 'ms', subItemsHeading: {key: 'blockingTime'}, granularity: 1, text: str_(i18n.UIStrings.columnBlockingTime)}, /* eslint-enable max-len */ ]; From d207b8cbaa2eac4e2a3328c1705c51b556a4d804 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Fri, 9 Oct 2020 11:28:57 -0400 Subject: [PATCH 66/82] sort --- lighthouse-core/audits/third-party-facades.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index d9f494050099..2dd655161013 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -93,6 +93,7 @@ class ThirdPartyFacades extends Audit { * @param {ThirdPartySummary.URLSummary[]} items */ static condenseItems(items) { + items.sort((a, b) => b.transferSize - a.transferSize); const splitIndex = items.findIndex((item) => item.transferSize < 1000); if (splitIndex === -1) return; @@ -165,12 +166,10 @@ class ThirdPartyFacades extends Audit { const entitySummary = summaries.byEntity.get(entity); if (!urls || !entitySummary) continue; - const items = Array.from(urls) - .map((url) => { - const urlStats = summaries.byURL.get(url); - return /** @type {ThirdPartySummary.URLSummary} */ ({url, ...urlStats}); - }) - .sort((a, b) => b.transferSize - a.transferSize); + const items = Array.from(urls).map((url) => { + const urlStats = summaries.byURL.get(url); + return /** @type {ThirdPartySummary.URLSummary} */ ({url, ...urlStats}); + }); this.condenseItems(items); results.push({ product: productWithCategory, From d8a793f59ba249f78175d4b4762c7f1d6ec0825b Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 11 Nov 2020 11:39:42 -0500 Subject: [PATCH 67/82] comments --- lighthouse-core/audits/third-party-facades.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 2dd655161013..18a3600db9cc 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -29,14 +29,14 @@ const MainThreadTasks = require('../computed/main-thread-tasks.js'); const ThirdPartySummary = require('./third-party-summary.js'); const UIStrings = { - /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded with a facade alternative. This descriptive title is shown to users when no resources have facade alternatives available. Lazy loading means loading resources is deferred until they are needed. */ + /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded with a facade alternative. This descriptive title is shown to users when no resources have facade alternatives available. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ title: 'Lazy load third-party resources with facades', - /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded with a facade alternative. This descriptive title is shown to users when one or more third-party resources have available facade alternatives. Lazy loading means loading resources is deferred until they are needed. */ + /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded with a facade alternative. This descriptive title is shown to users when one or more third-party resources have available facade alternatives. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ failureTitle: 'Some third-party resources can be lazy loaded with a facade', - /** Description of a Lighthouse audit that identifies the third party code on the page that can be lazy loaded with a facade alternative. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. Lazy loading means loading resources is deferred until they are needed. */ - description: 'Some third party embeds can be lazy loaded. ' + + /** Description of a Lighthouse audit that identifies the third party code on the page that can be lazy loaded with a facade alternative. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ + description: 'Some third-party embeds can be lazy loaded. ' + 'Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).', - /** Summary text for the result of a Lighthouse audit that identifies the third party code on a web page that can be lazy loaded with a facade alternative. This text summarizes the number of lazy loading facades that can be used on the page. Lazy loading means loading resources is deferred until they are needed. */ + /** Summary text for the result of a Lighthouse audit that identifies the third party code on a web page that can be lazy loaded with a facade alternative. This text summarizes the number of lazy loading facades that can be used on the page. Lazy loading means resources are deferred until they are needed. */ displayValue: `{itemCount, plural, =1 {# facade alternative available} other {# facade alternatives available} @@ -90,6 +90,7 @@ class ThirdPartyFacades extends Audit { } /** + * Sort items by transfer size and combine any items <1KB into a single row. * @param {ThirdPartySummary.URLSummary[]} items */ static condenseItems(items) { @@ -155,10 +156,10 @@ class ThirdPartyFacades extends Audit { let productWithCategory; if (categoryTemplate) { - // Display product name with category next to it in the same column + // Display product name with category next to it in the same column. productWithCategory = str_(categoryTemplate, {productName: product.name}); } else { - // Just display product name if no category is found + // Just display product name if no category is found. productWithCategory = product.name; } From 7d5d2b7873ffb65bfa1adef50b97812d38383eb3 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 11 Nov 2020 11:41:35 -0500 Subject: [PATCH 68/82] more comment --- lighthouse-core/audits/third-party-facades.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 18a3600db9cc..2d6d92f53ad7 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -7,9 +7,9 @@ /** * @fileoverview Audit which identifies third-party code on the page which can be lazy loaded. - * The audit will recommend a facade alternative which is used to imitate the third party resource until it is needed. + * The audit will recommend a facade alternative which is used to imitate the third-party resource until it is needed. * - * Entity: Set of domains which are used by a company or product area to deliver third party resources + * Entity: Set of domains which are used by a company or product area to deliver third-party resources * Product: Specific piece of software belonging to an entity. Entities can have multiple products. * Facade: Placeholder for a product which looks likes the actual product and replaces itself with that product when the user needs it. */ @@ -33,10 +33,10 @@ const UIStrings = { title: 'Lazy load third-party resources with facades', /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded with a facade alternative. This descriptive title is shown to users when one or more third-party resources have available facade alternatives. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ failureTitle: 'Some third-party resources can be lazy loaded with a facade', - /** Description of a Lighthouse audit that identifies the third party code on the page that can be lazy loaded with a facade alternative. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ + /** Description of a Lighthouse audit that identifies the third-party code on the page that can be lazy loaded with a facade alternative. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ description: 'Some third-party embeds can be lazy loaded. ' + 'Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).', - /** Summary text for the result of a Lighthouse audit that identifies the third party code on a web page that can be lazy loaded with a facade alternative. This text summarizes the number of lazy loading facades that can be used on the page. Lazy loading means resources are deferred until they are needed. */ + /** Summary text for the result of a Lighthouse audit that identifies the third-party code on a web page that can be lazy loaded with a facade alternative. This text summarizes the number of lazy loading facades that can be used on the page. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ displayValue: `{itemCount, plural, =1 {# facade alternative available} other {# facade alternatives available} From 87b15d08435d9c2b9acc9972b4848502baa8b0a9 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 11 Nov 2020 11:44:22 -0500 Subject: [PATCH 69/82] rename rowOther --- lighthouse-core/lib/i18n/i18n.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-core/lib/i18n/i18n.js b/lighthouse-core/lib/i18n/i18n.js index 2a1f40cc34a8..4bc9256578bd 100644 --- a/lighthouse-core/lib/i18n/i18n.js +++ b/lighthouse-core/lib/i18n/i18n.js @@ -111,7 +111,7 @@ const UIStrings = { /** Label for a row in a data table; entries will be the total number and byte size of all third-party resources loaded by a web page. 'Third-party resources are items loaded from URLs that aren't controlled by the owner of the web page. */ thirdPartyResourceType: 'Third-party', /** Label used to identify a value in a table where many individual values are aggregated to a single value, for brevity. "Other resources" could also be read as "the rest of the resources". Resource refers to network resources requested by the browser. */ - otherValue: 'Other resources', + rowOther: 'Other resources', /** The name of the metric that marks the time at which the first text or image is painted by the browser. Shown to users as the label for the numeric metric value. Ideally fits within a ~40 character limit. */ firstContentfulPaintMetric: 'First Contentful Paint', /** The name of the metric that marks when the page has displayed content and the CPU is not busy executing the page's scripts. Shown to users as the label for the numeric metric value. Ideally fits within a ~40 character limit. */ From 02210e789e593b9cf300064d006c991ffd227bc8 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 11 Nov 2020 11:44:51 -0500 Subject: [PATCH 70/82] rename rowOther pt2 --- lighthouse-core/audits/third-party-facades.js | 2 +- lighthouse-core/audits/third-party-summary.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 2d6d92f53ad7..e3f5e70ebf7e 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -104,7 +104,7 @@ class ThirdPartyFacades extends Audit { result.blockingTime += item.blockingTime; return result; }); - finalItem.url = str_(i18n.UIStrings.otherValue); + finalItem.url = str_(i18n.UIStrings.rowOther); items.push(finalItem); } diff --git a/lighthouse-core/audits/third-party-summary.js b/lighthouse-core/audits/third-party-summary.js index c972eed5f1b9..55de0d9e1290 100644 --- a/lighthouse-core/audits/third-party-summary.js +++ b/lighthouse-core/audits/third-party-summary.js @@ -178,7 +178,7 @@ class ThirdPartySummary extends Audit { // we'll replace the tail entries with single remainder entry. items = items.slice(0, numSubItems); const remainder = { - url: str_(i18n.UIStrings.otherValue), + url: str_(i18n.UIStrings.rowOther), transferSize: stats.transferSize - subitemSummary.transferSize, blockingTime: stats.blockingTime - subitemSummary.blockingTime, }; From 86690f09d1f57dff1af7a888724e4178c94e0c76 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 11 Nov 2020 13:56:12 -0500 Subject: [PATCH 71/82] update condense function --- lighthouse-core/audits/third-party-facades.js | 15 +- .../test/audits/third-party-facades-test.js | 170 ++++++++++-------- 2 files changed, 111 insertions(+), 74 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index e3f5e70ebf7e..74b66adb6b4b 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -90,13 +90,18 @@ class ThirdPartyFacades extends Audit { } /** - * Sort items by transfer size and combine any items <1KB into a single row. + * Sort items by transfer size and combine small items into a single row. * @param {ThirdPartySummary.URLSummary[]} items */ static condenseItems(items) { items.sort((a, b) => b.transferSize - a.transferSize); - const splitIndex = items.findIndex((item) => item.transferSize < 1000); - if (splitIndex === -1) return; + + // Items <1KB are condensed. If all items are <1KB, condense all but the largest. + let splitIndex = items.findIndex((item) => item.transferSize < 1000) || 1; + // Show details for maximum of 5 items. + if (splitIndex === -1 || splitIndex > 5) splitIndex = 5; + // If there is only 1 item to condense, don't condense. + if (splitIndex >= items.length - 1) return; const remainder = items.splice(splitIndex); const finalItem = remainder.reduce((result, item) => { @@ -104,6 +109,10 @@ class ThirdPartyFacades extends Audit { result.blockingTime += item.blockingTime; return result; }); + + // If condensed row is still <1KB, don't show it. + if (finalItem.transferSize < 1000) return; + finalItem.url = str_(i18n.UIStrings.rowOther); items.push(finalItem); } diff --git a/lighthouse-core/test/audits/third-party-facades-test.js b/lighthouse-core/test/audits/third-party-facades-test.js index 2273077979a2..41bfd10bf667 100644 --- a/lighthouse-core/test/audits/third-party-facades-test.js +++ b/lighthouse-core/test/audits/third-party-facades-test.js @@ -210,56 +210,6 @@ describe('Third party facades audit', () => { ]); }); - it('condenses items under 1KB', async () => { - const artifacts = { - devtoolsLogs: { - defaultPass: networkRecordsToDevtoolsLog([ - resourceEntry(100, 101, 102, 2000, 'https://example.com'), - intercomProductEntry(200, 201, 202, 4000, '1'), - intercomResourceEntry(300, 301, 302, 2000, 'a'), - intercomResourceEntry(310, 311, 312, 800, 'b'), - intercomResourceEntry(320, 321, 322, 0, 'c'), - ]), - }, - traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, - URL: {finalUrl: 'https://example.com'}, - }; - - const settings = {throttlingMethod: 'simulate', throttling: {cpuSlowdownMultiplier: 4}}; - const results = await ThirdPartyFacades.audit(artifacts, {computedCache: new Map(), settings}); - expect(results.details.items).toMatchObject([ - { - transferSize: 6800, - blockingTime: 0, - subItems: { - type: 'subitems', - items: [ - { - url: 'https://widget.intercom.io/widget/1', - mainThreadTime: 0, - blockingTime: 0, - transferSize: 4000, - }, - { - url: 'https://js.intercomcdn.com/frame-modern.a.js', - mainThreadTime: 0, - blockingTime: 0, - transferSize: 2000, - }, - { - url: { - formattedDefault: 'Other resources', - }, - mainThreadTime: 0, - blockingTime: 0, - transferSize: 800, - }, - ], - }, - }, - ]); - }); - it('does not report first party resources', async () => { const artifacts = { devtoolsLogs: { @@ -372,20 +322,10 @@ describe('Third party facades audit', () => { { blockingTime: 0, mainThreadTime: 0, - transferSize: 10703, - url: 'https://www.youtube.com/embed/tgbNymZ7vqY', - }, - { - blockingTime: 0, - mainThreadTime: 0, - transferSize: 3191, - url: 'https://www.youtube.com/yts/jsbin/fetch-polyfill-vfl6MZH8P/fetch-polyfill.js', - }, - { - blockingTime: 0, - mainThreadTime: 0, - transferSize: 3077, - url: 'https://yt3.ggpht.com/a/AATXAJxtCYVD65XPtigYUOad-Nd2v3EvnXnz__MkJrg=s68-c-k-c0x00ffffff-no-rj', + transferSize: 16971, + url: { + formattedDefault: 'Other resources', + }, }, ], type: 'subitems', @@ -429,13 +369,7 @@ describe('Third party facades audit', () => { { blockingTime: 0, mainThreadTime: 0, - transferSize: 1075, - url: 'https://i.vimeocdn.com/video/784397921.jpg?mw=80&q=85', - }, - { - blockingTime: 0, - mainThreadTime: 0, - transferSize: 928, + transferSize: 2003, url: { formattedDefault: 'Other resources', }, @@ -447,4 +381,98 @@ describe('Third party facades audit', () => { ] ); }); + + describe('.condenseItems', () => { + it('basic case', () => { + const items = [ + {url: 'd', transferSize: 500, blockingTime: 5}, + {url: 'b', transferSize: 1000, blockingTime: 0}, + {url: 'c', transferSize: 500, blockingTime: 5}, + {url: 'e', transferSize: 500, blockingTime: 5}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + ]; + ThirdPartyFacades.condenseItems(items); + expect(items).toMatchObject([ + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'b', transferSize: 1000, blockingTime: 0}, + {url: {formattedDefault: 'Other resources'}, transferSize: 1500, blockingTime: 15}, + ]); + }); + + it('only shown top 5 items', () => { + const items = [ + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 5}, + {url: 'a', transferSize: 5000, blockingTime: 5}, + ]; + ThirdPartyFacades.condenseItems(items); + expect(items).toMatchObject([ + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: {formattedDefault: 'Other resources'}, transferSize: 10000, blockingTime: 10}, + ]); + }); + + it('hide condensed row if total transfer size <1KB', () => { + const items = [ + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'b', transferSize: 100, blockingTime: 0}, + {url: 'c', transferSize: 100, blockingTime: 0}, + ]; + ThirdPartyFacades.condenseItems(items); + expect(items).toMatchObject([ + {url: 'a', transferSize: 5000, blockingTime: 0}, + ]); + }); + + it('always show at least one item', () => { + const items = [ + {url: 'a', transferSize: 500, blockingTime: 0}, + {url: 'b', transferSize: 500, blockingTime: 0}, + {url: 'c', transferSize: 500, blockingTime: 0}, + ]; + ThirdPartyFacades.condenseItems(items); + expect(items).toMatchObject([ + {url: 'a', transferSize: 500, blockingTime: 0}, + {url: {formattedDefault: 'Other resources'}, transferSize: 1000, blockingTime: 0}, + ]); + }); + + it('single small item', () => { + const items = [ + {url: 'a', transferSize: 500, blockingTime: 0}, + ]; + ThirdPartyFacades.condenseItems(items); + expect(items).toMatchObject([ + {url: 'a', transferSize: 500, blockingTime: 0}, + ]); + }); + + it('do not condense if only one item to condense', () => { + const items = [ + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'c', transferSize: 500, blockingTime: 0}, + ]; + ThirdPartyFacades.condenseItems(items); + expect(items).toMatchObject([ + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'a', transferSize: 5000, blockingTime: 0}, + {url: 'c', transferSize: 500, blockingTime: 0}, + ]); + }); + }); }); From b90640aa62f461adab04cd0db851545fca91bbac Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 11 Nov 2020 14:21:23 -0500 Subject: [PATCH 72/82] join the dark side --- .../test/audits/third-party-facades-test.js | 63 +++++++------------ 1 file changed, 23 insertions(+), 40 deletions(-) diff --git a/lighthouse-core/test/audits/third-party-facades-test.js b/lighthouse-core/test/audits/third-party-facades-test.js index 41bfd10bf667..bebc45402477 100644 --- a/lighthouse-core/test/audits/third-party-facades-test.js +++ b/lighthouse-core/test/audits/third-party-facades-test.js @@ -15,36 +15,20 @@ const videoEmbedsTrace = require('../fixtures/traces/video-embeds-m84.json'); const videoEmbedsDevtolsLog = require('../fixtures/traces/video-embeds-m84.devtools.log.json'); const noThirdPartyTrace = require('../fixtures/traces/no-tracingstarted-m74.json'); -function resourceEntry(startTime, headerEndTime, endTime, transferSize, url) { - return { - url, - startTime, - endTime, - transferSize, - timing: { - receiveHeadersEnd: (headerEndTime - startTime) * 1000, - }, - }; +function intercomProductUrl(id) { + return `https://widget.intercom.io/widget/${id}`; } -function intercomProductEntry(startTime, headerEndTime, endTime, transferSize, id) { - const url = `https://widget.intercom.io/widget/${id}`; - return resourceEntry(startTime, headerEndTime, endTime, transferSize, url); +function intercomResourceUrl(id) { + return `https://js.intercomcdn.com/frame-modern.${id}.js`; } -function intercomResourceEntry(startTime, headerEndTime, endTime, transferSize, id) { - const url = `https://js.intercomcdn.com/frame-modern.${id}.js`; - return resourceEntry(startTime, headerEndTime, endTime, transferSize, url); +function youtubeProductUrl(id) { + return `https://www.youtube.com/embed/${id}`; } -function youtubeProductEntry(startTime, headerEndTime, endTime, transferSize, id) { - const url = `https://www.youtube.com/embed/${id}`; - return resourceEntry(startTime, headerEndTime, endTime, transferSize, url); -} - -function youtubeResourceEntry(startTime, headerEndTime, endTime, transferSize, id) { - const url = `https://i.ytimg.com/${id}/maxresdefault.jpg`; - return resourceEntry(startTime, headerEndTime, endTime, transferSize, url); +function youtubeResourceUrl(id) { + return `https://i.ytimg.com/${id}/maxresdefault.jpg`; } /* eslint-env jest */ @@ -53,9 +37,9 @@ describe('Third party facades audit', () => { const artifacts = { devtoolsLogs: { defaultPass: networkRecordsToDevtoolsLog([ - resourceEntry(100, 101, 102, 2000, 'https://example.com'), - intercomProductEntry(200, 201, 202, 4000, '1'), - intercomResourceEntry(300, 301, 302, 8000, 'a'), + {transferSize: 2000, url: 'https://example.com'}, + {transferSize: 4000, url: intercomProductUrl('1')}, + {transferSize: 8000, url: intercomResourceUrl('a')}, ]), }, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, @@ -98,11 +82,11 @@ describe('Third party facades audit', () => { const artifacts = { devtoolsLogs: { defaultPass: networkRecordsToDevtoolsLog([ - resourceEntry(100, 101, 102, 2000, 'https://example.com'), - intercomProductEntry(200, 201, 202, 4000, '1'), - youtubeProductEntry(210, 211, 212, 3000, '2'), - intercomResourceEntry(300, 301, 302, 8000, 'a'), - youtubeResourceEntry(310, 311, 312, 7000, 'b'), + {transferSize: 2000, url: 'https://example.com'}, + {transferSize: 4000, url: intercomProductUrl('1')}, + {transferSize: 3000, url: youtubeProductUrl('2')}, + {transferSize: 8000, url: intercomResourceUrl('a')}, + {transferSize: 7000, url: youtubeResourceUrl('b')}, ]), }, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, @@ -167,11 +151,10 @@ describe('Third party facades audit', () => { const artifacts = { devtoolsLogs: { defaultPass: networkRecordsToDevtoolsLog([ - resourceEntry(100, 101, 102, 2000, 'https://example.com'), - // The first product entry is used to mark the start of product requests - intercomProductEntry(200, 201, 202, 2000, '1'), - intercomResourceEntry(300, 301, 302, 8000, 'a'), - intercomProductEntry(400, 401, 402, 2000, '1'), + {transferSize: 2000, url: 'https://example.com'}, + {transferSize: 2000, url: intercomProductUrl('1')}, + {transferSize: 8000, url: intercomResourceUrl('a')}, + {transferSize: 2000, url: intercomProductUrl('1')}, ]), }, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, @@ -214,8 +197,8 @@ describe('Third party facades audit', () => { const artifacts = { devtoolsLogs: { defaultPass: networkRecordsToDevtoolsLog([ - resourceEntry(100, 101, 102, 2000, 'https://intercomcdn.com'), - intercomProductEntry(200, 201, 202, 4000, '1'), + {transferSize: 2000, url: 'https://intercomcdn.com'}, + {transferSize: 4000, url: intercomProductUrl('1')}, ]), }, traces: {defaultPass: createTestTrace({timeOrigin: 0, traceEnd: 2000})}, @@ -252,7 +235,7 @@ describe('Third party facades audit', () => { const artifacts = { devtoolsLogs: { defaultPass: networkRecordsToDevtoolsLog([ - resourceEntry(100, 101, 102, 2000, 'https://example.com'), + {transferSize: 2000, url: 'https://example.com'}, ]), }, traces: {defaultPass: noThirdPartyTrace}, From 9a534e30223e2df9c4ac4179806a846c3566f781 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 11 Nov 2020 14:25:44 -0500 Subject: [PATCH 73/82] rn other resources --- lighthouse-core/audits/third-party-facades.js | 2 +- lighthouse-core/audits/third-party-summary.js | 2 +- lighthouse-core/lib/i18n/i18n.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 74b66adb6b4b..ef2f1c3fb711 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -113,7 +113,7 @@ class ThirdPartyFacades extends Audit { // If condensed row is still <1KB, don't show it. if (finalItem.transferSize < 1000) return; - finalItem.url = str_(i18n.UIStrings.rowOther); + finalItem.url = str_(i18n.UIStrings.otherResourcesLabel); items.push(finalItem); } diff --git a/lighthouse-core/audits/third-party-summary.js b/lighthouse-core/audits/third-party-summary.js index 55de0d9e1290..8873913e420e 100644 --- a/lighthouse-core/audits/third-party-summary.js +++ b/lighthouse-core/audits/third-party-summary.js @@ -178,7 +178,7 @@ class ThirdPartySummary extends Audit { // we'll replace the tail entries with single remainder entry. items = items.slice(0, numSubItems); const remainder = { - url: str_(i18n.UIStrings.rowOther), + url: str_(i18n.UIStrings.otherResourcesLabel), transferSize: stats.transferSize - subitemSummary.transferSize, blockingTime: stats.blockingTime - subitemSummary.blockingTime, }; diff --git a/lighthouse-core/lib/i18n/i18n.js b/lighthouse-core/lib/i18n/i18n.js index 4bc9256578bd..4006d0be7ae5 100644 --- a/lighthouse-core/lib/i18n/i18n.js +++ b/lighthouse-core/lib/i18n/i18n.js @@ -111,7 +111,7 @@ const UIStrings = { /** Label for a row in a data table; entries will be the total number and byte size of all third-party resources loaded by a web page. 'Third-party resources are items loaded from URLs that aren't controlled by the owner of the web page. */ thirdPartyResourceType: 'Third-party', /** Label used to identify a value in a table where many individual values are aggregated to a single value, for brevity. "Other resources" could also be read as "the rest of the resources". Resource refers to network resources requested by the browser. */ - rowOther: 'Other resources', + otherResourcesLabel: 'Other resources', /** The name of the metric that marks the time at which the first text or image is painted by the browser. Shown to users as the label for the numeric metric value. Ideally fits within a ~40 character limit. */ firstContentfulPaintMetric: 'First Contentful Paint', /** The name of the metric that marks when the page has displayed content and the CPU is not busy executing the page's scripts. Shown to users as the label for the numeric metric value. Ideally fits within a ~40 character limit. */ From 11d2d6570ee580cac3cbebab61b333818da3aa63 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 11 Nov 2020 14:33:59 -0500 Subject: [PATCH 74/82] update translator comment --- lighthouse-core/audits/third-party-facades.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index ef2f1c3fb711..4ea848e18dcd 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -36,7 +36,7 @@ const UIStrings = { /** Description of a Lighthouse audit that identifies the third-party code on the page that can be lazy loaded with a facade alternative. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ description: 'Some third-party embeds can be lazy loaded. ' + 'Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).', - /** Summary text for the result of a Lighthouse audit that identifies the third-party code on a web page that can be lazy loaded with a facade alternative. This text summarizes the number of lazy loading facades that can be used on the page. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ + /** Summary text for the result of a Lighthouse audit that identifies the third-party code on a web page that can be lazy loaded with a facade alternative. This text summarizes the number of lazy loading facades that can be used on the page. */ displayValue: `{itemCount, plural, =1 {# facade alternative available} other {# facade alternatives available} From f97895b72ce4d2efb729ff0a0d0d976908fc8dec Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 11 Nov 2020 14:38:16 -0500 Subject: [PATCH 75/82] more translator comment updates --- lighthouse-core/audits/third-party-facades.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 4ea848e18dcd..bc89836d88dd 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -29,19 +29,19 @@ const MainThreadTasks = require('../computed/main-thread-tasks.js'); const ThirdPartySummary = require('./third-party-summary.js'); const UIStrings = { - /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded with a facade alternative. This descriptive title is shown to users when no resources have facade alternatives available. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ + /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded with a facade alternative. This descriptive title is shown to users when no resources have facade alternatives available. A facade is a lightweight component which looks like the desired resource. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ title: 'Lazy load third-party resources with facades', - /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded with a facade alternative. This descriptive title is shown to users when one or more third-party resources have available facade alternatives. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ + /** Title of a diagnostic audit that provides details about the third-party code on a web page that can be lazy loaded with a facade alternative. This descriptive title is shown to users when one or more third-party resources have available facade alternatives. A facade is a lightweight component which looks like the desired resource. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ failureTitle: 'Some third-party resources can be lazy loaded with a facade', - /** Description of a Lighthouse audit that identifies the third-party code on the page that can be lazy loaded with a facade alternative. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ + /** Description of a Lighthouse audit that identifies the third-party code on the page that can be lazy loaded with a facade alternative. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. A facade is a lightweight component which looks like the desired resource. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ description: 'Some third-party embeds can be lazy loaded. ' + 'Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).', - /** Summary text for the result of a Lighthouse audit that identifies the third-party code on a web page that can be lazy loaded with a facade alternative. This text summarizes the number of lazy loading facades that can be used on the page. */ + /** Summary text for the result of a Lighthouse audit that identifies the third-party code on a web page that can be lazy loaded with a facade alternative. This text summarizes the number of lazy loading facades that can be used on the page. A facade is a lightweight component which looks like the desired resource. */ displayValue: `{itemCount, plural, =1 {# facade alternative available} other {# facade alternatives available} }`, - /** Label for a table column that displays the name of the product that a URL is used for. A product is a piece of software used on the page. */ + /** Label for a table column that displays the name of the product that a URL is used for. The products in the column will be pieces of software used on the page, like the "YouTube Embedded Player" or the "Drift Live Chat" box. */ columnProduct: 'Product', /** * @description Template for a table entry that gives the name of a product which we categorize as video related. From cb279048fee9c10d9ceeb00ae7dc79682fe68158 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 11 Nov 2020 14:49:42 -0500 Subject: [PATCH 76/82] update comments --- lighthouse-core/audits/third-party-facades.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index bc89836d88dd..7650278c2841 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -91,6 +91,7 @@ class ThirdPartyFacades extends Audit { /** * Sort items by transfer size and combine small items into a single row. + * items will be condensed to maximum of 6 rows. * @param {ThirdPartySummary.URLSummary[]} items */ static condenseItems(items) { @@ -98,9 +99,9 @@ class ThirdPartyFacades extends Audit { // Items <1KB are condensed. If all items are <1KB, condense all but the largest. let splitIndex = items.findIndex((item) => item.transferSize < 1000) || 1; - // Show details for maximum of 5 items. + // Show details for top 5 items. if (splitIndex === -1 || splitIndex > 5) splitIndex = 5; - // If there is only 1 item to condense, don't condense. + // If there is only 1 item to condense, leave it as is. if (splitIndex >= items.length - 1) return; const remainder = items.splice(splitIndex); From b67a145be9e00a1d99cf64a15f42b2134e121e22 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 11 Nov 2020 14:50:23 -0500 Subject: [PATCH 77/82] update html --- lighthouse-cli/test/fixtures/perf/third-party.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-cli/test/fixtures/perf/third-party.html b/lighthouse-cli/test/fixtures/perf/third-party.html index 57ab91a4f85b..d060d1ac6f96 100644 --- a/lighthouse-cli/test/fixtures/perf/third-party.html +++ b/lighthouse-cli/test/fixtures/perf/third-party.html @@ -7,7 +7,7 @@ -
AAAAAAAAAAAAAAAAAAA
+
We need some content to have a valid FCP/LCP
From 1776f1e6cdc199f3d34fefcea8da144a91142482 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 11 Nov 2020 14:51:18 -0500 Subject: [PATCH 78/82] update smoke expectations --- .../test/smokehouse/test-definitions/perf/expectations.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js b/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js index 6e3a37deb6c7..12306e076609 100644 --- a/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js +++ b/lighthouse-cli/test/smokehouse/test-definitions/perf/expectations.js @@ -371,7 +371,7 @@ module.exports = [ subItems: { type: 'subitems', items: { - length: 8, + length: '>5', // We don't care exactly how many it has, just ensure we surface the subresources. }, }, }, From 1539de8bb26e6065a3324c5ec497dbb774c4216f Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 11 Nov 2020 14:52:33 -0500 Subject: [PATCH 79/82] update sample --- lighthouse-core/lib/i18n/locales/en-US.json | 8 ++++---- lighthouse-core/lib/i18n/locales/en-XL.json | 8 ++++---- lighthouse-core/test/results/sample_v2.json | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lighthouse-core/lib/i18n/locales/en-US.json b/lighthouse-core/lib/i18n/locales/en-US.json index e3caea69bf48..215d6fc31366 100644 --- a/lighthouse-core/lib/i18n/locales/en-US.json +++ b/lighthouse-core/lib/i18n/locales/en-US.json @@ -1329,7 +1329,7 @@ "message": "Product" }, "lighthouse-core/audits/third-party-facades.js | description": { - "message": "Some third party embeds can be lazy loaded. Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/)." + "message": "Some third-party embeds can be lazy loaded. Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/)." }, "lighthouse-core/audits/third-party-facades.js | displayValue": { "message": "{itemCount, plural,\n =1 {# facade alternative available}\n other {# facade alternatives available}\n }" @@ -1733,12 +1733,12 @@ "lighthouse-core/lib/i18n/i18n.js | ms": { "message": "{timeInMs, number, milliseconds} ms" }, + "lighthouse-core/lib/i18n/i18n.js | otherResourcesLabel": { + "message": "Other resources" + }, "lighthouse-core/lib/i18n/i18n.js | otherResourceType": { "message": "Other" }, - "lighthouse-core/lib/i18n/i18n.js | otherValue": { - "message": "Other resources" - }, "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": { "message": "Script" }, diff --git a/lighthouse-core/lib/i18n/locales/en-XL.json b/lighthouse-core/lib/i18n/locales/en-XL.json index 8884c27a961d..33c2e9860925 100644 --- a/lighthouse-core/lib/i18n/locales/en-XL.json +++ b/lighthouse-core/lib/i18n/locales/en-XL.json @@ -1329,7 +1329,7 @@ "message": "P̂ŕôd́ûćt̂" }, "lighthouse-core/audits/third-party-facades.js | description": { - "message": "Ŝóm̂é t̂h́îŕd̂ ṕâŕt̂ý êḿb̂éd̂ś ĉán̂ b́ê ĺâźŷ ĺôád̂éd̂. Ćôńŝíd̂ér̂ ŕêṕl̂áĉín̂ǵ t̂h́êḿ ŵít̂h́ â f́âćâd́ê ún̂t́îĺ t̂h́êý âŕê ŕêq́ûír̂éd̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/efficiently-load-third-party-javascript/)." + "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý êḿb̂éd̂ś ĉán̂ b́ê ĺâźŷ ĺôád̂éd̂. Ćôńŝíd̂ér̂ ŕêṕl̂áĉín̂ǵ t̂h́êḿ ŵít̂h́ â f́âćâd́ê ún̂t́îĺ t̂h́êý âŕê ŕêq́ûír̂éd̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/efficiently-load-third-party-javascript/)." }, "lighthouse-core/audits/third-party-facades.js | displayValue": { "message": "{itemCount, plural,\n =1 {# f̂áĉád̂é âĺt̂ér̂ńât́îv́ê áv̂áîĺâb́l̂é}\n other {# f̂áĉád̂é âĺt̂ér̂ńât́îv́êś âv́âíl̂áb̂ĺê}\n }" @@ -1733,12 +1733,12 @@ "lighthouse-core/lib/i18n/i18n.js | ms": { "message": "{timeInMs, number, milliseconds} m̂ś" }, + "lighthouse-core/lib/i18n/i18n.js | otherResourcesLabel": { + "message": "Ôt́ĥér̂ ŕêśôúr̂ćêś" + }, "lighthouse-core/lib/i18n/i18n.js | otherResourceType": { "message": "Ôt́ĥér̂" }, - "lighthouse-core/lib/i18n/i18n.js | otherValue": { - "message": "Ôt́ĥér̂ ŕêśôúr̂ćêś" - }, "lighthouse-core/lib/i18n/i18n.js | scriptResourceType": { "message": "Ŝćr̂íp̂t́" }, diff --git a/lighthouse-core/test/results/sample_v2.json b/lighthouse-core/test/results/sample_v2.json index c1b8806e99e5..e1640500895b 100644 --- a/lighthouse-core/test/results/sample_v2.json +++ b/lighthouse-core/test/results/sample_v2.json @@ -1798,7 +1798,7 @@ "third-party-facades": { "id": "third-party-facades", "title": "Lazy load third-party resources with facades", - "description": "Some third party embeds can be lazy loaded. Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).", + "description": "Some third-party embeds can be lazy loaded. Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).", "score": null, "scoreDisplayMode": "notApplicable" }, From d617f068f059525f6b9a937f482e1f8dcad655af Mon Sep 17 00:00:00 2001 From: Adam Raine <6752989+adamraine@users.noreply.github.com> Date: Wed, 11 Nov 2020 18:03:41 -0500 Subject: [PATCH 80/82] Update lighthouse-core/audits/third-party-facades.js Co-authored-by: Patrick Hulce --- lighthouse-core/audits/third-party-facades.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 7650278c2841..4de1bdc0f1c4 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -91,7 +91,7 @@ class ThirdPartyFacades extends Audit { /** * Sort items by transfer size and combine small items into a single row. - * items will be condensed to maximum of 6 rows. + * Items will be mutated in place to a maximum of 6 rows. * @param {ThirdPartySummary.URLSummary[]} items */ static condenseItems(items) { From 2d7158eefb1d451a17961e9b04949bca2a319e35 Mon Sep 17 00:00:00 2001 From: Adam Raine <6752989+adamraine@users.noreply.github.com> Date: Tue, 1 Dec 2020 18:14:22 -0500 Subject: [PATCH 81/82] Update learn more link --- lighthouse-core/audits/third-party-facades.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lighthouse-core/audits/third-party-facades.js b/lighthouse-core/audits/third-party-facades.js index 4de1bdc0f1c4..17effe9cdfee 100644 --- a/lighthouse-core/audits/third-party-facades.js +++ b/lighthouse-core/audits/third-party-facades.js @@ -35,7 +35,7 @@ const UIStrings = { failureTitle: 'Some third-party resources can be lazy loaded with a facade', /** Description of a Lighthouse audit that identifies the third-party code on the page that can be lazy loaded with a facade alternative. This is displayed after a user expands the section to see more. No character length limits. 'Learn More' becomes link text to additional documentation. A facade is a lightweight component which looks like the desired resource. Lazy loading means resources are deferred until they are needed. Third-party code refers to resources that are not within the control of the site owner. */ description: 'Some third-party embeds can be lazy loaded. ' + - 'Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).', + 'Consider replacing them with a facade until they are required. [Learn more](https://web.dev/third-party-facades/).', /** Summary text for the result of a Lighthouse audit that identifies the third-party code on a web page that can be lazy loaded with a facade alternative. This text summarizes the number of lazy loading facades that can be used on the page. A facade is a lightweight component which looks like the desired resource. */ displayValue: `{itemCount, plural, =1 {# facade alternative available} From 482dd423c24b6a8ab6078f0c49a14b4206573002 Mon Sep 17 00:00:00 2001 From: Adam Raine Date: Wed, 2 Dec 2020 12:31:02 -0500 Subject: [PATCH 82/82] update sample --- lighthouse-core/lib/i18n/locales/en-US.json | 2 +- lighthouse-core/lib/i18n/locales/en-XL.json | 2 +- lighthouse-core/test/results/sample_v2.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lighthouse-core/lib/i18n/locales/en-US.json b/lighthouse-core/lib/i18n/locales/en-US.json index 32e893705d5a..d47550bc84c1 100644 --- a/lighthouse-core/lib/i18n/locales/en-US.json +++ b/lighthouse-core/lib/i18n/locales/en-US.json @@ -1350,7 +1350,7 @@ "message": "Product" }, "lighthouse-core/audits/third-party-facades.js | description": { - "message": "Some third-party embeds can be lazy loaded. Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/)." + "message": "Some third-party embeds can be lazy loaded. Consider replacing them with a facade until they are required. [Learn more](https://web.dev/third-party-facades/)." }, "lighthouse-core/audits/third-party-facades.js | displayValue": { "message": "{itemCount, plural,\n =1 {# facade alternative available}\n other {# facade alternatives available}\n }" diff --git a/lighthouse-core/lib/i18n/locales/en-XL.json b/lighthouse-core/lib/i18n/locales/en-XL.json index 661168d24030..9a355341c4f1 100644 --- a/lighthouse-core/lib/i18n/locales/en-XL.json +++ b/lighthouse-core/lib/i18n/locales/en-XL.json @@ -1350,7 +1350,7 @@ "message": "P̂ŕôd́ûćt̂" }, "lighthouse-core/audits/third-party-facades.js | description": { - "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý êḿb̂éd̂ś ĉán̂ b́ê ĺâźŷ ĺôád̂éd̂. Ćôńŝíd̂ér̂ ŕêṕl̂áĉín̂ǵ t̂h́êḿ ŵít̂h́ â f́âćâd́ê ún̂t́îĺ t̂h́êý âŕê ŕêq́ûír̂éd̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/efficiently-load-third-party-javascript/)." + "message": "Ŝóm̂é t̂h́îŕd̂-ṕâŕt̂ý êḿb̂éd̂ś ĉán̂ b́ê ĺâźŷ ĺôád̂éd̂. Ćôńŝíd̂ér̂ ŕêṕl̂áĉín̂ǵ t̂h́êḿ ŵít̂h́ â f́âćâd́ê ún̂t́îĺ t̂h́êý âŕê ŕêq́ûír̂éd̂. [Ĺêár̂ń m̂ór̂é](https://web.dev/third-party-facades/)." }, "lighthouse-core/audits/third-party-facades.js | displayValue": { "message": "{itemCount, plural,\n =1 {# f̂áĉád̂é âĺt̂ér̂ńât́îv́ê áv̂áîĺâb́l̂é}\n other {# f̂áĉád̂é âĺt̂ér̂ńât́îv́êś âv́âíl̂áb̂ĺê}\n }" diff --git a/lighthouse-core/test/results/sample_v2.json b/lighthouse-core/test/results/sample_v2.json index cf25b94e281a..9a495b82cd60 100644 --- a/lighthouse-core/test/results/sample_v2.json +++ b/lighthouse-core/test/results/sample_v2.json @@ -1800,7 +1800,7 @@ "third-party-facades": { "id": "third-party-facades", "title": "Lazy load third-party resources with facades", - "description": "Some third-party embeds can be lazy loaded. Consider replacing them with a facade until they are required. [Learn more](https://web.dev/efficiently-load-third-party-javascript/).", + "description": "Some third-party embeds can be lazy loaded. Consider replacing them with a facade until they are required. [Learn more](https://web.dev/third-party-facades/).", "score": null, "scoreDisplayMode": "notApplicable" },