Commit 5a003efc authored by Paul Irish's avatar Paul Irish Committed by Commit Bot

DevTools: Roll Lighthouse to 4.0.0-beta

Bug: 772558
Change-Id: Ie1ef89f7a189687e600e5e22d376c53dac242079
Reviewed-on: https://chromium-review.googlesource.com/c/1355176Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Commit-Queue: Paul Irish <paulirish@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612481}
parent 298c4d34
......@@ -38,7 +38,7 @@ all_devtools_files = [
"front_end/audits2_worker.js",
"front_end/audits2_worker.json",
"front_end/audits2_worker/Audits2Service.js",
"front_end/audits2_worker/lighthouse/lighthouse-background.js",
"front_end/audits2_worker/lighthouse/lighthouse-dt-bundle.js",
"front_end/audits2_worker/module.json",
"front_end/audits2/Audits2Panel.js",
"front_end/audits2/Audits2Controller.js",
......@@ -55,6 +55,7 @@ all_devtools_files = [
"front_end/audits2/lighthouse/renderer/details-renderer.js",
"front_end/audits2/lighthouse/renderer/category-renderer.js",
"front_end/audits2/lighthouse/renderer/performance-category-renderer.js",
"front_end/audits2/lighthouse/renderer/pwa-category-renderer.js",
"front_end/audits2/lighthouse/renderer/crc-details-renderer.js",
"front_end/audits2/lighthouse/renderer/report-renderer.js",
"front_end/audits2/lighthouse/renderer/util.js",
......
......@@ -59,7 +59,7 @@ class CriticalRequestChainRenderer {
const node = parent[id];
const siblings = Object.keys(parent);
const isLastChild = siblings.indexOf(id) === (siblings.length - 1);
const hasChildren = Object.keys(node.children).length > 0;
const hasChildren = !!node.children && Object.keys(node.children).length > 0;
// Copy the tree markers so that we don't change by reference.
const newTreeMarkers = Array.isArray(treeMarkers) ? treeMarkers.slice(0) : [];
......@@ -149,11 +149,12 @@ class CriticalRequestChainRenderer {
*/
static buildTree(dom, tmpl, segment, elem, details) {
elem.appendChild(CriticalRequestChainRenderer.createChainNode(dom, tmpl, segment));
for (const key of Object.keys(segment.node.children)) {
const childSegment = CriticalRequestChainRenderer.createSegment(segment.node.children, key,
segment.startTime, segment.transferSize, segment.treeMarkers, segment.isLastChild);
CriticalRequestChainRenderer.buildTree(dom, tmpl, childSegment, elem, details);
if (segment.node.children) {
for (const key of Object.keys(segment.node.children)) {
const childSegment = CriticalRequestChainRenderer.createSegment(segment.node.children, key,
segment.startTime, segment.transferSize, segment.treeMarkers, segment.isLastChild);
CriticalRequestChainRenderer.buildTree(dom, tmpl, childSegment, elem, details);
}
}
}
......
......@@ -80,6 +80,8 @@ class DetailsRenderer {
case 'opportunity':
// @ts-ignore - TODO(bckenny): Fix type hierarchy
return this._renderOpportunityTable(details);
case 'numeric':
return this._renderNumeric(/** @type {StringDetailsJSON} */ (details));
default: {
throw new Error(`Unknown type: ${details.type}`);
}
......@@ -124,14 +126,11 @@ class DetailsRenderer {
displayedPath = parsed.file === '/' ? parsed.origin : parsed.file;
displayedHost = parsed.file === '/' ? '' : `(${parsed.hostname})`;
title = url;
} catch (/** @type {!Error} */ e) {
if (!e.name.startsWith('TypeError')) {
throw e;
}
} catch (e) {
displayedPath = url;
}
const element = /** @type {HTMLElement} */ (this._dom.createElement('div', 'lh-text__url'));
const element = this._dom.createElement('div', 'lh-text__url');
element.appendChild(this._renderText({
value: displayedPath,
}));
......@@ -162,7 +161,7 @@ class DetailsRenderer {
});
}
const a = /** @type {HTMLAnchorElement} */ (this._dom.createElement('a'));
const a = this._dom.createElement('a');
a.rel = 'noopener';
a.target = '_blank';
a.textContent = details.text;
......@@ -181,6 +180,16 @@ class DetailsRenderer {
return element;
}
/**
* @param {{value: string}} text
* @return {Element}
*/
_renderNumeric(text) {
const element = this._dom.createElement('div', 'lh-numeric');
element.textContent = text.value;
return element;
}
/**
* Create small thumbnail with scaled down image asset.
* If the supplied details doesn't have an image/* mimeType, then an empty span is returned.
......@@ -188,7 +197,7 @@ class DetailsRenderer {
* @return {Element}
*/
_renderThumbnail(details) {
const element = /** @type {HTMLImageElement}*/ (this._dom.createElement('img', 'lh-thumbnail'));
const element = this._dom.createElement('img', 'lh-thumbnail');
const strValue = details.value;
element.src = strValue;
element.title = strValue;
......@@ -337,7 +346,7 @@ class DetailsRenderer {
* @protected
*/
renderNode(item) {
const element = /** @type {HTMLSpanElement} */ (this._dom.createElement('span', 'lh-node'));
const element = this._dom.createElement('span', 'lh-node');
if (item.snippet) {
element.textContent = item.snippet;
}
......
......@@ -18,6 +18,8 @@
/* globals URL self */
/** @typedef {HTMLElementTagNameMap & {[id: string]: HTMLElement}} HTMLElmentByTagName */
class DOM {
/**
* @param {Document} document
......@@ -27,14 +29,14 @@ class DOM {
this._document = document;
}
// TODO(bckenny): can pass along `createElement`'s inferred type
/**
* @param {string} name
* @template {string} T
* @param {T} name
* @param {string=} className
* @param {Object<string, (string|undefined)>=} attrs Attribute key/val pairs.
* Note: if an attribute key has an undefined value, this method does not
* set the attribute on the node.
* @return {Element}
* @return {HTMLElmentByTagName[T]}
*/
createElement(name, className, attrs = {}) {
const element = this._document.createElement(name);
......@@ -58,13 +60,14 @@ class DOM {
}
/**
* @template {string} T
* @param {Element} parentElem
* @param {string} elementName
* @param {T} elementName
* @param {string=} className
* @param {Object<string, (string|undefined)>=} attrs Attribute key/val pairs.
* Note: if an attribute key has an undefined value, this method does not
* set the attribute on the node.
* @return {Element}
* @return {HTMLElmentByTagName[T]}
*/
createChildOf(parentElem, elementName, className, attrs) {
const element = this.createElement(elementName, className, attrs);
......@@ -122,7 +125,7 @@ class DOM {
// Append link if there are any.
if (linkText && linkHref) {
const a = /** @type {HTMLAnchorElement} */ (this.createElement('a'));
const a = this.createElement('a');
a.rel = 'noopener';
a.target = '_blank';
a.textContent = linkText;
......@@ -147,7 +150,7 @@ class DOM {
const [preambleText, codeText] = parts.splice(0, 2);
element.appendChild(this._document.createTextNode(preambleText));
if (codeText) {
const pre = /** @type {HTMLPreElement} */ (this.createElement('code'));
const pre = this.createElement('code');
pre.textContent = codeText;
element.appendChild(pre);
}
......
......@@ -188,7 +188,7 @@ class PerformanceCategoryRenderer extends CategoryRenderer {
groupEl.appendChild(headerEl);
opportunityAudits.forEach((item, i) =>
groupEl.appendChild(this._renderOpportunity(item, i, scale)));
groupEl.classList.add('lh-audit-group--opportunities');
groupEl.classList.add('lh-audit-group--load-opportunities');
element.appendChild(groupEl);
}
......@@ -209,14 +209,17 @@ class PerformanceCategoryRenderer extends CategoryRenderer {
}
// Passed audits
const passedElements = category.auditRefs
const passedAudits = category.auditRefs
.filter(audit => (audit.group === 'load-opportunities' || audit.group === 'diagnostics') &&
Util.showAsPassed(audit.result))
.map((audit, i) => this.renderAudit(audit, i));
Util.showAsPassed(audit.result));
if (!passedElements.length) return element;
if (!passedAudits.length) return element;
const passedElem = this.renderPassedAuditsSection(passedElements);
const clumpOpts = {
auditRefs: passedAudits,
groupDefinitions: groups,
};
const passedElem = this.renderClump('passed', clumpOpts);
element.appendChild(passedElem);
return element;
}
......
/**
* @license
* Copyright 2018 Google Inc. 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';
/* globals self, Util, CategoryRenderer */
class PwaCategoryRenderer extends CategoryRenderer {
/**
* @param {LH.ReportResult.Category} category
* @param {Object<string, LH.Result.ReportGroup>} [groupDefinitions]
* @return {Element}
*/
render(category, groupDefinitions = {}) {
const categoryElem = this.dom.createElement('div', 'lh-category');
this.createPermalinkSpan(categoryElem, category.id);
categoryElem.appendChild(this.renderCategoryHeader(category));
const auditRefs = category.auditRefs;
// Regular audits aren't split up into pass/fail/not-applicable clumps, they're
// all put in a top-level clump that isn't expandable/collapsable.
const regularAuditRefs = auditRefs.filter(ref => ref.result.scoreDisplayMode !== 'manual');
const auditsElem = this._renderAudits(regularAuditRefs, groupDefinitions);
categoryElem.appendChild(auditsElem);
// Manual audits are still in a manual clump.
const manualAuditRefs = auditRefs.filter(ref => ref.result.scoreDisplayMode === 'manual');
const manualElem = this.renderClump('manual',
{auditRefs: manualAuditRefs, groupDefinitions, description: category.manualDescription});
categoryElem.appendChild(manualElem);
return categoryElem;
}
/**
* @param {LH.ReportResult.Category} category
* @return {DocumentFragment}
*/
renderScoreGauge(category) {
// Defer to parent-gauge style if category error.
if (category.score === null) {
return super.renderScoreGauge(category);
}
const tmpl = this.dom.cloneTemplate('#tmpl-lh-gauge--pwa', this.templateContext);
const wrapper = /** @type {HTMLAnchorElement} */ (this.dom.find('.lh-gauge--pwa__wrapper',
tmpl));
wrapper.href = `#${category.id}`;
const allGroups = this._getGroupIds(category.auditRefs);
const passingGroupIds = this._getPassingGroupIds(category.auditRefs);
if (passingGroupIds.size === allGroups.size) {
wrapper.classList.add('lh-badged--all');
} else {
for (const passingGroupId of passingGroupIds) {
wrapper.classList.add(`lh-badged--${passingGroupId}`);
}
}
this.dom.find('.lh-gauge__label', tmpl).textContent = category.title;
return tmpl;
}
/**
* Returns the group IDs found in auditRefs.
* @param {Array<LH.ReportResult.AuditRef>} auditRefs
* @return {Set<string>}
*/
_getGroupIds(auditRefs) {
const groupIds = auditRefs.map(ref => ref.group).filter(/** @return {g is string} */ g => !!g);
return new Set(groupIds);
}
/**
* Returns the group IDs whose audits are all considered passing.
* @param {Array<LH.ReportResult.AuditRef>} auditRefs
* @return {Set<string>}
*/
_getPassingGroupIds(auditRefs) {
const uniqueGroupIds = this._getGroupIds(auditRefs);
// Remove any that have a failing audit.
for (const auditRef of auditRefs) {
if (!Util.showAsPassed(auditRef.result) && auditRef.group) {
uniqueGroupIds.delete(auditRef.group);
}
}
return uniqueGroupIds;
}
/**
* Render non-manual audits in groups, giving a badge to any group that has
* all passing audits.
* @param {Array<LH.ReportResult.AuditRef>} auditRefs
* @param {Object<string, LH.Result.ReportGroup>} groupDefinitions
* @return {Element}
*/
_renderAudits(auditRefs, groupDefinitions) {
const auditsElem = this.renderUnexpandableClump(auditRefs, groupDefinitions);
// Add a 'badged' class to group if all audits in that group pass.
const passsingGroupIds = this._getPassingGroupIds(auditRefs);
for (const groupId of passsingGroupIds) {
const groupElem = this.dom.find(`.lh-audit-group--${groupId}`, auditsElem);
groupElem.classList.add('lh-badged');
}
return auditsElem;
}
}
if (typeof module !== 'undefined' && module.exports) {
module.exports = PwaCategoryRenderer;
} else {
self.PwaCategoryRenderer = PwaCategoryRenderer;
}
......@@ -26,7 +26,7 @@
/** @typedef {import('./dom.js')} DOM */
/** @typedef {import('./details-renderer.js').DetailsJSON} DetailsJSON */
/* globals self, Util, DetailsRenderer, CategoryRenderer, PerformanceCategoryRenderer */
/* globals self, Util, DetailsRenderer, CategoryRenderer, PerformanceCategoryRenderer, PwaCategoryRenderer */
class ReportRenderer {
/**
......@@ -42,6 +42,7 @@ class ReportRenderer {
/**
* @param {LH.Result} result
* @param {Element} container Parent element to render the report into.
* @return {Element}
*/
renderReport(result, container) {
// Mutate the UIStrings if necessary (while saving originals)
......@@ -55,7 +56,7 @@ class ReportRenderer {
// put the UIStrings back into original state
Util.updateAllUIStrings(originalUIStrings);
return /** @type {Element} **/ (container);
return container;
}
/**
......@@ -188,24 +189,39 @@ class ReportRenderer {
const detailsRenderer = new DetailsRenderer(this._dom);
const categoryRenderer = new CategoryRenderer(this._dom, detailsRenderer);
categoryRenderer.setTemplateContext(this._templateContext);
const perfCategoryRenderer = new PerformanceCategoryRenderer(this._dom, detailsRenderer);
perfCategoryRenderer.setTemplateContext(this._templateContext);
/** @type {Record<string, CategoryRenderer>} */
const specificCategoryRenderers = {
performance: new PerformanceCategoryRenderer(this._dom, detailsRenderer),
pwa: new PwaCategoryRenderer(this._dom, detailsRenderer),
};
Object.values(specificCategoryRenderers).forEach(renderer => {
renderer.setTemplateContext(this._templateContext);
});
const categories = reportSection.appendChild(this._dom.createElement('div', 'lh-categories'));
for (const category of report.reportCategories) {
if (scoreHeader) {
scoreHeader.appendChild(categoryRenderer.renderScoreGauge(category));
}
let renderer = categoryRenderer;
if (category.id === 'performance') {
renderer = perfCategoryRenderer;
}
const renderer = specificCategoryRenderers[category.id] || categoryRenderer;
categories.appendChild(renderer.render(category, report.categoryGroups));
}
if (scoreHeader) {
const defaultGauges = [];
const customGauges = [];
for (const category of report.reportCategories) {
const renderer = specificCategoryRenderers[category.id] || categoryRenderer;
const categoryGauge = renderer.renderScoreGauge(category);
// Group gauges that aren't default at the end of the header
if (renderer.renderScoreGauge === categoryRenderer.renderScoreGauge) {
defaultGauges.push(categoryGauge);
} else {
customGauges.push(categoryGauge);
}
}
scoreHeader.append(...defaultGauges, ...customGauges);
const scoreScale = this._dom.cloneTemplate('#tmpl-lh-scorescale', this._templateContext);
this._dom.find('.lh-scorescale-label', scoreScale).textContent =
Util.UIStrings.scorescaleLabel;
......
......@@ -62,6 +62,15 @@ class Util {
if (typeof clone.categories !== 'object') throw new Error('No categories provided.');
clone.reportCategories = Object.values(clone.categories);
// The proto process turns 'not-applicable' into 'not_applicable'. Correct this to support both.
// TODO: remove when underscore/hyphen proto issue is resolved. See #6371, #6201.
for (const audit of Object.values(clone.audits)) {
// @ts-ignore tsc rightly flags that this value shouldn't occur.
if (audit.scoreDisplayMode === 'not_applicable') {
audit.scoreDisplayMode = 'not-applicable';
}
}
// For convenience, smoosh all AuditResults into their auditDfn (which has just weight & group)
for (const category of clone.reportCategories) {
category.auditRefs.forEach(auditMeta => {
......@@ -398,7 +407,7 @@ class Util {
networkThrottling = `${Util.formatNumber(requestLatencyMs)}${NBSP}ms HTTP RTT, ` +
`${Util.formatNumber(throttling.downloadThroughputKbps)}${NBSP}Kbps down, ` +
`${Util.formatNumber(throttling.uploadThroughputKbps)}${NBSP}Kbps up (DevTools)`;
summary = 'Throttled Fast 3G network';
summary = 'Throttled Slow 4G network';
break;
}
case 'simulate': {
......@@ -406,7 +415,7 @@ class Util {
cpuThrottling = `${Util.formatNumber(cpuSlowdownMultiplier)}x slowdown (Simulated)`;
networkThrottling = `${Util.formatNumber(rttMs)}${NBSP}ms TCP RTT, ` +
`${Util.formatNumber(throughputKbps)}${NBSP}Kbps throughput (Simulated)`;
summary = 'Simulated Fast 3G network';
summary = 'Simulated Slow 4G network';
break;
}
default:
......@@ -484,8 +493,8 @@ Util.UIStrings = {
/** Label of value shown in the summary of critical request chains. Refers to the total amount of time (milliseconds) of the longest critical path chain/sequence of network requests. Example value: 2310 ms */
crcLongestDurationLabel: 'Maximum critical path latency:',
/** Explanation shown to users below performance results to inform them that the test was done with a 3G network connection and to warn them that the numbers they see will likely change slightly the next time they run Lighthouse. 'Lighthouse' becomes link text to additional documentation. */
lsPerformanceCategoryDescription: '[Lighthouse](https://developers.google.com/web/tools/lighthouse/) analysis of the current page on emulated 3G. Values are estimated and may vary.',
/** Explanation shown to users below performance results to inform them that the test was done with a 4G network connection and to warn them that the numbers they see will likely change slightly the next time they run Lighthouse. 'Lighthouse' becomes link text to additional documentation. */
lsPerformanceCategoryDescription: '[Lighthouse](https://developers.google.com/web/tools/lighthouse/) analysis of the current page on an emulated mobile network. Values are estimated and may vary.',
/** Title of the lab data section of the Performance category. Within this section are various speed metrics which quantify the pageload performance into values presented in seconds and milliseconds. "Lab" is an abbreviated form of "laboratory", and refers to the fact that the data is from a controlled test of a website, not measurements from real users visiting that site. */
labDataTitle: 'Lab Data',
};
......
......@@ -24,6 +24,7 @@
"lighthouse/renderer/dom.js",
"lighthouse/renderer/category-renderer.js",
"lighthouse/renderer/performance-category-renderer.js",
"lighthouse/renderer/pwa-category-renderer.js",
"lighthouse/renderer/details-renderer.js",
"lighthouse/renderer/crc-details-renderer.js",
"lighthouse/renderer/report-renderer.js",
......@@ -48,6 +49,7 @@
"lighthouse/renderer/dom.js",
"lighthouse/renderer/category-renderer.js",
"lighthouse/renderer/performance-category-renderer.js",
"lighthouse/renderer/pwa-category-renderer.js",
"lighthouse/renderer/details-renderer.js",
"lighthouse/renderer/crc-details-renderer.js",
"lighthouse/renderer/report-renderer.js"
......
......@@ -10,10 +10,10 @@
}
],
"scripts": [
"lighthouse/lighthouse-background.js",
"lighthouse/lighthouse-dt-bundle.js",
"Audits2Service.js"
],
"skip_compilation": [
"lighthouse/lighthouse-background.js"
"lighthouse/lighthouse-dt-bundle.js"
]
}
......@@ -399,7 +399,7 @@ function renameIdentifiers(identifierMap) {
return;
if (filePath.includes('externs.js'))
return;
if (filePath.includes('eslint') || filePath.includes('lighthouse-background.js') || filePath.includes('/cm/') ||
if (filePath.includes('eslint') || filePath.includes('lighthouse-dt-bundle.js') || filePath.includes('/cm/') ||
filePath.includes('/xterm.js/') || filePath.includes('/acorn/'))
return;
if (filePath.includes('/cm_modes/') && !filePath.includes('DefaultCodeMirror') &&
......
......@@ -12,10 +12,76 @@ Run audits: enabled visible
=============== Lighthouse Status Updates ===============
Loading…
Create config
Requiring gatherers
Requiring audits
Runner setup
Connecting to browser
Getting browser version
Resetting state with about:blank
Benchmarking machine
Initializing…
Running beforePass methods
Retrieving setup: Scripts
Retrieving setup: CSSUsage
Retrieving setup: Viewport
Retrieving setup: ViewportDimensions
Retrieving setup: ThemeColor
Retrieving setup: Manifest
Retrieving setup: RuntimeExceptions
Retrieving setup: ChromeConsoleMessages
Retrieving setup: ImageUsage
Retrieving setup: Accessibility
Retrieving setup: AnchorsWithNoRelNoopener
Retrieving setup: AppCacheManifest
Retrieving setup: Doctype
Retrieving setup: DOMStats
Retrieving setup: JSLibraries
Retrieving setup: OptimizedImages
Retrieving setup: PasswordInputsWithPreventedPaste
Retrieving setup: ResponseCompression
Retrieving setup: TagsBlockingFirstPaint
Retrieving setup: MetaDescription
Retrieving setup: FontSize
Retrieving setup: CrawlableLinks
Retrieving setup: MetaRobots
Retrieving setup: Hreflang
Retrieving setup: EmbeddedContent
Retrieving setup: Canonical
Retrieving setup: RobotsTxt
Loading page & waiting for onload
Getting browser version
Running pass methods
Retrieving in-page: Scripts
Retrieving in-page: CSSUsage
Retrieving in-page: Viewport
Retrieving in-page: ViewportDimensions
Retrieving in-page: ThemeColor
Retrieving in-page: Manifest
Retrieving in-page: RuntimeExceptions
Retrieving in-page: ChromeConsoleMessages
Retrieving in-page: ImageUsage
Retrieving in-page: Accessibility
Retrieving in-page: AnchorsWithNoRelNoopener
Retrieving in-page: AppCacheManifest
Retrieving in-page: Doctype
Retrieving in-page: DOMStats
Retrieving in-page: JSLibraries
Retrieving in-page: OptimizedImages
Retrieving in-page: PasswordInputsWithPreventedPaste
Retrieving in-page: ResponseCompression
Retrieving in-page: TagsBlockingFirstPaint
Retrieving in-page: MetaDescription
Retrieving in-page: FontSize
Retrieving in-page: CrawlableLinks
Retrieving in-page: MetaRobots
Retrieving in-page: Hreflang
Retrieving in-page: EmbeddedContent
Retrieving in-page: Canonical
Retrieving in-page: RobotsTxt
Retrieving trace
Retrieving devtoolsLog and network records
Retrieving devtoolsLog & network records
Running afterPass methods
Retrieving: Scripts
Retrieving: CSSUsage
Retrieving: Viewport
......@@ -35,7 +101,6 @@ Retrieving: OptimizedImages
Retrieving: PasswordInputsWithPreventedPaste
Retrieving: ResponseCompression
Retrieving: TagsBlockingFirstPaint
Retrieving: WebSQL
Retrieving: MetaDescription
Retrieving: FontSize
Retrieving: CrawlableLinks
......@@ -44,52 +109,87 @@ Retrieving: Hreflang
Retrieving: EmbeddedContent
Retrieving: Canonical
Retrieving: RobotsTxt
Retrieving: Fonts
Resetting state with about:blank
Running beforePass methods
Retrieving setup: ServiceWorker
Retrieving setup: Offline
Retrieving setup: StartUrl
Loading page & waiting for onload
Retrieving devtoolsLog and network records
Running pass methods
Retrieving in-page: ServiceWorker
Retrieving in-page: Offline
Retrieving in-page: StartUrl
Retrieving devtoolsLog & network records
Running afterPass methods
Retrieving: ServiceWorker
Retrieving: Offline
Retrieving: StartUrl
Resetting state with about:blank
Running beforePass methods
Retrieving setup: HTTPRedirect
Retrieving setup: HTMLWithoutJavaScript
Loading page & waiting for onload
Retrieving devtoolsLog and network records
Running pass methods
Retrieving in-page: HTTPRedirect
Retrieving in-page: HTMLWithoutJavaScript
Retrieving devtoolsLog & network records
Running afterPass methods
Retrieving: HTTPRedirect
Retrieving: HTMLWithoutJavaScript
Disconnecting from browser...
Analyzing and running audits...
Evaluating: Uses HTTPS
Computing artifact: NetworkRecords
Evaluating: Redirects HTTP traffic to HTTPS
Evaluating: Registers a service worker
Evaluating: Responds with a 200 when offline
Evaluating: Current page responds with a 200 when offline
Evaluating: Has a `<meta name="viewport">` tag with `width` or `initial-scale`
Evaluating: Contains some content when JavaScript is not available
Evaluating: First Contentful Paint
Computing artifact: FirstContentfulPaint
Computing artifact: TraceOfTab
Evaluating: First Meaningful Paint
Evaluating: Page load is fast enough on 3G
Computing artifact: FirstMeaningfulPaint
Evaluating: Page load is fast enough on mobile networks
Computing artifact: Interactive
Evaluating: Speed Index
Computing artifact: SpeedIndex
Evaluating: Screenshot Thumbnails
Computing artifact: Speedline
Evaluating: Final Screenshot
Computing artifact: Screenshots
Evaluating: Estimated Input Latency
Computing artifact: EstimatedInputLatency
Evaluating: No browser errors logged to the console
Evaluating: Server response times are low (TTFB)
Computing artifact: MainResource
Evaluating: First CPU Idle
Computing artifact: FirstCPUIdle
Evaluating: Time to Interactive
Evaluating: User Timing marks and measures
Evaluating: Minimize Critical Requests Depth
Computing artifact: CriticalRequestChains
Evaluating: Avoid multiple page redirects
Evaluating: User can be prompted to Install the Web App
Evaluating: Web app manifest meets the installability requirements
Computing artifact: ManifestValues
Evaluating: Configured for a custom splash screen
Evaluating: Address bar matches brand colors
Evaluating: The `short_name` won't be truncated on the homescreen
Evaluating: Sets an address-bar theme color
Evaluating: Content is sized correctly for the viewport
Evaluating: Displays images with correct aspect ratio
Evaluating: Avoids deprecated APIs
Evaluating: Minimizes main-thread work
Computing artifact: MainThreadTasks
Evaluating: JavaScript execution time
Evaluating: Preload key requests
Computing artifact: PageDependencyGraph
Computing artifact: LoadSimulator
Computing artifact: NetworkAnalysis
Evaluating: Preconnect to required origins
Computing artifact: LoadSimulator
Evaluating: All text remains visible during webfont loads
Evaluating: Network Requests
Evaluating: Metrics
Evaluating: start_url responds with a 200 when offline
Evaluating: Site works cross-browser
Evaluating: Page transitions don't feel like they block on the network
Evaluating: Each page has a URL
......@@ -159,7 +259,6 @@ Evaluating: Avoids requesting the geolocation permission on page load
Evaluating: Avoids `document.write()`
Evaluating: Avoids front-end JavaScript libraries with known security vulnerabilities
Evaluating: Detected JavaScript libraries
Evaluating: Avoids WebSQL DB
Evaluating: Avoids requesting the notification permission on page load
Evaluating: Allows users to paste into password fields
Evaluating: Uses HTTP/2 for its own resources
......@@ -179,7 +278,7 @@ Generating results...
=============== Lighthouse Results ===============
URL: http://127.0.0.1:8000/devtools/resources/inspected-page.html
Version: 3.2.0
Version: 4.0.0-beta
accesskeys: not-applicable
......@@ -230,6 +329,7 @@ http-status-code: pass
image-alt: not-applicable
image-aspect-ratio: pass
input-image-alt: not-applicable
installable-manifest: fail
interactive: flaky
interactive-element-affordance: manual
is-crawlable: pass
......@@ -245,7 +345,6 @@ load-fast-enough-for-pwa: flaky
logical-tab-order: manual
mainthread-work-breakdown: ERROR Something went wrong with recording the trace over your page load. Please run Lighthouse again. (NO_FCP)
managed-focus: manual
manifest-short-name-length: not-applicable
meta-description: fail
meta-refresh: not-applicable
meta-viewport: not-applicable
......@@ -254,9 +353,9 @@ mobile-friendly: manual
network-requests: informative
no-document-write: pass
no-vulnerable-libraries: pass
no-websql: pass
notification-on-start: pass
object-alt: not-applicable
offline-start-url: fail
offscreen-content-hidden: manual
offscreen-images: flaky
password-inputs-can-be-pasted-into: pass
......@@ -298,9 +397,8 @@ video-caption: not-applicable
video-description: not-applicable
viewport: fail
visual-order-follows-dom: manual
webapp-install-banner: fail
without-javascript: fail
works-offline: fail
# of .lh-audit divs: 112
# of .lh-audit divs: 111
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment