Skip to content

Vite plugins: cx-scss-manifest + transform-cx-imports, Vite-based litmus setup - #1318

Open
mstijak wants to merge 7 commits into
masterfrom
feat/scss-manifest-vite-plugin
Open

Vite plugins: cx-scss-manifest + transform-cx-imports, Vite-based litmus setup#1318
mstijak wants to merge 7 commits into
masterfrom
feat/scss-manifest-vite-plugin

Conversation

@mstijak

@mstijak mstijak commented Jul 31, 2026

Copy link
Copy Markdown
Member

Summary

Adds two Vite plugins — vite-plugin-cx-scss-manifest and vite-plugin-transform-cx-imports — and converts litmus to optionally run on Vite 8 to prove them out end-to-end.

packages/vite-plugin-cx-scss-manifest

Vite counterpart of cx-scss-manifest-webpack-plugin.

  • Scans import statements of the app's own modules with es-module-lexer in the transform hook, validates candidates against cx/manifest.js, and generates the same manifest.scss format as the webpack plugin (files are interchangeable between the two).
  • Handles named imports (alias-aware), cross-namespace re-exports (e.g. Repeater from cx/widgetsui/Repeater), deep imports, and skips import type statements and node_modules.
  • Dev: debounced writes; Vite tracks manifest.scss as a sass dependency, so new widget styles hot-reload without a page refresh.
  • Build: full-graph scan; warns when the manifest changed during the build (CSS compiled with the previous manifest — rerun to apply).
  • Seeds its entry set from the existing file on startup, so an on-demand dev session never shrinks a manifest produced by a full build. Entries are append-only; reset by deleting entries + running a build.

packages/vite-plugin-transform-cx-imports

Vite counterpart of babel-plugin-transform-cx-imports. Rewrites namespace barrel imports into direct file imports using cx/manifest.js:

import { Button, Grid as CxGrid } from "cx/widgets";
// becomes
import { Button } from "cx/widgets/Button.js";
import { Grid as CxGrid } from "cx/widgets/grid/Grid.js";
  • Halves litmus's transformed module count (354 → 181) since barrels no longer pull the whole namespace through the pipeline — the main win is dev-server cold start.
  • Unknown names stay on the barrel with a one-time warning (instead of the babel plugin's hard error); import type, namespace, default, and dynamic imports are left untouched. Sourcemaps preserved via magic-string.
  • Optional scss flag mirrors the babel plugin's sass option (currently dormant — the shipped manifest has no scss entries).
  • Perf note: uses the same es-module-lexer Vite itself runs on every module during import-analysis, gated behind node_modules/extension/indexOf("cx/") checks — measured build overhead of both plugins together is ~15ms (within noise).

fix(cx): type-only re-exports

Three type-only names were re-exported as values (AccessorChain in ui/index.ts, JSX in jsx-dev-runtime.ts, GridRowConfig in Grid.tsx). Babel tolerated this, but any isolated-modules transpiler (esbuild/oxc/swc) keeps the import and fails at runtime — this breaks all jsxImportSource: "cx" source-consuming setups, not just litmus. Fixed with export type (verified via tsc --isolatedModules, which now reports no TS1205 errors).

feat(litmus): Vite setup alongside webpack

  • yarn start:vite (port 8090) / yarn build:vite; the webpack workflow is untouched.
  • Aliases cx/* to packages/cx/src — framework source edits hot-reload directly, no compile step.
  • Automatic JSX runtime with jsxImportSource: "cx" (no babel). Legacy .js demos containing JSX go through a small esbuild bridge plugin, since rolldown's built-in transform doesn't allow enabling JSX for .js (its TransformOptions.lang is ignored in the native plugin). The active demo is renamed to .tsx as the migration path — pure oxc handles those.
  • Vite 8 production build: ~0.6s.

Testing

  • Verified in a real browser (dev + production build): widget styles present, chart/switch/select rendered correctly, HMR loop (new import → manifest update → CSS hot update) works without page reload, direct file imports visible in the dev network log.
  • yarn check-types clean; yarn test — 535 passing, 1 pre-existing failure on master (babel-plugin-transform-cx-imports vs. stale dist/manifest.js after the cx/widgets barrel refactor, unrelated to this PR).

@mstijak mstijak changed the title SCSS manifest plugin for Vite + Vite-based litmus setup Vite plugins: SCSS manifest + transform-cx-imports, Vite-based litmus setup Aug 4, 2026
@mstijak mstijak changed the title Vite plugins: SCSS manifest + transform-cx-imports, Vite-based litmus setup Vite plugins: cx-scss-manifest + transform-cx-imports, Vite-based litmus setup Aug 4, 2026
@mstijak
mstijak force-pushed the feat/scss-manifest-vite-plugin branch from d77dc75 to 97af1c0 Compare August 4, 2026 08:22
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