Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit 3848221
Author: Connor Clark <[email protected]>
Date:   Mon Dec 9 14:38:40 2019 -0800

    tests

commit d73c056
Author: Connor Clark <[email protected]>
Date:   Mon Dec 9 13:32:41 2019 -0800

    rm row.multi

commit 2b9babb
Author: Connor Clark <[email protected]>
Date:   Mon Dec 9 12:31:13 2019 -0800

    initial

commit c4ab6a0
Author: Paul Irish <[email protected]>
Date:   Fri Dec 6 16:53:42 2019 -0800

    docs: add readme for build/ (#10004)
  • Loading branch information
connorjclark committed Dec 9, 2019
1 parent 4e15110 commit e22ad8d
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 17 deletions.
54 changes: 54 additions & 0 deletions build/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Building Lighthouse

Lighthouse is built into browser-friendly bundles for two clients:

* Chrome DevTools Audits Panel
* Lightrider, the backend of PageSpeed Insights

Additionally, there are build processes for:

* [The Lighthouse report viewer](../lighthouse-viewer/)
* The chrome extension (as of Nov 2019 is a thin-client that defers to the viewer)

## Building for DevTools

To build the devtools files and roll them into a local checkout of Chromium:

```sh
yarn build-devtools && yarn devtools
```


`yarn build-devtools` creates these files:

```
dist
├── dt-report-resources
│ ├── report-generator.js
│ ├── report.css
│ ├── report.js
│ ├── template.html
│ └── templates.html
└── lighthouse-dt-bundle.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.

### How the Audits Panel uses the Lighthouse assets

`AuditsService` uses `self.runLighthouseInWorker`, the main export of the big bundle.

`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.

`AuditsPanel` also registers `report.css`.

`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

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.

1. Create the report within the Audits Panel DOM. `report.js` exports the renderer, and `report.css` and `templates.html` are pulled from `.cachedResources`.

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`.
31 changes: 16 additions & 15 deletions lighthouse-core/report/html/renderer/details-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -304,11 +304,21 @@ class DetailsRenderer {
}

return tableLike.headings.map(heading => {
let multi;
if (heading.multi) {
multi = {
key: heading.multi.key,
valueType: heading.multi.itemType,
displayUnit: heading.displayUnit,
granularity: heading.granularity,
};
}

return {
key: heading.key,
label: heading.text,
valueType: heading.itemType,
multi: heading.multi,
multi,
displayUnit: heading.displayUnit,
granularity: heading.granularity,
};
Expand All @@ -333,18 +343,6 @@ class DetailsRenderer {
return valueElement;
}

/**
* @param {*} maybeMulti
* @return {maybeMulti is LH.Audit.Details.Value}
*/
_isScalar(maybeMulti) {
if (typeof maybeMulti !== 'object') return true;
for (const value of Object.values(maybeMulti)) {
if (!Array.isArray(value)) return true;
}
return false;
}

/**
* @param {LH.Audit.Details.Table|LH.Audit.Details.Opportunity} details
* @return {Element}
Expand Down Expand Up @@ -385,8 +383,11 @@ class DetailsRenderer {

if (heading.multi) {
const multiHeading = {
...heading,
...heading.multi,
key: heading.multi.key,
valueType: heading.multi.valueType || heading.valueType,
granularity: heading.multi.granularity || heading.granularity,
displayUnit: heading.multi.displayUnit || heading.displayUnit,
label: '',
};
const multiElement = this._renderMultiValue(row, multiHeading);
if (multiElement) valueFragment.appendChild(multiElement);
Expand Down
77 changes: 75 additions & 2 deletions lighthouse-core/test/report/html/renderer/details-renderer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ describe('DetailsRenderer', () => {
// itemType is overriden by code object
headings: [{key: 'content', itemType: 'url', text: 'Heading'}],
items: [
{content: {type: 'code', value: 'code object'}},
{content: {type: 'code', value: 'https://codeobject.com'}},
{content: 'https://example.com'},
],
};
Expand All @@ -560,7 +560,7 @@ describe('DetailsRenderer', () => {
const codeEl = itemElements[0].firstChild;
assert.equal(codeEl.localName, 'pre');
assert.ok(codeEl.classList.contains('lh-code'));
assert.equal(codeEl.textContent, 'code object');
assert.equal(codeEl.textContent, 'https://codeobject.com');

// Second item uses the heading's specified type for the column.
const urlEl = itemElements[1].firstChild;
Expand All @@ -569,5 +569,78 @@ describe('DetailsRenderer', () => {
assert.equal(urlEl.title, 'https://example.com');
assert.equal(urlEl.textContent, 'https://example.com');
});

describe('multiple values', () => {
it('renders', () => {
const details = {
type: 'table',
headings: [{key: 'url', itemType: 'url', multi: {key: 'sources', itemType: 'code'}}],
items: [
{url: 'https://www.example.com', sources: ['a', 'b', 'c']},
],
};

const el = renderer.render(details);
const columnElement = el.querySelector('td.lh-table-column--url');

// First element is the url.
const codeEl = columnElement.firstChild;
assert.equal(codeEl.localName, 'div');
assert.ok(codeEl.classList.contains('lh-text__url'));
assert.equal(codeEl.textContent, 'https://www.example.com');

// Second element lists the multiple values.
const multiValuesEl = columnElement.children[1];
assert.equal(multiValuesEl.localName, 'div');
assert.ok(multiValuesEl.classList.contains('lh-multi-values'));

const multiValueEls = multiValuesEl.querySelectorAll('.lh-multi-value-entry');
assert.equal(multiValueEls[0].textContent, 'a');
assert.ok(multiValueEls[0].classList.contains('lh-code'));
assert.equal(multiValueEls[1].textContent, 'b');
assert.ok(multiValueEls[1].classList.contains('lh-code'));
assert.equal(multiValueEls[2].textContent, 'c');
assert.ok(multiValueEls[2].classList.contains('lh-code'));
});

it('renders, uses heading properties as fallback', () => {
const details = {
type: 'table',
headings: [{key: 'url', itemType: 'url', multi: {key: 'sources'}}],
items: [
{
url: 'https://www.example.com',
sources: [
'https://www.a.com',
{type: 'code', value: 'https://www.b.com'},
'https://www.c.com',
],
},
],
};

const el = renderer.render(details);
const columnElement = el.querySelector('td.lh-table-column--url');

// First element is the url.
const codeEl = columnElement.firstChild;
assert.equal(codeEl.localName, 'div');
assert.ok(codeEl.classList.contains('lh-text__url'));
assert.equal(codeEl.textContent, 'https://www.example.com');

// Second element lists the multiple values.
const multiValuesEl = columnElement.children[1];
assert.equal(multiValuesEl.localName, 'div');
assert.ok(multiValuesEl.classList.contains('lh-multi-values'));

const multiValueEls = multiValuesEl.querySelectorAll('.lh-multi-value-entry');
assert.equal(multiValueEls[0].textContent, 'https://www.a.com');
assert.ok(multiValueEls[0].classList.contains('lh-text__url'));
assert.equal(multiValueEls[1].textContent, 'https://www.b.com');
assert.ok(multiValueEls[1].classList.contains('lh-code'));
assert.equal(multiValueEls[2].textContent, 'https://www.c.com');
assert.ok(multiValueEls[2].classList.contains('lh-text__url'));
});
});
});
});

0 comments on commit e22ad8d

Please sign in to comment.