mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-14 21:26:15 -08:00
perf(web): lower the initial-bytes baseline to 1,345,810 and document the startup-path rules
The five previous commits took Angular Material off the renderer's startup path: renderer.initialBytes went from 1,596,201 to 1,344,067 bytes (-252,134, 15.8%) on a local production build at the branch point, measured with `pnpm nx build web --skip-nx-cache --output-path=dist/measure-web --stats-json` after each commit. Rebased onto master (#1905 adds 1,743 bytes of backup code to the initial path), the branch measures 1,345,810, and the baseline follows that; the ratchet and direction checks pass against it. evidencePr is filled in once the pull request exists. The performance contract explains the chunk-level rule behind the work, and the UI guidelines gain a "Material off the startup path" section with the form-field, dialog, deferred panel, theme scope and animations rules and the guards that keep them. The release note covers the user-visible effect. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
85c5a078fb
commit
dee1d04a70
4 files changed
+71
-3
No files matched your search
@@ -0,0 +1,9 @@
|
||||
---
|
||||
type: perf
|
||||
area: web
|
||||
---
|
||||
|
||||
The app loads about 15% less code before it shows its first screen: form
|
||||
field, dialog, tooltip and progress-bar code, the animation engine and the
|
||||
theme colours of unused components now load only when something needs them,
|
||||
so every launch has less to download and parse.
|
||||
@@ -88,6 +88,47 @@ tokens, so the retired `--mdc-*` names compile but do nothing;
|
||||
a spec loads as raw CSS cannot use Sass modules; it declares the `--mat-*`
|
||||
token directly and says why.
|
||||
|
||||
### Material off the startup path
|
||||
|
||||
`renderer.initialBytes` ([performance journeys](performance-journeys.md#rendererinitialbytes))
|
||||
counts every module an eager file imports, and the bundler keeps a module in
|
||||
one chunk, so one import of one export carries the whole module. Material
|
||||
therefore reaches the initial bundle only through the snack-bar, which root
|
||||
services inject (and with it `button`, the icon button and the CDK overlay).
|
||||
Everything else is lazy by these rules:
|
||||
|
||||
- **Form-field defaults.** Import `AppFormFieldModule`
|
||||
(`@iptvnator/ui/components/form-field`) instead of `MatFormFieldModule`
|
||||
wherever a template renders `<mat-form-field>`: it exports Material's form
|
||||
field with a directive that provides the app defaults (outlined, dynamic
|
||||
subscript) on the element. The defaults are not a root provider, and a
|
||||
route-level one would miss dialogs opened by root services.
|
||||
`pnpm run styles:form-field-defaults:validate` (CI) rejects a component that
|
||||
renders a form field without the module.
|
||||
- **Dialogs from services created with the app.** A root service that opens a
|
||||
dialog resolves `MatDialog` through `LazyMatDialog`
|
||||
(`@iptvnator/ui/components/lazy-dialog`) and imports the dialog component
|
||||
on demand, as `DialogService`, the player service, the parental lock prompt
|
||||
and the workspace shell actions do; `openConfirmDialog` returns a promise
|
||||
that settles once the dialog is open. A component in a lazy chunk injects
|
||||
`MatDialog` directly.
|
||||
- **Panels the shell mounts on every launch.** The EPG progress panel and the
|
||||
update notification are an eager host with `@defer (when visible)` around
|
||||
the view that imports Material; the startup status draws its spinner as
|
||||
static markup copied from `mat-spinner`. A new always-mounted component
|
||||
follows the same split.
|
||||
- **Theme scope.** `m3-theme.scss` themes only the components in its
|
||||
`$material-components` list, through `meta.apply` for both the light theme
|
||||
and the dark colours. Add an entry with a new `@angular/material/<entry>`
|
||||
import and remove it with the last one;
|
||||
`pnpm run styles:material-theme-scope:validate` (CI) checks both directions
|
||||
(`core` always stays, `button` brings `icon-button` and `fab`).
|
||||
- **No animations module.** Nothing declares an Angular animation trigger and
|
||||
Material 22 animates with CSS, deciding from `prefers-reduced-motion` itself,
|
||||
so `app.config.ts` does not call `provideAnimations()`; the Electron
|
||||
`material-motion.e2e.ts` checks that dialogs, selects, menus, snack-bars and
|
||||
tooltips still animate in and out and stop under reduced motion.
|
||||
|
||||
The app theme is the `.dark-theme` class that `SettingsService` puts on
|
||||
`<body>`; a "System" choice resolves the OS preference there and nowhere
|
||||
else. Component styles never use a `prefers-color-scheme` query, which
|
||||
|
||||
@@ -1156,6 +1156,24 @@ every build, which only the `development`, `electron-e2e` and
|
||||
`performance-build-config.spec.ts` keeps it that way. Removing the static
|
||||
import lowered the counter by 12,565 bytes.
|
||||
|
||||
The bundler keeps each module in one chunk, so one eager import of any
|
||||
export carries the module's whole code: providing
|
||||
`MAT_FORM_FIELD_DEFAULT_OPTIONS` in `app.config.ts` alone put the 54 KB
|
||||
form-field chunk on the initial path, although every form field renders in a
|
||||
lazy route or dialog. Angular Material therefore stays off the startup path by
|
||||
construction, with the rules and guards in the
|
||||
[UI guidelines](iptvnator-ui-guidelines.md#material-off-the-startup-path):
|
||||
form-field defaults travel with `AppFormFieldModule`, services created with
|
||||
the app resolve `MatDialog` through `LazyMatDialog`, the panels the shell
|
||||
mounts on every launch defer their Material views, the theme emits tokens only
|
||||
for imported components, and the app does not provide the animations module,
|
||||
which nothing used (Material 22 animates with CSS). Together these lowered the
|
||||
counter from 1,596,201 to 1,344,067 bytes (-252,134, 15.8%) on a local
|
||||
production build at the branch point; the baseline follows the measurement
|
||||
of the branch rebased onto `master`, 1,345,810. The snack-bar stays: root
|
||||
services inject it, and with it Material's button, the icon button chunk and
|
||||
the CDK overlay (about 190 KB) remain initial.
|
||||
|
||||
`--summary` writes the journey summary shape (`journeys.<journey>.counters`)
|
||||
that the ratchet checker consumes. `--dist <dir>` points the script at another
|
||||
build output, for example the `electron-performance` configuration.
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
"journeys": {
|
||||
"launch": {
|
||||
"renderer.initialBytes": {
|
||||
"value": 1595777,
|
||||
"value": 1345810,
|
||||
"unit": "bytes",
|
||||
"slack": 4096,
|
||||
"updatedAt": "2026-10-07",
|
||||
"evidencePr": 1810,
|
||||
"updatedAt": "2026-10-13",
|
||||
"evidencePr": null,
|
||||
"measuredWith": "pnpm nx build web && pnpm run perf:initial-bytes"
|
||||
},
|
||||
"renderer.ipcCallsToFirstCard": {
|
||||
|
||||
Reference in new issue
Block a user