perf(web): keep lazy-only services and SafePipe out of main.js

The eager shell imported barrels that re-export Angular injectables and a
pipe it never uses, and their static definitions keep those modules in
main.js: PlaylistFileImportService came with PlaylistContextFacade,
normalizeDateLocale with SafePipe, and the workspace-shell-util barrel with
SettingsContextService, which #1714 grew with match counts. That growth put
master 108 bytes over the renderer.initialBytes baseline #1712 had measured
on a branch without #1714.

Add file-level entries for the three modules and use them from the eager
and settings code: renderer.initialBytes 1,626,127 -> 1,619,993 bytes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
4grayandClaude Opus 5.5 committed 2026-09-27 11:17:43 +02:00
1 parent 254d1fd922
commit 3aa036d460
12 files changed
+40 -16

No files matched your search

+11 -4
View File
@@ -235,18 +235,25 @@ and value-imports those two dependency-free modules directly.
`@iptvnator/workspace/shell/util/settings-search` exists for the opposite
reason: the main `workspace-shell-util` barrel is imported eagerly, and the
settings search index must stay in the lazy settings and shell chunks.
`@iptvnator/workspace/shell/util/settings-context` keeps
`SettingsContextService`, which only the lazy settings page and settings
context panel use, out of that barrel for the same reason.
The web app's root shell (`app.component.ts`, `app.config.ts` and the services
they construct) is on the renderer's initial path, where a barrel costs its
whole library: esbuild keeps every Angular component module a barrel
re-exports, because their static definitions count as side effects. Importing
re-exports, because their static definitions count as side effects (so do an
`@Injectable` service's and a pipe's). Importing
`WindowControlsComponent` and `DialogService` from `@iptvnator/ui/components`
once put the channel lists, EPG views, `@angular/forms`, `date-fns` and the
Stalker data layer into `main.js`. The root shell therefore uses file-level
entries: `@iptvnator/ui/components/window-controls`,
`@iptvnator/ui/components/confirm-dialog` and
`@iptvnator/playlist/shared/ui/stalker-connection-editor` (like the existing
`@iptvnator/ui/epg/progress-panel`), and loads anything used only on demand
`@iptvnator/ui/components/confirm-dialog`,
`@iptvnator/playlist/shared/ui/stalker-connection-editor`,
`@iptvnator/playlist/shared/util/playlist-file-import` (the barrel would add
`PlaylistContextFacade`) and `@iptvnator/pipes/date-format` (the barrel would
add `SafePipe`; the eager EPG progress panel uses it too), like the existing
`@iptvnator/ui/epg/progress-panel`, and loads anything used only on demand
through a local file it imports dynamically (the Stalker connection editor,
the release-notes dialog, the external-player info dialog). A local file,
not the library alias, is the dynamic-import target because
+11
View File
@@ -273,6 +273,17 @@ the first measurements was otherwise `package.json` text embedded in
`main.js`, which moved with every script edit; #1692 fixed that by importing
only the version.)
Two effects make the exact counter move for reasons outside a PR's own diff.
A baseline lowered on a branch that predates a concurrent `master` merge can
sit below what the merged code measures: #1712 lowered it on a branch without
#1714, so `master` measured 108 bytes over and every later PR failed the job
until a follow-up moved lazy-only modules out of `main.js`. Re-run the job on
an up-to-date branch before merging a baseline change. And the bundler's
chunk-level identifier renaming shifts when a module enters or leaves
`main.js`: moving one service out once renamed an imported identifier at 162
call sites, eating about 320 of the bytes saved. Judge a small change by the
`--stats-json` input sizes, not only by the counter.
The job also refuses a weakened baselines file:
`tools/performance/check-baseline-direction.mjs` compares
`journey-baselines.json` with the revision the change is measured against