@r0hitsharma/vite-config 0.12.0-rohit-fork-ci.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +130 -0
- package/dist/react-compiler.d.ts +88 -0
- package/dist/react-compiler.js +83 -0
- package/package.json +52 -0
- package/react-compiler.ts +148 -0
package/README.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# @r0hitsharma/vite-config
|
|
2
|
+
|
|
3
|
+
Shared Vite build presets, so that wiring every app needs is written once.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install --save-dev @r0hitsharma/vite-config \
|
|
9
|
+
vite @vitejs/plugin-react @rolldown/plugin-babel babel-plugin-react-compiler
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The four packages are peer dependencies: the preset composes them, it does not
|
|
13
|
+
vendor them, so the app decides which versions its build runs on. Vite 8 is
|
|
14
|
+
required: the preset is built on rolldown's plugin API.
|
|
15
|
+
|
|
16
|
+
## React Compiler
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import reactCompiler from '@r0hitsharma/vite-config/react-compiler';
|
|
20
|
+
import react from '@vitejs/plugin-react';
|
|
21
|
+
import { defineConfig } from 'vite';
|
|
22
|
+
|
|
23
|
+
export default defineConfig({
|
|
24
|
+
plugins: [react(), reactCompiler()],
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`react()` stays responsible for JSX and Fast Refresh; `reactCompiler()` adds the
|
|
29
|
+
compiler. Order matters only in that both must be present.
|
|
30
|
+
|
|
31
|
+
### Why this is not a `@vitejs/plugin-react` option
|
|
32
|
+
|
|
33
|
+
Vite 8 bundles with rolldown, whose transformer is Oxc, and Oxc does not run
|
|
34
|
+
Babel plugins. The React Compiler is a Babel plugin, so it arrives as a separate
|
|
35
|
+
Babel pass — `@rolldown/plugin-babel` carrying `reactCompilerPreset()` — rather
|
|
36
|
+
than as a `babel.plugins` entry on `react()`.
|
|
37
|
+
|
|
38
|
+
That preset ships a `code` filter and no `id` filter, which means every module
|
|
39
|
+
passing the code test is handed to Babel. Babel is the one part of the pipeline
|
|
40
|
+
that is not Oxc, so this preset adds the `id` filter the preset omits.
|
|
41
|
+
|
|
42
|
+
### Options
|
|
43
|
+
|
|
44
|
+
| Option | Default | Effect |
|
|
45
|
+
| --- | --- | --- |
|
|
46
|
+
| `exclude` | `[]` | Extra module ids kept out of the Babel pass, merged after the defaults rather than replacing them |
|
|
47
|
+
| `excludeStyledSystem` | `true` | Whether the default `styled-system` exclusion applies |
|
|
48
|
+
| `compiler` | `undefined` | Options forwarded to `babel-plugin-react-compiler` |
|
|
49
|
+
|
|
50
|
+
Excluded by default:
|
|
51
|
+
|
|
52
|
+
| Pattern | Why |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| `/[/\\]node_modules[/\\]/` | Dependencies ship compiled; also `@rolldown/plugin-babel`'s own default, restated so this preset does not depend on that default staying put |
|
|
55
|
+
| `/[/\\]styled-system[/\\](?!jsx[/\\])/` | Panda's generated output — style objects, token maps, type declarations — which every design-system consumer has and which holds no components |
|
|
56
|
+
|
|
57
|
+
The `jsx` carve-out is deliberate. Under `jsxFramework: 'react'` Panda generates
|
|
58
|
+
real `forwardRef` components into `styled-system/jsx/`, and this repo's own
|
|
59
|
+
shared Panda config sets exactly that. Since `exclude` only ever adds, a blanket
|
|
60
|
+
`styled-system` exclusion would skip the compiler on genuine components — so the
|
|
61
|
+
default is narrowed to the part of the tree that is component-free under every
|
|
62
|
+
Panda setting, rather than left for consumers to correct.
|
|
63
|
+
|
|
64
|
+
That leaves one assumption: that the segment means Panda's `outdir` at all. A
|
|
65
|
+
project where it does not — a hand-written `styled-system/` directory, say —
|
|
66
|
+
would hit exactly the failure this preset exists to prevent, a build that
|
|
67
|
+
type-checks, exits 0 and ships those components unoptimized, with no way to say
|
|
68
|
+
so through an append-only `exclude`. `excludeStyledSystem: false` drops that one
|
|
69
|
+
pattern:
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
reactCompiler({ excludeStyledSystem: false });
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`node_modules` is not part of the trade and stays out of the pass either way. It
|
|
76
|
+
is also `@rolldown/plugin-babel`'s own default `exclude`, applied to the pass
|
|
77
|
+
independently of the filter this preset sets, so an option to compile
|
|
78
|
+
dependencies would not work even if one existed.
|
|
79
|
+
|
|
80
|
+
Add your own generated trees:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
reactCompiler({ exclude: [/[/\\]src[/\\]generated[/\\]/] });
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Regular expressions rather than globs, and the defaults are regexes for the
|
|
87
|
+
same reason: a string pattern is compiled by two different matchers.
|
|
88
|
+
`@rolldown/plugin-babel` compiles one copy with a bare `picomatch(pattern)`,
|
|
89
|
+
which defaults to `dot: false`, so a project living under `.cache/` or `.pnpm/`
|
|
90
|
+
drops out of a `**` glob entirely. rolldown's own id filter has no such blind
|
|
91
|
+
spot and is the one that decides for this wiring, which is why a glob is not
|
|
92
|
+
wrong here today — but it is right by way of which of the two gates happens to
|
|
93
|
+
be authoritative, and that is a plugin internal. A `RegExp` is
|
|
94
|
+
`pattern.test(id)` on both sides.
|
|
95
|
+
|
|
96
|
+
Leave `compiler` unset on React 19.2 and later. The compiler then emits calls
|
|
97
|
+
into `react/compiler-runtime`, which those versions ship; only an older React
|
|
98
|
+
needs an explicit `target`.
|
|
99
|
+
|
|
100
|
+
### Confirming it ran
|
|
101
|
+
|
|
102
|
+
An unwired compiler is silent — the build succeeds and produces the same output
|
|
103
|
+
it always did. The compiler's runtime import is the marker to look for, since
|
|
104
|
+
nothing else in an app imports it:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
vite build --minify false
|
|
108
|
+
grep -rc 'react/compiler-runtime' dist/assets/*.js
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
This package's own tests assert exactly that, against real builds — including
|
|
112
|
+
that the excluded trees really do come out untouched.
|
|
113
|
+
|
|
114
|
+
## Linting for it
|
|
115
|
+
|
|
116
|
+
The compiler's own static analysis is available as oxlint rules, and the `react`
|
|
117
|
+
preset in [`@r0hitsharma/oxlint-config`](../oxlint-config/README.md) enables
|
|
118
|
+
19 of them. A consumer on that preset gets the build and the lint agreeing
|
|
119
|
+
without configuring anything.
|
|
120
|
+
|
|
121
|
+
They are named one at a time — `react/hooks`, `react/purity`,
|
|
122
|
+
`react/immutability`, `react/preserve-manual-memoization` and the rest — because
|
|
123
|
+
the umbrella `react/react-compiler` rule no longer exists. oxlint 1.79.0 split it
|
|
124
|
+
into one rule per compiler diagnostic, matching `eslint-plugin-react-hooks` v6,
|
|
125
|
+
and naming the old umbrella is now a hard config-parse failure:
|
|
126
|
+
`Rule 'react-compiler' not found in plugin 'react'`.
|
|
127
|
+
|
|
128
|
+
Five further split rules are deferred to `off` in that preset, each with its
|
|
129
|
+
reason and current finding count recorded beside it in
|
|
130
|
+
[`react.ts`](../oxlint-config/react.ts).
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { reactCompilerPreset } from '@vitejs/plugin-react';
|
|
2
|
+
import type { PluginOption } from 'vite';
|
|
3
|
+
/**
|
|
4
|
+
* Vite 8 bundles with rolldown, and rolldown's own transformer is Oxc, which
|
|
5
|
+
* does not run Babel plugins. So the React Compiler is not a `@vitejs/plugin-react`
|
|
6
|
+
* option: it is a separate Babel pass, added as a rolldown preset alongside
|
|
7
|
+
* `react()`. That indirection is the whole reason this preset exists — it is
|
|
8
|
+
* identical in every app, and easy to wire up in a way that silently compiles
|
|
9
|
+
* nothing.
|
|
10
|
+
*/
|
|
11
|
+
/** The React Compiler's Babel options, as `@vitejs/plugin-react` accepts them. */
|
|
12
|
+
export type ReactCompilerBabelOptions = NonNullable<Parameters<typeof reactCompilerPreset>[0]>;
|
|
13
|
+
/** A rolldown id filter pattern: a picomatch glob or a regular expression. */
|
|
14
|
+
export type IdPattern = string | RegExp;
|
|
15
|
+
export type ReactCompilerOptions = {
|
|
16
|
+
/**
|
|
17
|
+
* Extra module ids kept away from the Babel pass, merged after
|
|
18
|
+
* {@link DEFAULT_EXCLUDE} rather than replacing it. Generated trees are the
|
|
19
|
+
* usual candidates — anything with no components in it is pure cost.
|
|
20
|
+
*
|
|
21
|
+
* Prefer a `RegExp` over a glob string, for the reason
|
|
22
|
+
* {@link DEFAULT_EXCLUDE} gives: a glob is dot-blind in one of the two
|
|
23
|
+
* matchers that compile it.
|
|
24
|
+
*/
|
|
25
|
+
exclude?: readonly IdPattern[];
|
|
26
|
+
/**
|
|
27
|
+
* Whether the default `styled-system` exclusion applies.
|
|
28
|
+
*
|
|
29
|
+
* Set it to `false` where that path segment does not mean what
|
|
30
|
+
* {@link DEFAULT_EXCLUDE} assumes it means — a directory of that name
|
|
31
|
+
* holding hand-written components rather than Panda's generated output.
|
|
32
|
+
* Since `exclude` only ever adds, that is otherwise unfixable, and it fails
|
|
33
|
+
* the way this package exists to prevent: the build type-checks, exits 0,
|
|
34
|
+
* and quietly ships those components unoptimized.
|
|
35
|
+
*
|
|
36
|
+
* `node_modules` is not part of this and stays out of the pass either way.
|
|
37
|
+
* It is also `@rolldown/plugin-babel`'s own default `exclude`, which that
|
|
38
|
+
* plugin applies to this pass independently of the filter set here — so an
|
|
39
|
+
* option to compile dependencies would not work even if one existed.
|
|
40
|
+
*
|
|
41
|
+
* @default true
|
|
42
|
+
*/
|
|
43
|
+
excludeStyledSystem?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Forwarded to the compiler itself. Leave it unset on React 19.2 and later:
|
|
46
|
+
* the compiler then emits calls into `react/compiler-runtime`, which those
|
|
47
|
+
* versions ship. Only an older React needs an explicit `target`.
|
|
48
|
+
*/
|
|
49
|
+
compiler?: ReactCompilerBabelOptions;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Trees excluded from the Babel pass by default.
|
|
53
|
+
*
|
|
54
|
+
* Babel is the one part of a Vite 8 pipeline that is not Oxc, so it is the one
|
|
55
|
+
* part worth not running. Nothing upstream narrows it: the compiler preset
|
|
56
|
+
* ships only a `code` filter, and that filter is
|
|
57
|
+
* `/forwardRef|memo|\b(?:[A-Z]|use[A-Z0-9])/` — near enough every module with a
|
|
58
|
+
* capital letter in it, generated output very much included.
|
|
59
|
+
*
|
|
60
|
+
* Written as regular expressions rather than glob strings on purpose. A string
|
|
61
|
+
* pattern is compiled by two matchers that disagree: rolldown's own id filter,
|
|
62
|
+
* where a leading-dot path segment matches, and `@rolldown/plugin-babel`'s
|
|
63
|
+
* `picomatch(pattern)`, where it does not — picomatch defaults to
|
|
64
|
+
* `dot: false`, so a project under `.cache/` or `.pnpm/` falls out of a
|
|
65
|
+
* `styled-system` glob. Only rolldown's matcher is authoritative for the
|
|
66
|
+
* wiring below, so a glob is not wrong here today; it is right by way of which
|
|
67
|
+
* of the two gates happens to decide, which is a plugin internal. A `RegExp`
|
|
68
|
+
* is `pattern.test(id)` on both sides and has no such blind spot.
|
|
69
|
+
*/
|
|
70
|
+
export declare const DEFAULT_EXCLUDE: readonly IdPattern[];
|
|
71
|
+
/**
|
|
72
|
+
* The React Compiler, wired for Vite 8.
|
|
73
|
+
*
|
|
74
|
+
* Add it after `@vitejs/plugin-react`, which stays responsible for JSX and Fast
|
|
75
|
+
* Refresh:
|
|
76
|
+
*
|
|
77
|
+
* ```ts
|
|
78
|
+
* import react from '@vitejs/plugin-react';
|
|
79
|
+
* import reactCompiler from '@r0hitsharma/vite-config/react-compiler';
|
|
80
|
+
*
|
|
81
|
+
* export default defineConfig({
|
|
82
|
+
* plugins: [react(), reactCompiler()],
|
|
83
|
+
* });
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* Returns a promise, which Vite accepts directly in `plugins`.
|
|
87
|
+
*/
|
|
88
|
+
export default function reactCompiler(options?: ReactCompilerOptions): PluginOption;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import babel from '@rolldown/plugin-babel';
|
|
2
|
+
import { reactCompilerPreset } from '@vitejs/plugin-react';
|
|
3
|
+
/**
|
|
4
|
+
* `node_modules` is also `@rolldown/plugin-babel`'s own default `exclude`.
|
|
5
|
+
* Restating it keeps this preset's exclusion self-contained rather than
|
|
6
|
+
* dependent on that default staying what it is, and it is the one pattern here
|
|
7
|
+
* that no option removes: dependencies ship compiled, and the plugin's own
|
|
8
|
+
* default would keep them out of the pass regardless.
|
|
9
|
+
*/
|
|
10
|
+
const NODE_MODULES_EXCLUDE = /[/\\]node_modules[/\\]/;
|
|
11
|
+
/**
|
|
12
|
+
* Panda's generated output, which every design-system consumer has — style
|
|
13
|
+
* objects, token maps and type declarations, with no components in them.
|
|
14
|
+
*
|
|
15
|
+
* Its `jsx` subtree is the exception and is carved back IN: under
|
|
16
|
+
* `jsxFramework: 'react'`, which this repo's own shared Panda config sets,
|
|
17
|
+
* Panda generates real `forwardRef` components there. Excluding those would
|
|
18
|
+
* skip the compiler on genuine components, and `exclude` only ever adds, so
|
|
19
|
+
* undoing it would mean reaching for `excludeStyledSystem` — which no Panda
|
|
20
|
+
* consumer should have to discover. A default that is wrong under a supported
|
|
21
|
+
* Panda setting is worse than a default that compiles twenty extra generated
|
|
22
|
+
* files.
|
|
23
|
+
*
|
|
24
|
+
* This is the one pattern {@link ReactCompilerOptions.excludeStyledSystem}
|
|
25
|
+
* drops, for a project where the segment names something other than Panda's
|
|
26
|
+
* `outdir`.
|
|
27
|
+
*/
|
|
28
|
+
const STYLED_SYSTEM_EXCLUDE = /[/\\]styled-system[/\\](?!jsx[/\\])/;
|
|
29
|
+
/**
|
|
30
|
+
* Trees excluded from the Babel pass by default.
|
|
31
|
+
*
|
|
32
|
+
* Babel is the one part of a Vite 8 pipeline that is not Oxc, so it is the one
|
|
33
|
+
* part worth not running. Nothing upstream narrows it: the compiler preset
|
|
34
|
+
* ships only a `code` filter, and that filter is
|
|
35
|
+
* `/forwardRef|memo|\b(?:[A-Z]|use[A-Z0-9])/` — near enough every module with a
|
|
36
|
+
* capital letter in it, generated output very much included.
|
|
37
|
+
*
|
|
38
|
+
* Written as regular expressions rather than glob strings on purpose. A string
|
|
39
|
+
* pattern is compiled by two matchers that disagree: rolldown's own id filter,
|
|
40
|
+
* where a leading-dot path segment matches, and `@rolldown/plugin-babel`'s
|
|
41
|
+
* `picomatch(pattern)`, where it does not — picomatch defaults to
|
|
42
|
+
* `dot: false`, so a project under `.cache/` or `.pnpm/` falls out of a
|
|
43
|
+
* `styled-system` glob. Only rolldown's matcher is authoritative for the
|
|
44
|
+
* wiring below, so a glob is not wrong here today; it is right by way of which
|
|
45
|
+
* of the two gates happens to decide, which is a plugin internal. A `RegExp`
|
|
46
|
+
* is `pattern.test(id)` on both sides and has no such blind spot.
|
|
47
|
+
*/
|
|
48
|
+
export const DEFAULT_EXCLUDE = [
|
|
49
|
+
NODE_MODULES_EXCLUDE,
|
|
50
|
+
STYLED_SYSTEM_EXCLUDE,
|
|
51
|
+
];
|
|
52
|
+
/**
|
|
53
|
+
* The React Compiler, wired for Vite 8.
|
|
54
|
+
*
|
|
55
|
+
* Add it after `@vitejs/plugin-react`, which stays responsible for JSX and Fast
|
|
56
|
+
* Refresh:
|
|
57
|
+
*
|
|
58
|
+
* ```ts
|
|
59
|
+
* import react from '@vitejs/plugin-react';
|
|
60
|
+
* import reactCompiler from '@r0hitsharma/vite-config/react-compiler';
|
|
61
|
+
*
|
|
62
|
+
* export default defineConfig({
|
|
63
|
+
* plugins: [react(), reactCompiler()],
|
|
64
|
+
* });
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* Returns a promise, which Vite accepts directly in `plugins`.
|
|
68
|
+
*/
|
|
69
|
+
export default function reactCompiler(options = {}) {
|
|
70
|
+
const preset = reactCompilerPreset(options.compiler);
|
|
71
|
+
const defaults = options.excludeStyledSystem === false
|
|
72
|
+
? [NODE_MODULES_EXCLUDE]
|
|
73
|
+
: DEFAULT_EXCLUDE;
|
|
74
|
+
// The preset ships a `code` filter and no `id` filter, so without this every
|
|
75
|
+
// module that survives the code test is handed to Babel. Spread rather than
|
|
76
|
+
// replace: dropping the preset's own filters would widen the pass, not
|
|
77
|
+
// narrow it.
|
|
78
|
+
preset.rolldown.filter = {
|
|
79
|
+
...preset.rolldown.filter,
|
|
80
|
+
id: { exclude: [...defaults, ...(options.exclude ?? [])] },
|
|
81
|
+
};
|
|
82
|
+
return babel({ presets: [preset] });
|
|
83
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@r0hitsharma/vite-config",
|
|
3
|
+
"publishConfig": {
|
|
4
|
+
"access": "public"
|
|
5
|
+
},
|
|
6
|
+
"type": "module",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"react-compiler.ts"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc -p tsconfig.build.json",
|
|
13
|
+
"clean": "rm -rf dist",
|
|
14
|
+
"prepare": "npm run build",
|
|
15
|
+
"type:check": "tsc -p tsconfig.json --noEmit",
|
|
16
|
+
"lint": "oxlint -c oxlint.config.ts --max-warnings=0 *.ts",
|
|
17
|
+
"lint:fix": "oxlint -c oxlint.config.ts --fix *.ts",
|
|
18
|
+
"format": "oxfmt -c oxfmt.config.ts --write *.ts",
|
|
19
|
+
"format:check": "oxfmt -c oxfmt.config.ts --check *.ts",
|
|
20
|
+
"test": "npm run build && vitest run"
|
|
21
|
+
},
|
|
22
|
+
"exports": {
|
|
23
|
+
"./react-compiler": {
|
|
24
|
+
"types": "./dist/react-compiler.d.ts",
|
|
25
|
+
"default": "./dist/react-compiler.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"@rolldown/plugin-babel": "^0.2.3",
|
|
30
|
+
"@vitejs/plugin-react": "^6.0.5",
|
|
31
|
+
"babel-plugin-react-compiler": "^1.0.0",
|
|
32
|
+
"vite": "^8.0.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@babel/core": "7.29.7",
|
|
36
|
+
"@r0hitsharma/oxfmt-config": "*",
|
|
37
|
+
"@r0hitsharma/oxlint-config": "*",
|
|
38
|
+
"@r0hitsharma/tsconfig": "*",
|
|
39
|
+
"@rolldown/plugin-babel": "0.2.4",
|
|
40
|
+
"@types/babel__core": "7.20.5",
|
|
41
|
+
"@vitejs/plugin-react": "6.1.1",
|
|
42
|
+
"babel-plugin-react-compiler": "1.0.0",
|
|
43
|
+
"oxfmt": "0.67.0",
|
|
44
|
+
"oxlint": "1.82.0",
|
|
45
|
+
"vite": "8.2.2",
|
|
46
|
+
"vitest": "^4.1.9"
|
|
47
|
+
},
|
|
48
|
+
"version": "0.12.0-rohit-fork-ci.1",
|
|
49
|
+
"repository": {
|
|
50
|
+
"url": "https://github.com/r0hitsharma/uikit"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import babel from '@rolldown/plugin-babel';
|
|
2
|
+
import { reactCompilerPreset } from '@vitejs/plugin-react';
|
|
3
|
+
import type { PluginOption } from 'vite';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Vite 8 bundles with rolldown, and rolldown's own transformer is Oxc, which
|
|
7
|
+
* does not run Babel plugins. So the React Compiler is not a `@vitejs/plugin-react`
|
|
8
|
+
* option: it is a separate Babel pass, added as a rolldown preset alongside
|
|
9
|
+
* `react()`. That indirection is the whole reason this preset exists — it is
|
|
10
|
+
* identical in every app, and easy to wire up in a way that silently compiles
|
|
11
|
+
* nothing.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** The React Compiler's Babel options, as `@vitejs/plugin-react` accepts them. */
|
|
15
|
+
export type ReactCompilerBabelOptions = NonNullable<
|
|
16
|
+
Parameters<typeof reactCompilerPreset>[0]
|
|
17
|
+
>;
|
|
18
|
+
|
|
19
|
+
/** A rolldown id filter pattern: a picomatch glob or a regular expression. */
|
|
20
|
+
export type IdPattern = string | RegExp;
|
|
21
|
+
|
|
22
|
+
export type ReactCompilerOptions = {
|
|
23
|
+
/**
|
|
24
|
+
* Extra module ids kept away from the Babel pass, merged after
|
|
25
|
+
* {@link DEFAULT_EXCLUDE} rather than replacing it. Generated trees are the
|
|
26
|
+
* usual candidates — anything with no components in it is pure cost.
|
|
27
|
+
*
|
|
28
|
+
* Prefer a `RegExp` over a glob string, for the reason
|
|
29
|
+
* {@link DEFAULT_EXCLUDE} gives: a glob is dot-blind in one of the two
|
|
30
|
+
* matchers that compile it.
|
|
31
|
+
*/
|
|
32
|
+
exclude?: readonly IdPattern[];
|
|
33
|
+
/**
|
|
34
|
+
* Whether the default `styled-system` exclusion applies.
|
|
35
|
+
*
|
|
36
|
+
* Set it to `false` where that path segment does not mean what
|
|
37
|
+
* {@link DEFAULT_EXCLUDE} assumes it means — a directory of that name
|
|
38
|
+
* holding hand-written components rather than Panda's generated output.
|
|
39
|
+
* Since `exclude` only ever adds, that is otherwise unfixable, and it fails
|
|
40
|
+
* the way this package exists to prevent: the build type-checks, exits 0,
|
|
41
|
+
* and quietly ships those components unoptimized.
|
|
42
|
+
*
|
|
43
|
+
* `node_modules` is not part of this and stays out of the pass either way.
|
|
44
|
+
* It is also `@rolldown/plugin-babel`'s own default `exclude`, which that
|
|
45
|
+
* plugin applies to this pass independently of the filter set here — so an
|
|
46
|
+
* option to compile dependencies would not work even if one existed.
|
|
47
|
+
*
|
|
48
|
+
* @default true
|
|
49
|
+
*/
|
|
50
|
+
excludeStyledSystem?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Forwarded to the compiler itself. Leave it unset on React 19.2 and later:
|
|
53
|
+
* the compiler then emits calls into `react/compiler-runtime`, which those
|
|
54
|
+
* versions ship. Only an older React needs an explicit `target`.
|
|
55
|
+
*/
|
|
56
|
+
compiler?: ReactCompilerBabelOptions;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* `node_modules` is also `@rolldown/plugin-babel`'s own default `exclude`.
|
|
61
|
+
* Restating it keeps this preset's exclusion self-contained rather than
|
|
62
|
+
* dependent on that default staying what it is, and it is the one pattern here
|
|
63
|
+
* that no option removes: dependencies ship compiled, and the plugin's own
|
|
64
|
+
* default would keep them out of the pass regardless.
|
|
65
|
+
*/
|
|
66
|
+
const NODE_MODULES_EXCLUDE = /[/\\]node_modules[/\\]/;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Panda's generated output, which every design-system consumer has — style
|
|
70
|
+
* objects, token maps and type declarations, with no components in them.
|
|
71
|
+
*
|
|
72
|
+
* Its `jsx` subtree is the exception and is carved back IN: under
|
|
73
|
+
* `jsxFramework: 'react'`, which this repo's own shared Panda config sets,
|
|
74
|
+
* Panda generates real `forwardRef` components there. Excluding those would
|
|
75
|
+
* skip the compiler on genuine components, and `exclude` only ever adds, so
|
|
76
|
+
* undoing it would mean reaching for `excludeStyledSystem` — which no Panda
|
|
77
|
+
* consumer should have to discover. A default that is wrong under a supported
|
|
78
|
+
* Panda setting is worse than a default that compiles twenty extra generated
|
|
79
|
+
* files.
|
|
80
|
+
*
|
|
81
|
+
* This is the one pattern {@link ReactCompilerOptions.excludeStyledSystem}
|
|
82
|
+
* drops, for a project where the segment names something other than Panda's
|
|
83
|
+
* `outdir`.
|
|
84
|
+
*/
|
|
85
|
+
const STYLED_SYSTEM_EXCLUDE = /[/\\]styled-system[/\\](?!jsx[/\\])/;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Trees excluded from the Babel pass by default.
|
|
89
|
+
*
|
|
90
|
+
* Babel is the one part of a Vite 8 pipeline that is not Oxc, so it is the one
|
|
91
|
+
* part worth not running. Nothing upstream narrows it: the compiler preset
|
|
92
|
+
* ships only a `code` filter, and that filter is
|
|
93
|
+
* `/forwardRef|memo|\b(?:[A-Z]|use[A-Z0-9])/` — near enough every module with a
|
|
94
|
+
* capital letter in it, generated output very much included.
|
|
95
|
+
*
|
|
96
|
+
* Written as regular expressions rather than glob strings on purpose. A string
|
|
97
|
+
* pattern is compiled by two matchers that disagree: rolldown's own id filter,
|
|
98
|
+
* where a leading-dot path segment matches, and `@rolldown/plugin-babel`'s
|
|
99
|
+
* `picomatch(pattern)`, where it does not — picomatch defaults to
|
|
100
|
+
* `dot: false`, so a project under `.cache/` or `.pnpm/` falls out of a
|
|
101
|
+
* `styled-system` glob. Only rolldown's matcher is authoritative for the
|
|
102
|
+
* wiring below, so a glob is not wrong here today; it is right by way of which
|
|
103
|
+
* of the two gates happens to decide, which is a plugin internal. A `RegExp`
|
|
104
|
+
* is `pattern.test(id)` on both sides and has no such blind spot.
|
|
105
|
+
*/
|
|
106
|
+
export const DEFAULT_EXCLUDE: readonly IdPattern[] = [
|
|
107
|
+
NODE_MODULES_EXCLUDE,
|
|
108
|
+
STYLED_SYSTEM_EXCLUDE,
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* The React Compiler, wired for Vite 8.
|
|
113
|
+
*
|
|
114
|
+
* Add it after `@vitejs/plugin-react`, which stays responsible for JSX and Fast
|
|
115
|
+
* Refresh:
|
|
116
|
+
*
|
|
117
|
+
* ```ts
|
|
118
|
+
* import react from '@vitejs/plugin-react';
|
|
119
|
+
* import reactCompiler from '@r0hitsharma/vite-config/react-compiler';
|
|
120
|
+
*
|
|
121
|
+
* export default defineConfig({
|
|
122
|
+
* plugins: [react(), reactCompiler()],
|
|
123
|
+
* });
|
|
124
|
+
* ```
|
|
125
|
+
*
|
|
126
|
+
* Returns a promise, which Vite accepts directly in `plugins`.
|
|
127
|
+
*/
|
|
128
|
+
export default function reactCompiler(
|
|
129
|
+
options: ReactCompilerOptions = {},
|
|
130
|
+
): PluginOption {
|
|
131
|
+
const preset = reactCompilerPreset(options.compiler);
|
|
132
|
+
|
|
133
|
+
const defaults =
|
|
134
|
+
options.excludeStyledSystem === false
|
|
135
|
+
? [NODE_MODULES_EXCLUDE]
|
|
136
|
+
: DEFAULT_EXCLUDE;
|
|
137
|
+
|
|
138
|
+
// The preset ships a `code` filter and no `id` filter, so without this every
|
|
139
|
+
// module that survives the code test is handed to Babel. Spread rather than
|
|
140
|
+
// replace: dropping the preset's own filters would widen the pass, not
|
|
141
|
+
// narrow it.
|
|
142
|
+
preset.rolldown.filter = {
|
|
143
|
+
...preset.rolldown.filter,
|
|
144
|
+
id: { exclude: [...defaults, ...(options.exclude ?? [])] },
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
return babel({ presets: [preset] });
|
|
148
|
+
}
|