misc(build): inline report generator resources for devtools (#13406)

This commit is contained in:
Connor Clark 2021-11-23 13:38:30 -06:00 коммит произвёл GitHub
Родитель d8ae643f18
Коммит de99ab2dc2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 46 добавлений и 68 удалений

2
.github/scripts/generate-devtools-hash.sh поставляемый
Просмотреть файл

@ -19,6 +19,6 @@ md5 \
build/build-bundle.js \
build/build-dt-report-resources.js \
clients/devtools-entry.js \
clients/devtools-report-assets.js \
report/**/*.js \
lighthouse-core/test/chromium-web-tests/* \
third-party/chromium-webtests/webtests/http/tests/devtools/lighthouse/*.js

Просмотреть файл

@ -5,7 +5,8 @@
*/
'use strict';
const browserify = require('browserify');
const rollup = require('rollup');
const rollupPlugins = require('./rollup-plugins.js');
const fs = require('fs');
const path = require('path');
const assert = require('assert').strict;
@ -13,11 +14,8 @@ const {LH_ROOT} = require('../root.js');
const distDir = path.join(LH_ROOT, 'dist', 'dt-report-resources');
const bundleOutFile = `${distDir}/report-generator.js`;
const generatorFilename = `./report/generator/report-generator.js`;
const htmlReportAssets = require('../report/generator/report-assets.js');
/**
* Used to save cached resources (Runtime.cachedResources).
* @param {string} name
* @param {string} content
*/
@ -29,16 +27,31 @@ function writeFile(name, content) {
fs.rmSync(distDir, {recursive: true, force: true});
fs.mkdirSync(distDir, {recursive: true});
writeFile('report.js', htmlReportAssets.REPORT_JAVASCRIPT);
writeFile('standalone-template.html', htmlReportAssets.REPORT_TEMPLATE);
writeFile('report.js', '// This can be removed after the next CDT roll deletes this file');
writeFile('standalone-template.html',
'<!-- This can be removed after the next CDT roll deletes this file -->');
writeFile('report.d.ts', 'export {}');
writeFile('report-generator.d.ts', 'export {}');
const pathToReportAssets = require.resolve('../clients/devtools-report-assets.js');
browserify(generatorFilename, {standalone: 'Lighthouse.ReportGenerator'})
// Shims './report/generator/report-assets.js' to resolve to devtools-report-assets.js
.require(pathToReportAssets, {expose: './report-assets.js'})
.bundle((err, src) => {
if (err) throw err;
fs.writeFileSync(bundleOutFile, src.toString());
async function buildReportGenerator() {
const bundle = await rollup.rollup({
input: 'report/generator/report-generator.js',
plugins: [
rollupPlugins.shim({
[`${LH_ROOT}/report/generator/flow-report-assets.js`]: 'export default {}',
}),
rollupPlugins.commonjs(),
rollupPlugins.nodeResolve(),
rollupPlugins.inlineFs({verbose: Boolean(process.env.DEBUG)}),
],
});
await bundle.write({
file: bundleOutFile,
format: 'umd',
name: 'Lighthouse.ReportGenerator',
});
await bundle.close();
}
buildReportGenerator();

Просмотреть файл

@ -18,37 +18,37 @@ To build the devtools files and roll them into a local checkout of Chromium:
yarn devtools
```
`yarn build-devtools` creates these files:
```
dist
├── dt-report-resources
│ ├── report-generator.d.ts
│ ├── report-generator.js
│ ├── report.css
│ ├── report.js
│ ├── template.html
│ └── templates.html
└── lighthouse-dt-bundle.js
└── report
└── bundle.esm.js
```
1. the big `lighthouse-dt-bundle.js` bundle
1. the much smaller `report-generator.js` bundle (just two modules). This is exported as ReportGenerator
1. copies all the `report.{js,css}` / `template(s).html` files (these are not transformed in any way). We call these the report assets.
1. the biggest file is `lighthouse-dt-bundle.js`. This is a bundle of `lighthouse-core`, and is run inside a worker in CDT.
1. the much smaller `report-generator.js` bundle. This is assigned to the global object as `Lighthouse.ReportGenerator`
- This bundle has inlined the `dist/report/standalone.js` and `standalone-template.html` files (these are not transformed in any way). We call these the report generator assets.
- `report-generator.d.ts` is an empty type definition file to make the CDT build happy
1. Finally, `report/bundle.esm.js` is an ES modules bundle of the report code (note: this is copied to CDT as `report/bundle.js`).
### How the Audits Panel uses the Lighthouse assets
### How the Lighthouse Panel uses the Lighthouse CDT build artifacts
`AuditsService` uses `self.runLighthouseInWorker`, the main export of the big bundle.
`LighthouseService` uses `self.runLighthouse`, the main export of `lighthouse-dt-bundle.js`.
`AuditsPanel` uses `new Audits.ReportRenderer(dom)`, which overrides `self.ReportRenderer`, which is [exported](https://github.com/GoogleChrome/lighthouse/blob/ee3a9dfd665135b9dc03c18c9758b27464df07e0/lighthouse-core/report/html/renderer/report-renderer.js#L255) by `report.js`. This renderer takes a Lighthouse result, `templates.html`, and a target DOM element - it then renders the report to the target element.
`LighthousePanel` uses `new LighthouseReportRenderer(dom)`, which overrides `LighthouseReport.ReportRenderer`, ([defined here](https://github.com/GoogleChrome/lighthouse/blob/master/report/renderer/report-renderer.js)) which is exported by `report.js`. This renderer takes a Lighthouse result and a `rootEl` DOM element - it then renders the report to the target element. The CSS used by the report is embedded inside `bundle.esm.js` and is injected by the `ReportRenderer` via a call to `dom.createComponent('styles')`.
`AuditsPanel` also registers `report.css`.
A Lighthouse report (including what is shown within the Lighthouse panel) can also Export as HTML. Normally the report just uses `documentElement.outerHTML`, but from DevTools we get quine-y and use `Lighthouse.ReportGenerator`. This generator is defined in `report-generator.js`.
`report-generator.js` takes a Lighthouse result and creates an HTML file - it concats all of the report assets to create a singular HTML document. See: https://github.com/GoogleChrome/lighthouse/blob/ee3a9dfd665135b9dc03c18c9758b27464df07e0/lighthouse-core/report/report-generator.js#L35
`report-generator.js` takes a Lighthouse result and creates an HTML file - it concats all of the report generator assets to create a standalone HTML document. See: https://github.com/GoogleChrome/lighthouse/blob/ee3a9dfd665135b9dc03c18c9758b27464df07e0/lighthouse-core/report/report-generator.js#L35 . Normally when run in Node.js the report assets (JavaScript, which also contains the css; and the html template) are read from disk. But in DevTools, these assets have been inlined in the `report-generator.js` bundle.
A Lighthouse report (including what is shown within the Audits panel) can also Export as HTML. Normally the report just uses `documentElement.outerHTML`, but from DevTools we get quine-y and use `Lighthouse.ReportGenerator`. I only mention this because this is why the report assets are seperate files - there is a dual purpose.
In short, a Lighthouse report is rendered in two ways inside DevTools:
1. Create the report within the Audits Panel DOM. `report.js` exports the renderer, and `report.css` and `templates.html` are pulled from `.cachedResources`.
1. The LighthousePanel presents a report to the user via: the renderer as exported by `bundle.esm.js`. This file has inlined all the CSS and JS necessary to render a report.
2. Export the report as HTML. We can't just scrape the outerHTML like we normally do, because we render some thing a bit
special for DevTools, and we're not the only thing in that DOM (we would get _all_ of DevTools). So we use `Lighthouse.ReportGenerator` (important: this is only used here!) to create this HTML export. It requires all of the report assets, so to prevent double-bundling we [shim](https://github.com/GoogleChrome/lighthouse/blob/https://github.com/GoogleChrome/lighthouse/blob/ee3a9dfd665135b9dc03c18c9758b27464df07e0/lighthouse-core/report/report-generator.js#L35/clients/devtools-report-assets.js) its report assets module to just read from the `.cacheResources`.
2. The Lighthouse report exposes a "Save as HTML" feature: we can't scrape the outerHTML like we normally do, because we render some thing a bit
special for DevTools, and we're not the only thing in that DOM (we would get _all_ of DevTools). So we override the `getReportHtml` function in the renderer [here](undefined/blob/ba1bef52cea582fd2b9eed5b0f18ef739ff2e7b4/front_end/panels/lighthouse/LighthouseReportRenderer.ts#L175) to instead use `Lighthouse.ReportGenerator`, as defined by `report-generator.js`.

Просмотреть файл

@ -1,30 +0,0 @@
/**
* @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';
/**
* @fileoverview Instead of loading report assets form the filesystem, in Devtools we must load
* them via Runtime.cachedResources. We use this module to shim
* report/generator/report-assets.js in Devtools.
*/
/* global globalThis */
// @ts-expect-error: globalThis.EXPORTED_CACHED_RESOURCES_ONLY_FOR_LIGHTHOUSE exists in Devtools. https://source.chromium.org/chromium/chromium/src/+/main:third_party/devtools-frontend/src/front_end/root/Runtime.js;l=1247-1250;drc=c4e2fefe3327aa9fe5f4398a1baddb8726c230d5
const cachedResources = globalThis.EXPORTED_CACHED_RESOURCES_ONLY_FOR_LIGHTHOUSE;
// Getters are necessary because the DevTools bundling processes
// resources after this module is resolved. These properties are not
// read from immediately, so we can defer reading with getters and everything
// is going to be OK.
module.exports = {
get REPORT_JAVASCRIPT() {
return cachedResources.get('third_party/lighthouse/report-assets/report.js');
},
get REPORT_TEMPLATE() {
return cachedResources.get('third_party/lighthouse/report-assets/standalone-template.html');
},
};

Просмотреть файл

@ -21,7 +21,6 @@ limitations under the License.
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAEhklEQVR4AWJxL/BhIAesev1U5tcflpncgNrKIsqNIwzC9feMpDUzs70kOczMzMzJJcxwCTMzncPMnOwtzBwzMzPb0vRfeZPp0VhPS5I39V5fdiXV1/VD+9QC7OVn9BsyH1XIoEI1PfmJvLFowVV564+34DFUHudbmfDh4kVXh//7XwE+WjS/YfXZe3yr4j2rqj1AIhSB7hZ8ZtPZu/zw8cK523U4wE1/rvPfWrz4zs0m9ZdC9yUJAlASdBAgocRegfF/f3/h/PuaFsxMdwjAR0vm1+06eMMfIrhLqTWqdH4EumU2SPfMhigJAlRQbZrgrRsl9U+Y2DYDFCz3ILC9kiAiqSrMwbWT0nceEnR+9Kggc2zjOJCASDENkg0a5HfZZgDP81CM3CrQs2Z1+o7DJ6ePr8sK0AOCHv5Jjdt3evyYSaZ351VIStIxPRAUtrBYbxC6w+BZ0ivVSBKkIhJhemSyZpfB00EiPO2VjzYkxhcqXQqCWCShGplvi3y0QxqbuBurMjyJeWnkHZuAEgIQGsUBqwrfjZ+IlBgKyRJzVVYF8O6qFWdh86YzQzMrZigYmxAyfvHgLZQ/LC1CbeniW2Hkqr/PH16SgvGuf2/uzNMBwJA/njxizGPtSyAf7EziJCMGRDRdhoAC4PL1A/SrKQMAAQkEfpJAcRQdrBJ7gNwjSpJsdwK+CANBkqa1LgQB4IicV9nYUct7gaxuDJUErQIiEAiMxLVOFlKzIktPpT0ggpdpC/8YAHnxbgkUY4tAAFSR7AAXNyAAWHJrA/kHGjzg5nleuwFO7Nd/IoDw4Pm58+4jNLmYG0wRA5bErc2Mr3Y+dXTDW1VvwqbJkzMCHQ4S1GTCBOIgUHJrGdEwqzR+jAp/o2qAZelUDoQnruEEdDclJI6576AlNVfc+22XN/+Y1vnJD0Yind6UpEEvn/Hqq15EYjCW7jZCJEpnNvDgkyelDjs106kuux2AAXCSobULOWP8mLhYlpoDMK4qAFXJGk+grtH8YXVz5KJblqaG1+VUdTc0I290bmUQAriGITRbdQnom0aoFj8kx1+wMD2ifncAXUQE4SkDqN1hE0jEophs1SUwZAOhUAiMCLwRtamtTZtbbmZErSAUHbSysaoEmnrsakiMiUAURi283gN6wans9oX8rOCrj7/JP35DFD+iQ7Au/K2KE1jzx6ujjUnXFH9KjEq6ZlhsTBICrNLJf47Pv/pkHzvup1w4dmUbEei0+bcXRqJuh5kVARQ8byyYxOwNGr7A87xh1tp8sGT+uMInrwi++Xj7TQz2d27NvwEkrOflAFQGIDA5khASBCGdO2/Z/MnLPwYfv5TFhjW7QhVKAB6afwe2LpFlFsCnlQEosgQgDsdOG1/LKeNqJS4JCSPJ/i+TakwEARor7gER1Iva5JmPOJK0RUqmoPnnlzFCtmIAhAAQEIQRgDaiYPIauNXcnDlRIrWNFY3hm7PG9YRqr7IV7HrCgAC17befjEvRq2nGhAHtBqDpOuI/I1diUUAMYIxEdyejBJqLnNoszGZtfiX/CztGv2mq+sdaAAAAAElFTkSuQmCC">
<title>Lighthouse Flow Report</title>
<style>/*%%LIGHTHOUSE_CSS%%*/</style>
<style>/*%%LIGHTHOUSE_FLOW_CSS%%*/</style>
<style>body {margin: 0}</style>
</head>

Просмотреть файл

@ -9,12 +9,13 @@ const fs = require('fs');
/* eslint-disable max-len */
const FLOW_REPORT_TEMPLATE = fs.readFileSync(`${__dirname}/../../flow-report/assets/standalone-flow-template.html`, 'utf8');
const REGULAR_REPORT_CSS = fs.readFileSync(__dirname + '/../assets/styles.css', 'utf8');
const FLOW_REPORT_CSS = fs.readFileSync(`${__dirname}/../../flow-report/assets/styles.css`, 'utf8');
const FLOW_REPORT_JAVASCRIPT = fs.readFileSync(`${__dirname}/../../dist/report/flow.js`, 'utf8');
/* eslint-enable max-len */
module.exports = {
FLOW_REPORT_TEMPLATE,
FLOW_REPORT_CSS,
FLOW_REPORT_CSS: [REGULAR_REPORT_CSS, FLOW_REPORT_CSS].join('\n'),
FLOW_REPORT_JAVASCRIPT,
};

Просмотреть файл

@ -12,14 +12,10 @@ const flowReportAssets = require('./flow-report-assets.js');
const REPORT_TEMPLATE = fs.readFileSync(__dirname + '/../assets/standalone-template.html',
'utf8');
const REPORT_JAVASCRIPT = fs.readFileSync(__dirname + '/../../dist/report/standalone.js', 'utf8');
const REPORT_CSS = fs.readFileSync(__dirname + '/../assets/styles.css', 'utf8');
// Changes to this export interface should be reflected in build/build-dt-report-resources.js
// and clients/devtools-report-assets.js
module.exports = {
REPORT_TEMPLATE,
REPORT_JAVASCRIPT,
REPORT_CSS,
// Flow report assets are not needed for every bundle.
// Ignoring flow-report-assets.js (e.g. `browserify.ignore`) will remove the flow assets from the bundle.
...flowReportAssets,

Просмотреть файл

@ -70,7 +70,6 @@ class ReportGenerator {
{search: '%%LIGHTHOUSE_FLOW_JSON%%', replacement: sanitizedJson},
{search: '%%LIGHTHOUSE_FLOW_JAVASCRIPT%%', replacement: htmlReportAssets.FLOW_REPORT_JAVASCRIPT},
{search: '/*%%LIGHTHOUSE_FLOW_CSS%%*/', replacement: htmlReportAssets.FLOW_REPORT_CSS},
{search: '/*%%LIGHTHOUSE_CSS%%*/', replacement: htmlReportAssets.REPORT_CSS},
/* eslint-enable max-len */
]);
}