Skip to content

fix(extractor): compile imported styled retargets without redundant imports - #806

Open
owjs3901 wants to merge 1 commit into
mainfrom
fix/imported-retarget-relevance
Open

owjs3901 wants to merge 1 commit into
mainfrom
fix/imported-retarget-relevance

Conversation

@owjs3901

@owjs3901 owjs3901 commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Refs #689 (styled/compat). main 기준의 독립 PR이며, 다른 PR의 선행 병합이 필요하지 않습니다.

요약

다른 프로젝트 모듈에서 가져온 styled 컴포넌트에 .withComponent(...)만 호출하는 파일이, 직접적인 스타일링 패키지 import가 없다는 이유로 추출에서 제외되는 문제를 수정합니다.

기준 커밋: d121976523cc8f2e9da8d0976d5aa59d30e213d8 (origin/main). 기존 imported-styled 사용 탐색과 정의 해석을 재사용하며, 새 런타임 helper/method shim이나 별도 callback 복제 경로는 추가하지 않습니다. 기존 컴포넌트 생성 방식은 변경하지 않습니다. 의존성, 설정, 임계값, 예산, lockfile 변경은 없습니다.

// Base.tsx
import styled from '@emotion/styled'
export const Dyn = styled.button`font-size: ${(p) => (p.big ? '20px' : '10px')};`

// Retargeted.tsx — 불필요한 styled import 없이 동작
import { Dyn } from '@/Base'
export const Retargeted = Dyn.withComponent('a')

동작

  • 텍스트는 withComponent와 import가 모두 있는지 확인하는 저비용 사전 필터에만 사용합니다. 실제 허용 여부는 root binding의 semantic symbol과 기존 module resolver가 읽은 styled 정의로 결정합니다.
  • named import, reexport, namespace member를 같은 경로로 판정합니다. shadowing, type-only, 계산되는 namespace member, 일반 객체, 해석 불가/읽을 수 없는 정의는 그대로 둡니다.
  • 추출기의 이른 반환과 마지막 unchanged guard를 모두 수정하고, imported styled 정의가 있을 때 visitor의 semantic scoping도 활성화합니다. 먼저 읽은 정의는 실제 추출에서 재사용합니다.
  • has_devup_ui_with와 공개 WASM hasDevupUI도 같은 판정을 사용합니다. Bun의 사전 필터가 이 입력을 통과시키며 Vite, Next webpack/Turbopack, webpack, Rsbuild의 기존 공통 extraction 진입점에도 적용됩니다. TypeScript 플러그인별 별도 heuristic은 추가하지 않았습니다.
  • public API 테스트는 실제 tsconfig @/* -> src/*, Next withModuleResolver, 원래 Base/Dyn fixture를 사용합니다. 완전한 emitted module을 평가하고 실제 React forwardRef renderer의 출력과 emitted CSS를 확인합니다.
실제 관찰 수정 전 수정 후 (두 CSS 모드)
패키지 import 없는 consumer 평가 TypeError: Dyn.withComponent is not a function 정상 평가
target / ref / children 평가 실패로 관찰 불가 a / 같은 ref 객체 / child
big=false / big=true의 font-size 평가 실패로 관찰 불가 emitted CSS와 CSS 변수에서 10px / 20px
사용하지 않는 styled import만 추가한 control 정상 동작 정상 동작

새로 생기는 오류

새 오류 종류는 없습니다. 새로 인식되는 known-styled 호출의 인수가 기존 지원 조건을 벗어나면 기존 withComponent 빌드 오류 규칙을 그대로 따릅니다. 일반 객체의 동명 메서드를 styled 호출로 판단하지 않습니다.

남는 한계

  • resolver가 없거나 정의를 정적으로 읽을 수 없는 import와 동적인 namespace lookup은 기존 경계를 유지합니다. 이 PR은 알려진 styled 정의의 relevance 누락만 수정합니다.
  • 브라우저 자동화는 실행하지 않았습니다. 새 회귀 테스트는 실제 emitted ESM 평가, React renderer 출력, emitted CSS/변수의 값을 검증하며 브라우저 computed-style 측정으로 표현하지 않습니다.
  • Rust LSP 요청은 daemon timeout, TypeScript LSP는 기존 설치 거절 상태로 사용할 수 없었습니다. compiler/clippy, workspace tests, 빌드, coverage와 CI로 검증합니다.
  • 아래 microbenchmark는 같은 머신에서 저장한 수정 전/후 WASM을 번갈아 실행한 수치이며 전체 앱 빌드 성능을 의미하지 않습니다. 무트리거 파일은 추가 parse/resolver 호출이 없습니다. 작은 시간 차이는 숨기지 않고 함께 기록합니다.

검증

  • main RED: 원래 fixture를 변경하지 않고 별도 테스트를 추가한 뒤 6 pass / 2 fail, 두 실패 모두 module 평가 중 Dyn.withComponent is not a function. 불필요한 import만 추가한 두 control은 이미 target/ref/children/10px/20px 검증을 통과했습니다.
  • GREEN: 같은 public-API 파일 8 pass / 0 fail. 이후 정상 hook의 전체 테스트에서도 filter-first 판정과 두 CSS 모드 검증이 통과했습니다.
  • Rust: 새 relevance 테스트 20개 (positive/control 4, unchanged negative 15, no-resolver 1). cargo test --workspace 전체 통과. 기존 snapshot 변경 없음; 새 snapshot 4개는 named/reexport/namespace/control의 실제 emitted code와 dependency 목록입니다.
  • cargo fmt --all -- --check 통과. WASM bun run build 및 루트 bun run build 통과.
  • standalone bun lint는 새 helper의 wildcard import를 지적하여 explicit import로 수정했습니다. 첫 hook은 이후 추가한 테스트 줄의 CRLF formatting을 지적해 해당 테스트 파일만 scoped fix했습니다. 최종 정상 hook은 fmt/clippy -D warnings와 ESLint 0 errors / 기존 warnings 20개로 통과했습니다. hook 우회/수정, amend는 하지 않았습니다.
  • private Bun 1.4.4 루트 bun test --coverage: 6252 pass / 0 fail, 168 files, 89 snapshots, 23247 assertions, 254.67초.
All files | 100.00 | 100.00 |
  • 정상 commit hook 전체 통과: 928.30초. shared Bun 1.4.3 루트 6252 pass / 0 fail, Vite 868 pass / 0 fail, 양쪽 함수/줄 100.00%. Rust tarpaulin은 Windows 기준 **98.07% (24087/24562)**이며 100%라고 주장하지 않습니다. 변경한 Rust 줄과 uncovered 목록의 교집합은 없음; 새 relevance 모듈 27/27 실행 줄 covered. Linux CI의 wide-format 100% gate는 별도 확인합니다.
  • 최종 hook 직전 free memory 10,779,380 KiB (요구 기준 7,340,032 KiB 이상), CARGO_BUILD_JOBS=2. 공유 Bun/설정은 변경하지 않았습니다. 첫 commit 명령은 clone의 author identity 부재로 hook 이전에 종료되어, 인증된 계정의 identity를 그 명령의 환경 변수에만 지정했습니다.

성능 (12쌍 AB/BA 교차 실행의 중앙값, µs/호출)

corpus extract 전 → 후 hasDevupUI 전 → 후
작은 일반 모듈 3.121 → 2.930 2.006 → 2.081
일반 import + JSX 5.804 → 6.051 4.564 → 4.626
큰 일반 import + JSX 88.382 → 85.731 85.122 → 84.397
기존 직접 스타일 import 21.631 → 21.679 2.175 → 2.203
known imported retarget 5.403 (잘못된 skip) → 82.974 (실제 compile) 3.626 → 37.019
unknown imported retarget 6.262 → 11.725 4.324 → 10.190

무트리거 corpus의 resolver 호출 수는 전후 동일(작은 모듈/직접 스타일 0, 일반 import 1)하며 sample 범위는 겹칩니다. trigger가 있는 파일만 의미 분석과 기존 styled reader 비용을 지불합니다. known retarget의 정상 추출은 relevance에서 읽은 정의를 재사용하여 불필요한 두 번째 styled resolve를 하지 않습니다. 두 trigger corpus의 resolver 호출은 기존 barrel 확인 1회에서 styled 확인을 포함한 2회로 증가합니다.

CI 완료

Publish Package to npm — 40025554388, head fa4d6635b7de18e832035efe3f739fd2d5f947dc: success, 첫 실행에서 완료, rerun 없음.

Linux wide-format 후 tarpaulin: 100.00% (17059/17059), 새 relevance 모듈 15/15. --fail-under 100 gate 통과. 배포/release는 PR 이벤트 조건에 따라 skipped입니다.

Job 결과 소요 시간
publish success 20m15s
landing-next-e2e success 8m07s
benchmark success 15m46s
wasm-size success 5m32s
react-18 success 2m33s
vinext-rsc-css-e2e success 3m47s
release-compat success 6m40s
webpack-extends-theme success 4m34s
deploy-pages skipped —
release skipped —

Refs #689

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

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

codecov Bot commented Oct 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
libs/extractor/src/imported_styled.rs 100.00% <100.00%> (ø)
libs/extractor/src/imported_styled/relevance.rs 100.00% <100.00%> (ø)
libs/extractor/src/lib.rs 100.00% <100.00%> (ø)
libs/extractor/src/visit.rs 100.00% <100.00%> (ø)
🚀 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