Feature: allow a custom module file filter (support a bare `css.ts` convention)
Summary
Allow consumers to customize which files @vanilla-extract/vite-plugin (and @vanilla-extract/compiler) treat as Vanilla Extract modules, so a bare css.ts filename convention can be used instead of the *.css.ts suffix.
Today the filter is a hardcoded const in @vanilla-extract/integration:
export const cssFileFilter = /\.css\.(js|cjs|mjs|jsx|ts|tsx)(\?used)?$/;It is imported directly by the Vite plugin and the compiler with no way to override it.
css.ts vs *.css.ts the actual difference (re: your question in #1763)
They are not the same. The current filter requires a non-empty prefix before .css.ts (*.css.ts). It will not match a file literally named css.ts.
We co-locate one style file per component directory and want to name it just css.ts:
button/
index.tsx
css.ts <- not matched today; must be button.css.ts
tooltip/
index.tsx
css.tsRequiring the prefix forces a redundant, per-file token (button.css.ts, tooltip.css.ts) that:
- duplicates the directory name in the filename with zero added information, and
- has to be renamed every time the component is renamed (the style file drifts out of sync otherwise).
The convention itself (single fixed filename co-located in each component folder) is common and, for us, applied across a large multi-repo workspace.
Why this is distinct from #1574
#1574 is about a consumed third-party library whose emitted .css.ts/.css.js files clash with VE processing, solvable by controlling build output (emit .js, not .css.js). This request is about the authoring convention in first-party source; there is no build-output angle. It cannot be worked around by changing what a dependency ships.
Current workaround and why it's fragile
With no public override, the only options are:
- Patch
@vanilla-extract/integrationon disk after each install to rewrite the regex. In a multi-repo/workspace setup a single missed copy silently leavescss.tsfiles untransformed, which surfaces later at runtime asStyles were unable to be assigned to a file. - Maintain a fork of the plugin (what we currently do).
Both are avoidable with a first-class option.
Proposal
A single additive, backwards-compatible option threaded through the plugin and compiler, defaulting to the existing cssFileFilter so nothing changes when omitted:
vanillaExtractPlugin({
// treat a bare `css.ts` as the VE module convention
cssFileFilter: /(?:^|[/\\])css\.(js|cjs|mjs|jsx|ts|tsx)(\?used)?$/,
});Implemented in #1773 (~80 lines: vite-plugin transform gate + HMR invalidation, compiler module scanner + file-scope transform, defaulting to the current filter).
On the footgun concern
I understand the reluctance to expose the filter, a user-supplied regex can drop the js/jsx/tsx/mjs/cjs variants or otherwise misbehave. Happy to constrain the surface however you prefer (validate the shape, accept a set of extensions rather than a raw RegExp, document the caveats, etc.). I'd rather agree on the right shape here before iterating on the PR.
Source: vanilla-extract-css/vanilla-extract