Skip to content

Commit e8c79e6

Browse files
committed
[cna] Add reactCompiler option
This PR adds a new `reactCompiler` option to create-next-app. To provide more time for build perf measurements, this option defaults to "no" for now. When React Compiler is enabled, create-next-app will: 1. Add the experimental config enabling the compiler to next.config 2. Install babel-plugin-react-compiler, pinned to the latest rc 19.1.0-rc.2 Test plan: Double checked that the generated next.config.ts contains the flag and that babel-plugin-react-compiler was installed as a devDep. **OFF** ``` $ pnpm build $ dist/index.js ✔ What is your project named? … my-app ✔ Would you like to use TypeScript? … No / Yes ✔ Would you like to use ESLint? … No / Yes ✔ Would you like to use React Compiler (Release Candidate)? … No / Yes ✔ Would you like to use Tailwind CSS? … No / Yes ✔ Would you like your code inside a `src/` directory? … No / Yes ✔ Would you like to use App Router? (recommended) … No / Yes ✔ Would you like to use Turbopack for `next dev`? … No / Yes ✔ Would you like to customize the import alias (`@/*` by default)? … No / Yes Creating a new Next.js app in /Users/laurentan/code/next.js/packages/create-next-app/my-app. Using npm. Initializing project with template: app-tw Installing dependencies: - react - react-dom - next Installing devDependencies: - typescript - @types/node - @types/react - @types/react-dom - @tailwindcss/postcss - tailwindcss - eslint - eslint-config-next - @eslint/eslintrc <snip> Success! Created my-app at my-app ``` **ON** ``` $ pnpm build $ dist/index.js ✔ What is your project named? … my-app ✔ Would you like to use TypeScript? … No / Yes ✔ Would you like to use ESLint? … No / Yes ✔ Would you like to use React Compiler (Release Candidate)? … No / Yes ✔ Would you like to use Tailwind CSS? … No / Yes ✔ Would you like your code inside a `src/` directory? … No / Yes ✔ Would you like to use App Router? (recommended) … No / Yes ✔ Would you like to use Turbopack for `next dev`? … No / Yes ✔ Would you like to customize the import alias (`@/*` by default)? … No / Yes Creating a new Next.js app in /Users/laurentan/code/next.js/packages/create-next-app/my-app. Using npm. Initializing project with template: app-tw Installing dependencies: - react - react-dom - next Installing devDependencies: - babel-plugin-react-compiler - typescript - @types/node - @types/react - @types/react-dom - @tailwindcss/postcss - tailwindcss - eslint - eslint-config-next - @eslint/eslintrc <snip> Success! Created my-app at my-app ```
1 parent 1180a6e commit e8c79e6

File tree

13 files changed

+91
-0
lines changed

13 files changed

+91
-0
lines changed

packages/create-next-app/create-app.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export async function createApp({
4040
turbopack,
4141
rspack,
4242
disableGit,
43+
reactCompiler,
4344
}: {
4445
appPath: string
4546
packageManager: PackageManager
@@ -57,6 +58,7 @@ export async function createApp({
5758
turbopack: boolean
5859
rspack: boolean
5960
disableGit?: boolean
61+
reactCompiler: boolean
6062
}): Promise<void> {
6163
let repoInfo: RepoInfo | undefined
6264
const mode: TemplateMode = typescript ? 'ts' : 'js'
@@ -240,6 +242,7 @@ export async function createApp({
240242
skipInstall,
241243
turbopack,
242244
rspack,
245+
reactCompiler,
243246
})
244247
}
245248

packages/create-next-app/index.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const program = new Command(packageJson.name)
4949
.option('--ts, --typescript', 'Initialize as a TypeScript project. (default)')
5050
.option('--js, --javascript', 'Initialize as a JavaScript project.')
5151
.option('--tailwind', 'Initialize with Tailwind CSS config. (default)')
52+
.option('--react-compiler', 'Initialize with React Compiler enabled.')
5253
.option('--eslint', 'Initialize with ESLint config.')
5354
.option('--app', 'Initialize as an App Router project.')
5455
.option('--src-dir', "Initialize inside a 'src/' directory.")
@@ -237,6 +238,7 @@ async function run(): Promise<void> {
237238
empty: false,
238239
turbopack: true,
239240
disableGit: false,
241+
reactCompiler: false,
240242
}
241243
const getPrefOrDefault = (field: string) =>
242244
preferences[field] ?? defaults[field]
@@ -296,6 +298,29 @@ async function run(): Promise<void> {
296298
}
297299
}
298300

301+
if (
302+
!opts.reactCompiler &&
303+
!args.includes('--no-react-compiler') &&
304+
!opts.api
305+
) {
306+
if (skipPrompt) {
307+
opts.reactCompiler = getPrefOrDefault('reactCompiler')
308+
} else {
309+
const styledReactCompiler = blue('React Compiler')
310+
const { reactCompiler } = await prompts({
311+
onState: onPromptState,
312+
type: 'toggle',
313+
name: 'reactCompiler',
314+
message: `Would you like to use ${styledReactCompiler} (Release Candidate)?`,
315+
initial: getPrefOrDefault('reactCompiler'),
316+
active: 'Yes',
317+
inactive: 'No',
318+
})
319+
opts.reactCompiler = Boolean(reactCompiler)
320+
preferences.reactCompiler = Boolean(reactCompiler)
321+
}
322+
}
323+
299324
if (!opts.tailwind && !args.includes('--no-tailwind') && !opts.api) {
300325
if (skipPrompt) {
301326
opts.tailwind = getPrefOrDefault('tailwind')
@@ -435,6 +460,7 @@ async function run(): Promise<void> {
435460
turbopack: opts.turbopack,
436461
rspack: opts.rspack,
437462
disableGit: opts.disableGit,
463+
reactCompiler: opts.reactCompiler,
438464
})
439465
} catch (reason) {
440466
if (!(reason instanceof DownloadError)) {
@@ -468,6 +494,7 @@ async function run(): Promise<void> {
468494
turbopack: opts.turbopack,
469495
rspack: opts.rspack,
470496
disableGit: opts.disableGit,
497+
reactCompiler: opts.reactCompiler,
471498
})
472499
}
473500
conf.set('preferences', preferences)

packages/create-next-app/templates/index.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ export const installTemplate = async ({
4545
skipInstall,
4646
turbopack,
4747
rspack,
48+
reactCompiler,
4849
}: InstallTemplateArgs) => {
4950
console.log(bold(`Using ${packageManager}.`));
5051

@@ -93,6 +94,28 @@ export const installTemplate = async ({
9394
);
9495
}
9596

97+
if (reactCompiler) {
98+
const nextConfigFile = path.join(
99+
root,
100+
mode === "js" ? "next.config.mjs" : "next.config.ts",
101+
);
102+
let configContent = await fs.readFile(nextConfigFile, "utf8");
103+
104+
if (mode === "ts") {
105+
configContent = configContent.replace(
106+
"const nextConfig: NextConfig = {\n /* config options here */\n};",
107+
`const nextConfig: NextConfig = {\n experimental: {\n reactCompiler: true,\n },\n};`,
108+
);
109+
} else {
110+
configContent = configContent.replace(
111+
"const nextConfig = {};",
112+
`const nextConfig = {\n experimental: {\n reactCompiler: true,\n },\n};`,
113+
);
114+
}
115+
116+
await fs.writeFile(nextConfigFile, configContent);
117+
}
118+
96119
const tsconfigFile = path.join(
97120
root,
98121
mode === "js" ? "jsconfig.json" : "tsconfig.json",
@@ -219,6 +242,12 @@ export const installTemplate = async ({
219242
}
220243
}
221244

245+
if (reactCompiler) {
246+
// Note: When the compiler is stable, the versioning scheme will change to be standalone rather
247+
// than in lockstep with React.
248+
packageJson.devDependencies["babel-plugin-react-compiler"] = "19.1.0-rc.2";
249+
}
250+
222251
/**
223252
* TypeScript projects will have type definitions and other devDependencies.
224253
*/

packages/create-next-app/templates/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,5 @@ export interface InstallTemplateArgs {
3232
skipInstall: boolean;
3333
turbopack: boolean;
3434
rspack: boolean;
35+
reactCompiler: boolean;
3536
}

test/integration/create-next-app/index.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ describe('create-next-app', () => {
3939
'--no-tailwind',
4040
'--no-src-dir',
4141
'--no-import-alias',
42+
'--no-react-compiler',
4243
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
4344
],
4445
nextTgzFilename,
@@ -81,6 +82,7 @@ describe('create-next-app', () => {
8182
'--no-tailwind',
8283
'--no-src-dir',
8384
'--no-import-alias',
85+
'--no-react-compiler',
8486
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
8587
],
8688
nextTgzFilename,
@@ -113,6 +115,7 @@ describe('create-next-app', () => {
113115
'--no-src-dir',
114116
'--no-import-alias',
115117
'--skip-install',
118+
'--no-react-compiler',
116119
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
117120
],
118121
nextTgzFilename,

test/integration/create-next-app/package-manager/bun.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ describe('create-next-app with package manager bun', () => {
4949
'--no-src-dir',
5050
'--no-tailwind',
5151
'--no-import-alias',
52+
'--no-react-compiler',
5253
],
5354
nextTgzFilename,
5455
{
@@ -78,6 +79,7 @@ describe('create-next-app with package manager bun', () => {
7879
'--no-src-dir',
7980
'--no-tailwind',
8081
'--no-import-alias',
82+
'--no-react-compiler',
8183
],
8284
nextTgzFilename,
8385
{

test/integration/create-next-app/package-manager/npm.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ describe('create-next-app with package manager npm', () => {
3838
'--no-src-dir',
3939
'--no-tailwind',
4040
'--no-import-alias',
41+
'--no-react-compiler',
4142
],
4243
nextTgzFilename,
4344
{
@@ -67,6 +68,7 @@ describe('create-next-app with package manager npm', () => {
6768
'--no-src-dir',
6869
'--no-tailwind',
6970
'--no-import-alias',
71+
'--no-react-compiler',
7072
],
7173
nextTgzFilename,
7274
{

test/integration/create-next-app/package-manager/pnpm.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ describe('create-next-app with package manager pnpm', () => {
3838
'--no-src-dir',
3939
'--no-tailwind',
4040
'--no-import-alias',
41+
'--no-react-compiler',
4142
],
4243
nextTgzFilename,
4344
{
@@ -67,6 +68,7 @@ describe('create-next-app with package manager pnpm', () => {
6768
'--no-src-dir',
6869
'--no-tailwind',
6970
'--no-import-alias',
71+
'--no-react-compiler',
7072
],
7173
nextTgzFilename,
7274
{

test/integration/create-next-app/package-manager/yarn.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ describe('create-next-app with package manager yarn', () => {
4646
'--no-src-dir',
4747
'--no-tailwind',
4848
'--no-import-alias',
49+
'--no-react-compiler',
4950
],
5051
nextTgzFilename,
5152
{
@@ -75,6 +76,7 @@ describe('create-next-app with package manager yarn', () => {
7576
'--no-src-dir',
7677
'--no-tailwind',
7778
'--no-import-alias',
79+
'--no-react-compiler',
7880
],
7981
nextTgzFilename,
8082
{

test/integration/create-next-app/prompts.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ describe('create-next-app prompts', () => {
2929
'--no-src-dir',
3030
'--no-tailwind',
3131
'--no-import-alias',
32+
'--no-react-compiler',
3233
],
3334
{
3435
cwd,
@@ -68,6 +69,7 @@ describe('create-next-app prompts', () => {
6869
'--no-tailwind',
6970
'--no-src-dir',
7071
'--no-import-alias',
72+
'--no-react-compiler',
7173
],
7274
{
7375
cwd,
@@ -104,6 +106,7 @@ describe('create-next-app prompts', () => {
104106
'--no-turbopack',
105107
'--no-src-dir',
106108
'--no-import-alias',
109+
'--no-react-compiler',
107110
],
108111
{
109112
cwd,
@@ -140,6 +143,7 @@ describe('create-next-app prompts', () => {
140143
'--no-turbopack',
141144
'--no-tailwind',
142145
'--no-src-dir',
146+
'--no-react-compiler',
143147
],
144148
{
145149
cwd,

0 commit comments

Comments
 (0)