Skip to content

Commit 052aa88

Browse files
authored
feat(create-vite): support React Compiler (#20704)
1 parent c15847e commit 052aa88

File tree

4 files changed

+112
-9
lines changed

4 files changed

+112
-9
lines changed

packages/create-vite/__tests__/cli.spec.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,27 @@ test('successfully scaffolds a project with subfolder based on react starter tem
151151
expect(templateFilesReact).toEqual(generatedFiles)
152152
})
153153

154+
test('successfully scaffolds a project based on react-compiler-ts starter template', () => {
155+
const { stdout } = run([projectName, '--template', 'react-compiler-ts'], {
156+
cwd: __dirname,
157+
})
158+
const configFile = fs.readFileSync(
159+
path.join(genPath, 'vite.config.ts'),
160+
'utf-8',
161+
)
162+
const packageJsonFile = fs.readFileSync(
163+
path.join(genPath, 'package.json'),
164+
'utf-8',
165+
)
166+
const readmeFile = fs.readFileSync(path.join(genPath, 'README.md'), 'utf-8')
167+
168+
// Assertions
169+
expect(stdout).toContain(`Scaffolding project in ${genPath}`)
170+
expect(configFile).toContain('babel-plugin-react-compiler')
171+
expect(packageJsonFile).toContain('babel-plugin-react-compiler')
172+
expect(readmeFile).toContain('The React Compiler is enabled on this template')
173+
})
174+
154175
test('successfully scaffolds a project with subfolder based on react starter template with rolldown flag', () => {
155176
const { stdout } = run(
156177
[`subfolder/${projectName}`, '--template', 'react', '--rolldown'],

packages/create-vite/src/index.ts

Lines changed: 83 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,16 @@ Options:
4747
--interactive / --no-interactive force interactive / non-interactive mode
4848
4949
Available templates:
50-
${yellow ('vanilla-ts vanilla' )}
51-
${green ('vue-ts vue' )}
52-
${cyan ('react-ts react' )}
53-
${cyan ('react-swc-ts react-swc')}
54-
${magenta ('preact-ts preact' )}
55-
${redBright ('lit-ts lit' )}
56-
${red ('svelte-ts svelte' )}
57-
${blue ('solid-ts solid' )}
58-
${blueBright('qwik-ts qwik' )}`
50+
${yellow ('vanilla-ts vanilla' )}
51+
${green ('vue-ts vue' )}
52+
${cyan ('react-ts react' )}
53+
${cyan ('react-compiler-ts react-compiler')}
54+
${cyan ('react-swc-ts react-swc' )}
55+
${magenta ('preact-ts preact' )}
56+
${redBright ('lit-ts lit' )}
57+
${red ('svelte-ts svelte' )}
58+
${blue ('solid-ts solid' )}
59+
${blueBright('qwik-ts qwik' )}`
5960

6061
type ColorFunc = (str: string | number) => string
6162
type Framework = {
@@ -128,6 +129,11 @@ const FRAMEWORKS: Framework[] = [
128129
display: 'TypeScript',
129130
color: blue,
130131
},
132+
{
133+
name: 'react-compiler-ts',
134+
display: 'TypeScript + React Compiler',
135+
color: blue,
136+
},
131137
{
132138
name: 'react-swc-ts',
133139
display: 'TypeScript + SWC',
@@ -138,6 +144,11 @@ const FRAMEWORKS: Framework[] = [
138144
display: 'JavaScript',
139145
color: yellow,
140146
},
147+
{
148+
name: 'react-compiler',
149+
display: 'JavaScript + React Compiler',
150+
color: yellow,
151+
},
141152
{
142153
name: 'react-swc',
143154
display: 'JavaScript + SWC',
@@ -566,6 +577,11 @@ async function init() {
566577
isReactSwc = true
567578
template = template.replace('-swc', '')
568579
}
580+
let isReactCompiler = false
581+
if (template.includes('react-compiler')) {
582+
isReactCompiler = true
583+
template = template.replace('-compiler', '')
584+
}
569585

570586
const { customCommand } =
571587
FRAMEWORKS.flatMap((f) => f.variants).find((v) => v.name === template) ?? {}
@@ -667,6 +683,8 @@ async function init() {
667683

668684
if (isReactSwc) {
669685
setupReactSwc(root, template.endsWith('-ts'))
686+
} else if (isReactCompiler) {
687+
setupReactCompiler(root, template.endsWith('-ts'))
670688
}
671689

672690
if (immediate) {
@@ -780,6 +798,62 @@ function setupReactSwc(root: string, isTs: boolean) {
780798
return content.replace('@vitejs/plugin-react', '@vitejs/plugin-react-swc')
781799
},
782800
)
801+
updateReactCompilerReadme(
802+
root,
803+
'The React Compiler is currently not compatible with SWC. See [this issue](https://github.com/vitejs/vite-plugin-react/issues/428) for tracking the progress.',
804+
)
805+
}
806+
807+
function setupReactCompiler(root: string, isTs: boolean) {
808+
// renovate: datasource=npm depName=babel-plugin-react-compiler
809+
const reactCompilerPluginVersion = '19.1.0-rc.3'
810+
811+
editFile(path.resolve(root, 'package.json'), (content) => {
812+
const asObject = JSON.parse(content)
813+
const devDepsEntries = Object.entries(asObject.devDependencies)
814+
devDepsEntries.push([
815+
'babel-plugin-react-compiler',
816+
`^${reactCompilerPluginVersion}`,
817+
])
818+
devDepsEntries.sort()
819+
asObject.devDependencies = Object.fromEntries(devDepsEntries)
820+
return JSON.stringify(asObject, null, 2) + '\n'
821+
})
822+
editFile(
823+
path.resolve(root, `vite.config.${isTs ? 'ts' : 'js'}`),
824+
(content) => {
825+
return content.replace(
826+
' plugins: [react()],',
827+
` plugins: [
828+
react({
829+
babel: {
830+
plugins: [['babel-plugin-react-compiler']],
831+
},
832+
}),
833+
],`,
834+
)
835+
},
836+
)
837+
updateReactCompilerReadme(
838+
root,
839+
'The React Compiler is enabled on this template. See [this documentation](https://react.dev/learn/react-compiler) for more information.\n\nNote: This will impact Vite dev & build performances.',
840+
)
841+
}
842+
843+
function updateReactCompilerReadme(root: string, newBody: string) {
844+
editFile(path.resolve(root, `README.md`), (content) => {
845+
const h2Start = content.indexOf('## React Compiler')
846+
const bodyStart = content.indexOf('\n\n', h2Start)
847+
const compilerSectionEnd = content.indexOf('\n## ', bodyStart)
848+
if (h2Start === -1 || bodyStart === -1 || compilerSectionEnd === -1) {
849+
console.warn('Could not update compiler section in README.md')
850+
return content
851+
}
852+
return content.replace(
853+
content.slice(bodyStart + 2, compilerSectionEnd - 1),
854+
newBody,
855+
)
856+
})
783857
}
784858

785859
function editFile(file: string, callback: (content: string) => string) {

packages/create-vite/template-react-ts/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ Currently, two official plugins are available:
77
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
88
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
99

10+
## React Compiler
11+
12+
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
13+
1014
## Expanding the ESLint configuration
1115

1216
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:

packages/create-vite/template-react/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ Currently, two official plugins are available:
77
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
88
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
99

10+
## React Compiler
11+
12+
The React Compiler is not enabled on this template. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
13+
1014
## Expanding the ESLint configuration
1115

1216
If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.

0 commit comments

Comments
 (0)