Kompilowany, atomowy CSS dla Angulara w duchu StyleX: style w *.sx.ts, zerowy runtime
kompilacji, deterministyczne klasy, @layer zamiast wojen specyficzności.
Status: spike (etap 5a planu). Nie używać produkcyjnie.
Weryfikacja hipotezy: custom builder (wrapper na @angular/build) + plugin esbuild
onResolve/onLoad kompiluje *.sx.ts przed bundlowaniem, bez dotykania ngtsc.
| Kryterium | Status |
|---|---|
ng build dev i prod przechodzi |
OK |
bundle nie zawiera sx.create( ani stubu runtime (tree-shaking) |
OK |
style jako literały {$$css:!0,display:"sx-149y8yo",...} |
OK |
CSS z @layer ngsx.base, ngsx.pseudo w styles.css |
OK |
| błąd kompilacji z pozycją dla nie-literału | OK |
sourcemapa wskazuje na src/app/app.sx.ts |
OK |
ng serve: edycja .sx.ts -> nowy kod i CSS w ~2 s |
OK |
ng serve: nowy plik .sx.ts bez restartu |
OK |
| Playwright e2e | nie uruchomiono w sandboxie (brak dostępu do CDN z przeglądarkami); npm run e2e |
npm install # postinstall kopiuje schematy builderów z @angular/build
npm run build # prod
npm start # ng serve
npm run e2e # Playwright (wymaga: npx playwright install chromium)
executeDevServerBuilder(options, context, extensions?), bezbuilderSelector. Nazwa buildera zbuildTargetsłuży tylko do walidacji opcji schematem, dlategoscripts/sync-schema.cjskopiujeschema.jsonz@angular/build(jak custom-esbuild).- Namespace
file, ścieżka bez.ts.onLoadAngulara nie podaje namespace, więc wg dokumentacji esbuild działa w każdym. Ratuje nas filtr po rozszerzeniu:src/app/app.sxnie pasuje do regexa Angulara. Własny namespace odrzucony, bo klucz metafilens:/abs/pathtrafia przezjoin(workspaceRoot, input)do watchera jako bogus ścieżka. - Generowany CSS nie może leżeć w dot-katalogu. Watcher Angulara ignoruje
${workspaceRoot}/**/.*/**..ngsx/ngsx.cssnigdy nie było obserwowane, stądsrc/ngsx.generated.css(w.gitignore). - Pre-pass jest konieczny dla
ng build. Kontekst globalnych stylów buduje się równolegle z kodem; bez wcześniejszego zapisu CSS pierwszy build miałby pusty arkusz. - Koszt watch: dwie przebudowy na edycję (kod, potem styles po zapisie CSS w
onEnd). Obie poniżej 0,5 s. Zapis tylko przy zmianie treści, inaczej pętla.
Literały string/number, warunki { default, ':pseudo' }, jednostka px dla liczb poza
listą unitless. Brak: zmienne, spread, defineVars, media queries, style dynamiczne.
Hash FNV-1a (spike); docelowo murmurhash3 w @ngsx/shared.
tools/ngsx-builder/src/
compiler.cjs ewaluacja sx.create -> literał + reguły CSS (magic-string, TS API)
esbuild-plugin.cjs onResolve ./x.sx -> onLoad kompilacja, watchFiles, onEnd zapis CSS
bootstrap.cjs pre-pass + zapis CSS przed startem builda
application.cjs buildApplication(options, context, { codePlugins })
dev-server.cjs executeDevServerBuilder(options, context, { buildPlugins })
src/ngsx/core.ts create() tylko dla typów + attrs() (jedyny runtime, ~20 linii)
src/ngsx/sx.directive.ts [sx] -> host [class]
src/app/app.sx.ts style testowe; app.ts używa [sx]
e2e/spike.spec.ts computed style, :hover, merge, brak sx.create w bundlu
- Ścieżka
src/app/app.sx(bez.ts) trafia dowatchFilesAngulara jako nieistniejący plik. Nieszkodliwe, ale do obserwacji przy większej liczbie plików. - Pliki
.sx.tsmuszą być wtsconfig.app.jsoninclude, żeby ngtsc je typował. ng test(unit-test builder) nie ma jeszcze wrappera.