Skip to content

fix(wasm): align deterministic atom hoist names - #751

Open
owjs3901 wants to merge 18 commits into
mainfrom
fix/atom-hoist-names
Open

owjs3901 wants to merge 18 commits into
mainfrom
fix/atom-hoist-names

Conversation

@owjs3901

@owjs3901 owjs3901 commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Refs #694, #686 (W29). #743 (feat/deterministic-numbering) 위에 쌓은 PR이며, #743이 먼저 병합되어야 합니다. PR base는 요청대로 main입니다.

요약

atomHoist에서 JSX는 a-a/b-a를 참조하지만 공유 CSS는 .a/.b만 정의하던 오류를 수정합니다. 클래스 이름과 배치는 추출 순서가 아니라, 원자 스타일의 내용과 추출 전에 확정한 canonical bucket의 route reach로 결정합니다.

  • JSX, css(), styled(), StyleX, vanilla-extract, 선택자, 반응형 스타일, 동적 CSS 변수와 keyframes의 참조가 실제 CSS 정의와 일치합니다.
  • 일반 동적 값과 !important 값의 클래스 충돌도 수정합니다.
  • w={["$token"]}/boxShadow={["$token"]}의 첫 값이 JSX와 CSS에서 서로 다른 클래스로 계산되던 오류와, 일반 반응형 변수 토큰과의 충돌을 함께 수정합니다.
  • 공유 규칙이 추가되면 updatedBaseStyle을 전달하여 플러그인이 공유 CSS를 갱신합니다.
  • 플러그인 구현 변경은 계약 설명에 한정하며, Next coordinator와 plugin-utils는 수정하지 않습니다.

동작

호이스팅 여부는 첫 소스를 처리하기 전에 importFileRoutes가 제공한 reach로 고정합니다. threshold 이상인 bucket의 원자는 공유 이름으로 devup-ui.css에 한 번 정의하고, 그 외 원자는 파일 이름 공간과 파일별 CSS를 유지합니다. 나중에 도착한 reach 때문에 이미 출력한 이름이나 배치가 바뀌지 않습니다.

이름은 속성, 정규화한 값, 반응형 level, 선택자/at-rule 구조, layer, style order, 공유/로컬 이름 공간을 충돌 없이 인코딩합니다. atom 모드에서는 debug 여부나 파일 추출 순서로 이름이 바뀌지 않습니다. 변수와 keyframes도 내용으로 이름을 정하며, 파일별 keyframes는 해당 파일의 CSS에 남습니다.

호이스팅 배치와 고정한 계획은 sheet에 저장되어, CSS loader가 현재 atom 설정 없이 sheet를 복원해도 같은 CSS를 출력합니다.

export한 sheet에는 항상 atomNamingVersion: 1을 넣습니다. 추출 전의 빈 sheet나 이전 sheet를 복원한 경우에도 기존 Next loader 옵션의 cache fingerprint가 달라져, 오류가 있던 예전 JSX 캐시를 유지하지 않습니다. 기존 CSS 데이터와 round-trip은 보존합니다.

기존 재현 스크립트의 실제 출력은 ab/ba 모두 다음과 같습니다:

// src/a.tsx
<div className="a1-h-636f6c6f72-0-s-726564-6e2d6e-255" />
// src/b.tsx
<div className="a1-h-6261636b67726f756e64-0-s-626c7565-6e2d6e-255" />
.a1-h-6261636b67726f756e64-0-s-626c7565-6e2d6e-255{background:blue}
.a1-h-636f6c6f72-0-s-726564-6e2d6e-255{color:red}

파일별 CSS는 @import "./devup-ui.css";만 갖고, 두 출력 모두 updatedBaseStyle: true입니다. 공유 클래스 이름과 CSS는 두 순서에서 동일합니다.

바이트와 무효화 비용

8개 route, 모든 route가 미리 도달하는 공유 모듈 32개, 모듈마다 동일 원자 80개, route마다 고유 원자 25개인 fixture를 측정했습니다. threshold는 2이며, 공통 상수 한 개가 바뀌어 공유 소비자 32개의 선언이 바뀌는 새 배포 빌드를 비교합니다. gzip은 파일마다 압축하여 합산했고, header와 import-only 파일도 포함했습니다.

지표 정상 파일별 CSS (atom off) 수정 전 atom on (오류) 수정 후 atom on
전체 CSS raw bytes 69,604 10,030 30,352
전체 CSS gzip bytes 19,122 5,724 7,317
CSS 정의가 없는 생성 클래스 참조 0 2,760 0
route가 읽는 CSS raw bytes 64,816 5,418-5,443 11,515
route가 읽는 CSS gzip bytes 17,271-17,274 3,868-3,880 4,262-4,270
route가 읽는 CSS 파일 수 34 34 34
배포 후 바뀐 CSS 파일 수 32 1 1
다시 받는 CSS raw bytes 64,064 1,808 5,848
다시 받는 CSS gzip bytes 16,980 479 701

충돌 없는 이름 때문에 수정 전의 잘못된 출력보다 raw 20,322 bytes, gzip 1,593 bytes가 증가합니다. 대신 적용되지 않던 2,760개 참조를 모두 복구합니다. 정상 파일별 CSS와 비교하면 raw 39,252 bytes, gzip 11,805 bytes를 줄입니다. CSS 요청 수가 줄었다고 주장하지 않습니다.

기존의 일괄 30% 무효화 주장은 늦은 원자 합집합과 정의되지 않은 클래스가 포함된 fixture에서 나온 것이므로 그대로 유지하지 않았습니다. 새 Rust fixture는 실제 참조/선언 일치, 32회 선언 대 1회 선언, 32개 변경 파일 대 1개 변경 파일, 제거되는 선언 payload로 계산한 바이트 절감을 검증합니다. 이름 길이 비용도 계산에 포함합니다.

새로 생기는 오류

없습니다. 런타임 스타일 평가나 의존성을 추가하지 않습니다.

남는 한계

  • 서로 다른 단일-route 파일에서만 우연히 같은 원자를 사용하면 호이스팅하지 않습니다. route map만으로는 추출 전에 원자 내용의 합집합을 알 수 없고, 나중에 이름을 바꾸면 이미 출력한 JSX가 깨지기 때문입니다.
  • 늦게 발견한 reach는 다음 resetBuildState까지 로컬로 유지합니다.
  • 기존 additive HMR sheet는 이전 literal 규칙을 이전 이름으로 보관합니다. 이 PR은 새 참조가 그 규칙과 충돌하지 않게 하며, 배포 측정은 상태를 비운 새 빌드끼리 비교합니다.
  • 범위 밖의 기존 문제: Next graph의 cwd/src 고정으로 root App/Pages layout reach가 빠지는 경우, codeExtractWithoutSourceMap이 source map을 생성하는 INF-06, CSS 버전 header의 기존 쉼표. coordinator/plugin-utils 담당 영역은 변경하지 않았습니다.

검증

  • cargo fmt --all, Rust 1.99 workspace/all-target Clippy 통과
  • cargo test --workspace: 2,154 통과, 실패 없음; snapshot 변경은 저장한 atom_plan/hoisted 필드 2개뿐
  • WASM 재빌드와 루트 bun run build 통과
  • bun test: 5,530 통과, 실패 없음, 함수/라인 커버리지 100%
  • Next/Rsbuild/Vite 실제 플러그인 설정·hook·loader 테스트: 각 추출 순서와 새 프로세스 재빌드 모두 통과
  • 공개 WASM API 프로브: JSX/css()/styled()/StyleX, 동적 priority, keyframes, 선택자/반응형, 공유/로컬, debug/prefix, 늦은 reach, 새 빌드, import한 vanilla-extract 모듈 참조 확인
  • 반응형 토큰 배열 프로브: atom off/on 모두 첫 값 선언과 참조 일치
  • 이전/빈 sheet 프로브: naming version으로 캐시 fingerprint 변경, CSS/round-trip 보존
  • bun lint: 기존 경고 2개 외 오류/새 경고 없음
  • Rust LSP daemon은 timeout, TypeScript LSP는 미설치여서 clean diagnostics라고 주장하지 않음; 컴파일러와 Clippy로 검증
  • 최종 코드/실제 출력 gate review: Oracle APPROVE, HIGH confidence, 차단 항목 없음

W30 통합 업데이트: 이 브랜치는 main의 a935315c까지 포함합니다 (#747 vinext/RSC CSS 보존 및 #700 버전 업데이트).

W30 최종 CI

  • 최종 head: aaab75652615aedae65ec102e3576ea05b3c3c33, main의 a935315c까지 포함; MERGEABLE/CLEAN 확인
  • CI run 37177129245: success, publish / landing-next-e2e / vinext-rsc-css-e2e / benchmark 모두 통과
  • Ubuntu Rust 커버리지 100% (10042/10042), Bun 5530 통과 / 0 실패, 함수·라인 커버리지 100%
  • 로컬 vinext RSC 재현: per-file / singleCss 각각 29 통과; main의 RSC 전달/복원 구현은 byte-for-byte 유지
  • 추가 빌드 오류/의존성 없음; PR 병합/승인은 수행하지 않음
  • 최초 W30 CI의 미실행 경로 2개는 세 파일 route union 및 이전 로컬/새 호이스팅 원자가 같은 bucket에 공존하는 실제 회귀 테스트로 검증했습니다; production 동작이나 제외 설정은 변경하지 않았습니다.

owjs3901 and others added 18 commits October 1, 2026 01:50
…nd StyleX imports

The generated stylesheet always resolved to an empty module, so Bun.build dropped every style, and the pre-parse gate only accepted import declarations of @devup-ui/react, so files using the alias packages, StyleX, subpaths or re-exports ran the runtime stubs. DevupUI() now serves the complete sheet to the CSS loader after defer(), and the gate reads the real imports with Bun.Transpiler.scanImports.

Refs #686

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
… built stylesheets

A stylesheet module is built on its first import, and the shared base is read from disk past the plugin, so styles extracted later were missing from webpack and Rsbuild output; Rsbuild also served a module-wide string kept only when it grew. The files the entries reach are now extracted before the build, the base on disk is kept current, and a compilation whose stylesheets changed is run once more, writing only the complete result. Rsbuild serves each stylesheet from the current sheet.

Refs #686

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…into feat/deterministic-numbering

# Conflicts:
#	packages/next-plugin/src/loader.ts
…ing order

Refs #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
… forwarding alone

Refs #694

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #694, #686

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #694, #686

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #694, #686

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #694, #686

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #694, #686

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #694, #686

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #694, #686

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #694, #686

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Refs #694, #686

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Changepacks

@devup-ui/wasm@1.0.83 → 1.0.84 - bindings/devup-ui-wasm/package.json

Patch

  • Make atomHoist class names deterministic and match generated references to emitted CSS, freeze hoisting from predeclared route reach, and preserve dynamic !important, keyframes, and first-value responsive-token identities. No new build errors.
  • Class names and file numbers no longer depend on the order files are processed in. Every plugin walks the files it can extract (the project's source and the included packages) before the first transform and numbers them in path order (a file collapsed into a bucket is numbered as the bucket, and only files that mention the package, StyleX or an aliased package take numbers) through the new seedFileMap, so identical builds give identical class prefixes, CSS file names and output hashes; in development, files that appear later are numbered after the existing ones. Styles are given class names in a fixed order, not the order of a hash set. The exported class, file and canonical maps are canonical JSON (sorted keys). Stylesheet evaluation (vanilla-extract) refuses Math.random(), Date.now(), new Date() and Date(), which differ between builds, with a build error; fixed dates such as new Date(0) are unchanged. resetBuildState starts a build from its own options: the prefix, atom hoisting, routes, buckets, names, numbers and styles an earlier build in the process left are cleared, and the prefix is set on every setup even when it is absent. Engine snapshots from concurrent transforms are written one after another per file, so an older snapshot is never written last. File lists are ordered by code point rather than the locale

@devup-ui/bun-plugin@1.0.22 → 1.0.23 - packages/bun-plugin/package.json

Patch

  • Bun plugin works with Bun.build: DevupUI() (from @devup-ui/bun-plugin/register) serves the generated stylesheet to the bundler's CSS loader once every other module is loaded, so the build emits a CSS output with the styles of the whole bundle instead of an empty module; class names are short there and readable under the runtime (debug option). Files importing the packages Devup UI takes the place of (@emotion/react, @emotion/styled, styled-components, @vanilla-extract/css), @stylexjs/stylex, or a subpath or re-export of these or @devup-ui/react, are compiled instead of skipped
  • Class names and file numbers no longer depend on the order files are processed in. Every plugin walks the files it can extract (the project's source and the included packages) before the first transform and numbers them in path order (a file collapsed into a bucket is numbered as the bucket, and only files that mention the package, StyleX or an aliased package take numbers) through the new seedFileMap, so identical builds give identical class prefixes, CSS file names and output hashes; in development, files that appear later are numbered after the existing ones. Styles are given class names in a fixed order, not the order of a hash set. The exported class, file and canonical maps are canonical JSON (sorted keys). Stylesheet evaluation (vanilla-extract) refuses Math.random(), Date.now(), new Date() and Date(), which differ between builds, with a build error; fixed dates such as new Date(0) are unchanged. resetBuildState starts a build from its own options: the prefix, atom hoisting, routes, buckets, names, numbers and styles an earlier build in the process left are cleared, and the prefix is set on every setup even when it is absent. Engine snapshots from concurrent transforms are written one after another per file, so an older snapshot is never written last. File lists are ordered by code point rather than the locale

@devup-ui/components@0.1.60 → 0.1.61 - packages/components/package.json

Patch

  • Auto-update: depends on '@devup-ui/vite-plugin' via a local workspace dependency

@devup-ui/next-plugin@1.0.90 → 1.0.91 - packages/next-plugin/package.json

Patch

  • Make atomHoist class names deterministic and match generated references to emitted CSS, freeze hoisting from predeclared route reach, and preserve dynamic !important, keyframes, and first-value responsive-token identities. No new build errors.
  • Isolate the coordinator port file per owning process when another live next dev/build holds it, record the owner pid, and report port, pid and recovery when the coordinator is missing or unreachable
  • Class names and file numbers no longer depend on the order files are processed in. Every plugin walks the files it can extract (the project's source and the included packages) before the first transform and numbers them in path order (a file collapsed into a bucket is numbered as the bucket, and only files that mention the package, StyleX or an aliased package take numbers) through the new seedFileMap, so identical builds give identical class prefixes, CSS file names and output hashes; in development, files that appear later are numbered after the existing ones. Styles are given class names in a fixed order, not the order of a hash set. The exported class, file and canonical maps are canonical JSON (sorted keys). Stylesheet evaluation (vanilla-extract) refuses Math.random(), Date.now(), new Date() and Date(), which differ between builds, with a build error; fixed dates such as new Date(0) are unchanged. resetBuildState starts a build from its own options: the prefix, atom hoisting, routes, buckets, names, numbers and styles an earlier build in the process left are cleared, and the prefix is set on every setup even when it is absent. Engine snapshots from concurrent transforms are written one after another per file, so an older snapshot is never written last. File lists are ordered by code point rather than the locale

@devup-ui/plugin-utils@1.0.17 → 1.0.18 - packages/plugin-utils/package.json

Patch

  • Webpack and Rsbuild builds hold every style in their stylesheets: a stylesheet module is built on its first import, so styles extracted later (the global styles of files webpack or Rsbuild reached late, often outside src) were missing from the output. The files the entries reach under src are now extracted before the build, the shared base on disk is kept current, and when a stylesheet still changed during the build it is compiled once more, writing only the complete result. Rsbuild serves each stylesheet from the current sheet instead of a module-wide string kept only when it grew, which left edits that shortened the CSS and later builds in the same process stale. plugin-utils adds computeReachableFiles
  • Class names and file numbers no longer depend on the order files are processed in. Every plugin walks the files it can extract (the project's source and the included packages) before the first transform and numbers them in path order (a file collapsed into a bucket is numbered as the bucket, and only files that mention the package, StyleX or an aliased package take numbers) through the new seedFileMap, so identical builds give identical class prefixes, CSS file names and output hashes; in development, files that appear later are numbered after the existing ones. Styles are given class names in a fixed order, not the order of a hash set. The exported class, file and canonical maps are canonical JSON (sorted keys). Stylesheet evaluation (vanilla-extract) refuses Math.random(), Date.now(), new Date() and Date(), which differ between builds, with a build error; fixed dates such as new Date(0) are unchanged. resetBuildState starts a build from its own options: the prefix, atom hoisting, routes, buckets, names, numbers and styles an earlier build in the process left are cleared, and the prefix is set on every setup even when it is absent. Engine snapshots from concurrent transforms are written one after another per file, so an older snapshot is never written last. File lists are ordered by code point rather than the locale

@devup-ui/rsbuild-plugin@1.0.67 → 1.0.68 - packages/rsbuild-plugin/package.json

Patch

  • Make atomHoist class names deterministic and match generated references to emitted CSS, freeze hoisting from predeclared route reach, and preserve dynamic !important, keyframes, and first-value responsive-token identities. No new build errors.
  • Webpack and Rsbuild builds hold every style in their stylesheets: a stylesheet module is built on its first import, so styles extracted later (the global styles of files webpack or Rsbuild reached late, often outside src) were missing from the output. The files the entries reach under src are now extracted before the build, the shared base on disk is kept current, and when a stylesheet still changed during the build it is compiled once more, writing only the complete result. Rsbuild serves each stylesheet from the current sheet instead of a module-wide string kept only when it grew, which left edits that shortened the CSS and later builds in the same process stale. plugin-utils adds computeReachableFiles
  • Class names and file numbers no longer depend on the order files are processed in. Every plugin walks the files it can extract (the project's source and the included packages) before the first transform and numbers them in path order (a file collapsed into a bucket is numbered as the bucket, and only files that mention the package, StyleX or an aliased package take numbers) through the new seedFileMap, so identical builds give identical class prefixes, CSS file names and output hashes; in development, files that appear later are numbered after the existing ones. Styles are given class names in a fixed order, not the order of a hash set. The exported class, file and canonical maps are canonical JSON (sorted keys). Stylesheet evaluation (vanilla-extract) refuses Math.random(), Date.now(), new Date() and Date(), which differ between builds, with a build error; fixed dates such as new Date(0) are unchanged. resetBuildState starts a build from its own options: the prefix, atom hoisting, routes, buckets, names, numbers and styles an earlier build in the process left are cleared, and the prefix is set on every setup even when it is absent. Engine snapshots from concurrent transforms are written one after another per file, so an older snapshot is never written last. File lists are ordered by code point rather than the locale

@devup-ui/vite-plugin@1.0.73 → 1.0.74 - packages/vite-plugin/package.json

Patch

  • Make atomHoist class names deterministic and match generated references to emitted CSS, freeze hoisting from predeclared route reach, and preserve dynamic !important, keyframes, and first-value responsive-token identities. No new build errors.
  • Class names and file numbers no longer depend on the order files are processed in. Every plugin walks the files it can extract (the project's source and the included packages) before the first transform and numbers them in path order (a file collapsed into a bucket is numbered as the bucket, and only files that mention the package, StyleX or an aliased package take numbers) through the new seedFileMap, so identical builds give identical class prefixes, CSS file names and output hashes; in development, files that appear later are numbered after the existing ones. Styles are given class names in a fixed order, not the order of a hash set. The exported class, file and canonical maps are canonical JSON (sorted keys). Stylesheet evaluation (vanilla-extract) refuses Math.random(), Date.now(), new Date() and Date(), which differ between builds, with a build error; fixed dates such as new Date(0) are unchanged. resetBuildState starts a build from its own options: the prefix, atom hoisting, routes, buckets, names, numbers and styles an earlier build in the process left are cleared, and the prefix is set on every setup even when it is absent. Engine snapshots from concurrent transforms are written one after another per file, so an older snapshot is never written last. File lists are ordered by code point rather than the locale

@devup-ui/webpack-plugin@1.0.71 → 1.0.72 - packages/webpack-plugin/package.json

Patch

  • Webpack and Rsbuild builds hold every style in their stylesheets: a stylesheet module is built on its first import, so styles extracted later (the global styles of files webpack or Rsbuild reached late, often outside src) were missing from the output. The files the entries reach under src are now extracted before the build, the shared base on disk is kept current, and when a stylesheet still changed during the build it is compiled once more, writing only the complete result. Rsbuild serves each stylesheet from the current sheet instead of a module-wide string kept only when it grew, which left edits that shortened the CSS and later builds in the same process stale. plugin-utils adds computeReachableFiles
  • Class names and file numbers no longer depend on the order files are processed in. Every plugin walks the files it can extract (the project's source and the included packages) before the first transform and numbers them in path order (a file collapsed into a bucket is numbered as the bucket, and only files that mention the package, StyleX or an aliased package take numbers) through the new seedFileMap, so identical builds give identical class prefixes, CSS file names and output hashes; in development, files that appear later are numbered after the existing ones. Styles are given class names in a fixed order, not the order of a hash set. The exported class, file and canonical maps are canonical JSON (sorted keys). Stylesheet evaluation (vanilla-extract) refuses Math.random(), Date.now(), new Date() and Date(), which differ between builds, with a build error; fixed dates such as new Date(0) are unchanged. resetBuildState starts a build from its own options: the prefix, atom hoisting, routes, buckets, names, numbers and styles an earlier build in the process left are cleared, and the prefix is set on every setup even when it is absent. Engine snapshots from concurrent transforms are written one after another per file, so an older snapshot is never written last. File lists are ordered by code point rather than the locale

@codecov

codecov Bot commented Oct 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
...ndings/devup-ui-wasm/src/atom_hoist_measurement.rs 100.00% <100.00%> (ø)
bindings/devup-ui-wasm/src/atom_tests.rs 100.00% <100.00%> (ø)
bindings/devup-ui-wasm/src/lib.rs 100.00% <100.00%> (ø)
libs/css/src/atom_hoist.rs 100.00% <100.00%> (ø)
libs/css/src/atom_name.rs 100.00% <100.00%> (ø)
libs/css/src/file_map.rs 100.00% <100.00%> (ø)
libs/css/src/file_routes.rs 100.00% <ø> (ø)
libs/css/src/lib.rs 100.00% <100.00%> (ø)
libs/css/src/theme_tokens.rs 100.00% <100.00%> (ø)
...tractor/src/extract_style/extract_dynamic_style.rs 100.00% <ø> (ø)
... and 23 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant