chore: add readme link to size and bot

This commit is contained in:
Liz Mitchell 2023-12-13 11:23:32 -08:00
parent 1d9a552dcf
commit 381189da9b
4 changed files with 133 additions and 84 deletions

View File

@ -0,0 +1,43 @@
name: Update size
on:
push:
branches: main
workflow_dispatch:
# allows triggering from the github UI
jobs:
check-for-doc-changes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: 20
cache: npm
- uses: google/wireit@setup-github-actions-caching/v1
- name: Install Dependencies
run: npm ci
- name: Update Size
run: npm run update-size
- name: Check if update-size produces git diff
id: ifChange
run: git diff --exit-code || echo "::set-output name=changed::yes"
- name: Create or update PR
if: steps.ifChange.outputs.changed == 'yes'
uses: peter-evans/create-pull-request@v5
with:
token: ${{ secrets.LIT_ROBOT_ACCESS_TOKEN }}
commit-message: 'chore: update sizes'
author: lit-robot <lit-robot@google.com>
committer: lit-robot <lit-robot@google.com>
title: 'chore: update sizes'
body: This PR was auto generated by the update-size-on-main GitHub action.
reviewers: e111077,asyncliz
branch: auto-update-size
# Don't automatically add Ready for Google label until we're ready
# since this will be noisy.

View File

@ -16,5 +16,6 @@ Google's open-source design system.
- [Introduction](docs/intro.md)
- [Roadmap](docs/roadmap.md)
- [Quick start](docs/quick-start.md)
- [Bundle sizes](docs/size.md)
- [Component docs](docs/components/)
- [Browser support and FAQ](docs/support.md)

View File

@ -4,83 +4,92 @@
<!--*
# Document freshness: For more information, see go/fresh-source.
freshness: { owner: 'lizmitchell' reviewed: '2023-12-11' }
freshness: { owner: 'lizmitchell' reviewed: '2023-12-13' }
*-->
<!-- [TOC] -->
This doc tracks important size metrics for Material Web Components.
Sizes are tracked in bundles. A bundle is a single `.js` file for one or more
components that includes all of the JavaScript and CSS needed, minus external
dependencies. We track three metrics:
- **gzip** - minified and compressed. This impacts download size, which can
take longer on slow networks.
take longer over slow networks.
- **minified** - minified and unpacked. This impacts the time it takes a page
to be interactive, which can take longer on some devices.
- **% CSS** - the amount of CSS compared to JavaScript. The bundle includes
both JS and CSS, so this helps track changes to JS logic and CSS styles
separately.
<!-- Autogenerated below, do not update! -->
<!-- MWC_UPDATE_TRACKING_START -->
<small>Last updated 2023-12-12.</small>
<sub>Last updated 2023-12-13.</sub>
<!-- mdformat off(autogenerated might break rendering in catalog) -->
Component | gzip | minified | Import
--- | --- | --- | ---
**All** | **70.0kb** | 451.6kb <small>*(66% CSS)*</small> | *@material/web/all.js*
**Common** | **51.4kb** | 281.9kb <small>*(54% CSS)*</small> | *@material/web/common.js*
**Button** | **8.0kb** | 46.3kb <small>*(66% CSS)*</small> |
| 6.7kb | 27.4kb <small>*(49% CSS)*</small> | *@material/web/button/elevated-button.js*
| 6.6kb | 27.3kb <small>*(49% CSS)*</small> | *@material/web/button/filled-button.js*
| 6.7kb | 27.7kb <small>*(49% CSS)*</small> | *@material/web/button/filled-tonal-button.js*
| 6.4kb | 25.7kb <small>*(48% CSS)*</small> | *@material/web/button/outlined-button.js*
| 6.2kb | 24.2kb <small>*(45% CSS)*</small> | *@material/web/button/text-button.js*
**Checkbox** | **7.0kb** | 28.5kb <small>*(43% CSS)*</small> | *@material/web/checkbox/checkbox.js*
**Chips** | **9.9kb** | 60.1kb <small>*(64% CSS)*</small> |
| 4.8kb | 16.4kb <small>*(22% CSS)*</small> | *@material/web/chips/chip-set.js*
| 6.3kb | 26.8kb <small>*(51% CSS)*</small> | *@material/web/chips/assist-chip.js*
| 7.8kb | 36.7kb <small>*(56% CSS)*</small> | *@material/web/chips/filter-chip.js*
| 7.3kb | 33.6kb <small>*(54% CSS)*</small> | *@material/web/chips/input-chip.js*
| 6.4kb | 27.2kb <small>*(51% CSS)*</small> | *@material/web/chips/suggestion-chip.js*
**Dialog** | **4.2kb** | 15.2kb <small>*(36% CSS)*</small> | *@material/web/dialog/dialog.js*
**Divider** | **0.7kb** | 1.4kb <small>*(39% CSS)*</small> | *@material/web/divider/divider.js*
**Elevation** | **0.7kb** | 1.7kb <small>*(62% CSS)*</small> | *@material/web/elevation/elevation.js*
**Fab** | **6.9kb** | 37.1kb <small>*(67% CSS)*</small> |
| 6.6kb | 32.8kb <small>*(64% CSS)*</small> | *@material/web/fab/fab.js*
| 5.8kb | 24.6kb <small>*(51% CSS)*</small> | *@material/web/fab/branded-fab.js*
**Field** | **6.0kb** | 40.5kb <small>*(83% CSS)*</small> |
| 4.6kb | 24.8kb <small>*(75% CSS)*</small> | *@material/web/field/filled-field.js*
| 5.0kb | 27.1kb <small>*(76% CSS)*</small> | *@material/web/field/outlined-field.js*
**Focus** | **1.6kb** | 5.2kb <small>*(46% CSS)*</small> | *@material/web/focus/md-focus-ring.js*
**Icon** | **0.7kb** | 1.3kb <small>*(46% CSS)*</small> | *@material/web/icon/icon.js*
**Icon button** | **7.3kb** | 42.0kb <small>*(65% CSS)*</small> |
| 5.8kb | 23.1kb <small>*(42% CSS)*</small> | *@material/web/iconbutton/icon-button.js*
| 6.0kb | 25.0kb <small>*(45% CSS)*</small> | *@material/web/iconbutton/filled-icon-button.js*
| 6.0kb | 25.5kb <small>*(46% CSS)*</small> | *@material/web/iconbutton/filled-tonal-icon-button.js*
| 6.0kb | 24.6kb <small>*(45% CSS)*</small> | *@material/web/iconbutton/outlined-icon-button.js*
**List** | **6.9kb** | 27.2kb <small>*(35% CSS)*</small> |
| 1.6kb | 4.5kb <small>*(5% CSS)*</small> | *@material/web/list/list.js*
| 5.8kb | 23.0kb <small>*(40% CSS)*</small> | *@material/web/list/list-item.js*
**Menu** | **13.5kb** | 53.9kb <small>*(23% CSS)*</small> |
| 7.9kb | 28.8kb <small>*(17% CSS)*</small> | *@material/web/menu/menu.js*
| 6.5kb | 25.6kb <small>*(37% CSS)*</small> | *@material/web/menu/menu-item.js*
| 8.4kb | 31.9kb <small>*(11% CSS)*</small> | *@material/web/menu/sub-menu.js*
**Progress** | **3.5kb** | 13.9kb <small>*(70% CSS)*</small> |
| 2.6kb | 8.6kb <small>*(64% CSS)*</small> | *@material/web/progress/linear-progress.js*
| 2.2kb | 7.4kb <small>*(57% CSS)*</small> | *@material/web/progress/circular-progress.js*
**Radio** | **6.9kb** | 26.0kb <small>*(31% CSS)*</small> | *@material/web/radio/radio.js*
**Ripple** | **2.8kb** | 7.9kb <small>*(14% CSS)*</small> | *@material/web/ripple/ripple.js*
**Select** | **25.6kb** | 142.5kb <small>*(57% CSS)*</small> |
| 17.8kb | 89.3kb <small>*(48% CSS)*</small> | *@material/web/select/filled-select.js*
| 18.1kb | 89.9kb <small>*(48% CSS)*</small> | *@material/web/select/outlined-select.js*
| 6.6kb | 26.6kb <small>*(36% CSS)*</small> | *@material/web/select/select-option.js*
**Slider** | **9.7kb** | 45.0kb <small>*(49% CSS)*</small> | *@material/web/slider/slider.js*
**Switch** | **7.8kb** | 34.8kb <small>*(53% CSS)*</small> | *@material/web/switch/switch.js*
**Tabs** | **7.9kb** | 35.1kb <small>*(50% CSS)*</small> |
| 6.2kb | 21.9kb <small>*(25% CSS)*</small> | *@material/web/tabs/tabs.js*
| 6.3kb | 25.6kb <small>*(48% CSS)*</small> | *@material/web/tabs/primary-tab.js*
| 6.2kb | 25.2kb <small>*(48% CSS)*</small> | *@material/web/tabs/secondary-tab.js*
**Text field** | **13.7kb** | 93.0kb <small>*(74% CSS)*</small> |
| 10.7kb | 60.8kb <small>*(62% CSS)*</small> | *@material/web/textfield/filled-text-field.js*
| 10.9kb | 61.3kb <small>*(62% CSS)*</small> | *@material/web/textfield/outlined-text-field.js*
Component | gzip | minified | *% CSS* | Import
--- | --- | --- | --- | ---
**All** | **70.0kb** | 451.6kb | *66% CSS* | `@material/web/all.js`
**Common** | **51.4kb** | 281.9kb | *54% CSS* | `@material/web/common.js`
**Button** | **8.0kb** | 46.3kb | *66% CSS* |
| 6.7kb | 27.4kb | *49% CSS* | `@material/web/button/elevated-button.js`
| 6.6kb | 27.3kb | *49% CSS* | `@material/web/button/filled-button.js`
| 6.7kb | 27.7kb | *49% CSS* | `@material/web/button/filled-tonal-button.js`
| 6.4kb | 25.7kb | *48% CSS* | `@material/web/button/outlined-button.js`
| 6.2kb | 24.2kb | *45% CSS* | `@material/web/button/text-button.js`
**Checkbox** | **7.0kb** | 28.5kb | *43% CSS* | `@material/web/checkbox/checkbox.js`
**Chips** | **9.9kb** | 60.1kb | *64% CSS* |
| 4.8kb | 16.4kb | *22% CSS* | `@material/web/chips/chip-set.js`
| 6.3kb | 26.8kb | *51% CSS* | `@material/web/chips/assist-chip.js`
| 7.8kb | 36.7kb | *56% CSS* | `@material/web/chips/filter-chip.js`
| 7.3kb | 33.6kb | *54% CSS* | `@material/web/chips/input-chip.js`
| 6.4kb | 27.2kb | *51% CSS* | `@material/web/chips/suggestion-chip.js`
**Dialog** | **4.2kb** | 15.2kb | *36% CSS* | `@material/web/dialog/dialog.js`
**Divider** | **0.7kb** | 1.4kb | *39% CSS* | `@material/web/divider/divider.js`
**Elevation** | **0.7kb** | 1.7kb | *62% CSS* | `@material/web/elevation/elevation.js`
**Fab** | **6.9kb** | 37.1kb | *67% CSS* |
| 6.6kb | 32.8kb | *64% CSS* | `@material/web/fab/fab.js`
| 5.8kb | 24.6kb | *51% CSS* | `@material/web/fab/branded-fab.js`
**Field** | **6.0kb** | 40.5kb | *83% CSS* |
| 4.6kb | 24.8kb | *75% CSS* | `@material/web/field/filled-field.js`
| 5.0kb | 27.1kb | *76% CSS* | `@material/web/field/outlined-field.js`
**Focus** | **1.6kb** | 5.2kb | *46% CSS* | `@material/web/focus/md-focus-ring.js`
**Icon** | **0.7kb** | 1.3kb | *46% CSS* | `@material/web/icon/icon.js`
**Icon button** | **7.3kb** | 42.0kb | *65% CSS* |
| 5.8kb | 23.1kb | *42% CSS* | `@material/web/iconbutton/icon-button.js`
| 6.0kb | 25.0kb | *45% CSS* | `@material/web/iconbutton/filled-icon-button.js`
| 6.0kb | 25.5kb | *46% CSS* | `@material/web/iconbutton/filled-tonal-icon-button.js`
| 6.0kb | 24.6kb | *45% CSS* | `@material/web/iconbutton/outlined-icon-button.js`
**List** | **6.9kb** | 27.2kb | *35% CSS* |
| 1.6kb | 4.5kb | *5% CSS* | `@material/web/list/list.js`
| 5.8kb | 23.0kb | *40% CSS* | `@material/web/list/list-item.js`
**Menu** | **13.5kb** | 53.9kb | *23% CSS* |
| 7.9kb | 28.8kb | *17% CSS* | `@material/web/menu/menu.js`
| 6.5kb | 25.6kb | *37% CSS* | `@material/web/menu/menu-item.js`
| 8.4kb | 31.9kb | *11% CSS* | `@material/web/menu/sub-menu.js`
**Progress** | **3.5kb** | 13.9kb | *70% CSS* |
| 2.6kb | 8.6kb | *64% CSS* | `@material/web/progress/linear-progress.js`
| 2.2kb | 7.4kb | *57% CSS* | `@material/web/progress/circular-progress.js`
**Radio** | **6.9kb** | 26.0kb | *31% CSS* | `@material/web/radio/radio.js`
**Ripple** | **2.8kb** | 7.9kb | *14% CSS* | `@material/web/ripple/ripple.js`
**Select** | **25.6kb** | 142.5kb | *57% CSS* |
| 17.8kb | 89.3kb | *48% CSS* | `@material/web/select/filled-select.js`
| 18.1kb | 89.9kb | *48% CSS* | `@material/web/select/outlined-select.js`
| 6.6kb | 26.6kb | *36% CSS* | `@material/web/select/select-option.js`
**Slider** | **9.7kb** | 45.0kb | *49% CSS* | `@material/web/slider/slider.js`
**Switch** | **7.8kb** | 34.8kb | *53% CSS* | `@material/web/switch/switch.js`
**Tabs** | **7.9kb** | 35.1kb | *50% CSS* |
| 6.2kb | 21.9kb | *25% CSS* | `@material/web/tabs/tabs.js`
| 6.3kb | 25.6kb | *48% CSS* | `@material/web/tabs/primary-tab.js`
| 6.2kb | 25.2kb | *48% CSS* | `@material/web/tabs/secondary-tab.js`
**Text field** | **13.7kb** | 93.0kb | *74% CSS* |
| 10.7kb | 60.8kb | *62% CSS* | `@material/web/textfield/filled-text-field.js`
| 10.9kb | 61.3kb | *62% CSS* | `@material/web/textfield/outlined-text-field.js`
<!-- mdformat on(autogenerated might break rendering in catalog) -->

View File

@ -6,9 +6,9 @@
import * as fs from 'fs/promises';
import {MarkdownTable} from '../analyzer/markdown-tree-builder.js';
import {COMPONENT_CUSTOM_ELEMENTS} from '../component-custom-elements.js';
import {Bundle, Size, getBundleSize} from './bundle-size.js';
import { MarkdownTable } from '../analyzer/markdown-tree-builder.js';
import { COMPONENT_CUSTOM_ELEMENTS } from '../component-custom-elements.js';
import { Bundle, Size, getBundleSize } from './bundle-size.js';
// The bundles to track sizes for.
@ -28,7 +28,7 @@ const bundles: Bundle[] = [
).map((component) => {
const tsCustomElementPaths = COMPONENT_CUSTOM_ELEMENTS[component];
const jsCustomElementPaths = tsCustomElementPaths.map((tsPath) =>
tsPath.replace(/\.ts$/, '.js'),
tsPath.replace(/\.ts$/, '.js')
);
return {
@ -41,19 +41,20 @@ const bundles: Bundle[] = [
// Compute bundle sizes.
const bundleSizes = await Promise.all(
bundles.map((bundle) => getBundleSize(bundle)),
bundles.map((bundle) => getBundleSize(bundle))
);
// Create a markdown table with size data.
const columns = ['Component', 'gzip', 'minified', 'Import'];
const columns = ['Component', 'gzip', 'minified', '*% CSS*', 'Import'];
const rows: string[][] = [];
for (const {name, size, inputs} of bundleSizes) {
for (const { name, size, inputs } of bundleSizes) {
rows.push([
`**${camelToSentenceCase(name)}**`,
`**${bytesToString(size.gzip)}**`,
getJsAndCss(size),
inputs.length === 1 ? `*${getImport(inputs[0].input)}*` : '',
bytesToString(size.raw),
getCssPercent(size),
inputs.length === 1 ? getImport(inputs[0].input) : '',
]);
if (inputs.length > 1) {
@ -61,11 +62,12 @@ for (const {name, size, inputs} of bundleSizes) {
...inputs.map((input) => {
return [
'',
`${bytesToString(input.size.gzip)}`,
`${getJsAndCss(input.size)}`,
`*${getImport(input.input)}*`,
bytesToString(input.size.gzip),
bytesToString(input.size.raw),
getCssPercent(input.size),
getImport(input.input),
];
}),
})
);
}
}
@ -77,7 +79,7 @@ for (const row of rows) {
// Update markdown file.
const markdownContent = await fs.readFile('docs/size.md', {encoding: 'utf8'});
const markdownContent = await fs.readFile('docs/size.md', { encoding: 'utf8' });
const updateTrackingStart = '<!-- MWC_UPDATE_TRACKING_START -->';
const updateTrackingEnd = '<!-- MWC_UPDATE_TRACKING_END -->';
@ -88,7 +90,7 @@ const newMarkdownContent = [
markdownContent.substring(0, markdownContent.indexOf(updateTrackingStart)),
updateTrackingStart,
'\n\n',
`<small>Last updated ${nowString}.</small>\n\n`,
`<sub>Last updated ${nowString}.</sub>\n\n`,
markdownTable.toString(),
'\n\n',
markdownContent.substring(markdownContent.indexOf(updateTrackingEnd)),
@ -99,23 +101,17 @@ await fs.writeFile('docs/size.md', newMarkdownContent);
// Text formatting functions for markdown table.
function getImport(input: string) {
return `@material/web/${input}`;
return `\`@material/web/${input}\``;
}
function getCssPercent(size: Size) {
return `${Math.round((size.css / size.raw) * 100)}%`;
return `*${Math.round((size.css / size.raw) * 100)}% CSS*`;
}
function bytesToString(bytes: number) {
return `${(Math.round(bytes / 100) / 10).toFixed(1)}kb`;
}
function getJsAndCss(size: Size) {
return `${bytesToString(size.raw)} <small>*(${getCssPercent(
size,
)} CSS)*</small>`;
}
function camelToSentenceCase(value: string) {
const withSpaces = value.replaceAll(/([a-z])([A-Z])/g, '$1 $2');
return withSpaces[0].toUpperCase() + withSpaces.slice(1).toLowerCase();