Skip to content

Commit 7e5ed3b

Browse files
SyMindijjk
andauthored
feat: --rspack flag for create next app (#79077)
<!-- Thanks for opening a PR! Your contribution is much appreciated. To make sure your PR is handled as smoothly as possible we request that you follow the checklist sections below. Choose the right checklist for the change(s) that you're making: ## For Contributors ### Improving Documentation - Run `pnpm prettier-fix` to fix formatting issues before opening the PR. - Read the Docs Contribution Guide to ensure your contribution follows the docs guidelines: https://nextjs.org/docs/community/contribution-guide ### Adding or Updating Examples - The "examples guidelines" are followed from our contributing doc https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md - Make sure the linting passes by running `pnpm build && pnpm lint`. See https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md ### Fixing a bug - Related issues linked using `fixes #number` - Tests added. See: https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs - Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md ### Adding a feature - Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR. (A discussion must be opened, see https://github.com/vercel/next.js/discussions/new?category=ideas) - Related issues/discussions are linked using `fixes #number` - e2e tests added (https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) - Documentation added - Telemetry added. In case of a feature if it's used or not. - Errors have a helpful link attached, see https://github.com/vercel/next.js/blob/canary/contributing.md ## For Maintainers - Minimal description (aim for explaining to someone not on the team to understand the PR) - When linking to a Slack thread, you might want to share details of the conclusion - Link both the Linear (Fixes NEXT-xxx) and the GitHub issues - Add review comments if necessary to explain to the reviewer the logic behind a change ### What? ### Why? ### How? Closes NEXT- Fixes # --> The PR has resolved the failures in `test/integration/create-next-app/templates/*.test.js`. The `create-next-app` CLI now supports a `--rspack` flag to initialize projects with Rspack. Test cases in `test/integration/create-next-app/templates/*.test.js` have been updated to conditionally use `--rspack` based on `process.env.NEXT_RSPACK`. --------- Co-authored-by: JJ Kasper <jj@jjsweb.site>
1 parent 6a91ff2 commit 7e5ed3b

File tree

11 files changed

+186
-88
lines changed

11 files changed

+186
-88
lines changed

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

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export async function createApp({
3838
empty,
3939
api,
4040
turbopack,
41+
rspack,
4142
disableGit,
4243
}: {
4344
appPath: string
@@ -54,6 +55,7 @@ export async function createApp({
5455
empty: boolean
5556
api?: boolean
5657
turbopack: boolean
58+
rspack: boolean
5759
disableGit?: boolean
5860
}): Promise<void> {
5961
let repoInfo: RepoInfo | undefined
@@ -237,6 +239,7 @@ export async function createApp({
237239
importAlias,
238240
skipInstall,
239241
turbopack,
242+
rspack,
240243
})
241244
}
242245

packages/create-next-app/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ const program = new Command(packageJson.name)
5353
.option('--app', 'Initialize as an App Router project.')
5454
.option('--src-dir', "Initialize inside a 'src/' directory.")
5555
.option('--turbopack', 'Enable Turbopack by default for development.')
56+
.option('--rspack', 'Using Rspack as the bundler')
5657
.option(
5758
'--import-alias <prefix/*>',
5859
'Specify import alias to use (default "@/*").'
@@ -432,6 +433,7 @@ async function run(): Promise<void> {
432433
empty: opts.empty,
433434
api: opts.api,
434435
turbopack: opts.turbopack,
436+
rspack: opts.rspack,
435437
disableGit: opts.disableGit,
436438
})
437439
} catch (reason) {
@@ -464,6 +466,7 @@ async function run(): Promise<void> {
464466
skipInstall: opts.skipInstall,
465467
empty: opts.empty,
466468
turbopack: opts.turbopack,
469+
rspack: opts.rspack,
467470
disableGit: opts.disableGit,
468471
})
469472
}

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

+31
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export const installTemplate = async ({
4444
importAlias,
4545
skipInstall,
4646
turbopack,
47+
rspack,
4748
}: InstallTemplateArgs) => {
4849
console.log(bold(`Using ${packageManager}.`));
4950

@@ -77,6 +78,21 @@ export const installTemplate = async ({
7778
},
7879
});
7980

81+
if (rspack) {
82+
const nextConfigFile = path.join(
83+
root,
84+
mode === "js" ? "next.config.mjs" : "next.config.ts",
85+
);
86+
await fs.writeFile(
87+
nextConfigFile,
88+
`import withRspack from "next-rspack";\n\n` +
89+
(await fs.readFile(nextConfigFile, "utf8")).replace(
90+
"export default nextConfig;",
91+
"export default withRspack(nextConfig);",
92+
),
93+
);
94+
}
95+
8096
const tsconfigFile = path.join(
8197
root,
8298
mode === "js" ? "jsconfig.json" : "tsconfig.json",
@@ -188,6 +204,21 @@ export const installTemplate = async ({
188204
devDependencies: {},
189205
};
190206

207+
if (rspack) {
208+
const NEXT_PRIVATE_TEST_VERSION = process.env.NEXT_PRIVATE_TEST_VERSION;
209+
if (
210+
NEXT_PRIVATE_TEST_VERSION &&
211+
path.isAbsolute(NEXT_PRIVATE_TEST_VERSION)
212+
) {
213+
packageJson.dependencies["next-rspack"] = path.resolve(
214+
path.dirname(NEXT_PRIVATE_TEST_VERSION),
215+
"../next-rspack/next-rspack-packed.tgz",
216+
);
217+
} else {
218+
packageJson.dependencies["next-rspack"] = version;
219+
}
220+
}
221+
191222
/**
192223
* TypeScript projects will have type definitions and other devDependencies.
193224
*/

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

+1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ export interface InstallTemplateArgs {
3131
importAlias: string;
3232
skipInstall: boolean;
3333
turbopack: boolean;
34+
rspack: boolean;
3435
}

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

+24-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@ describe('create-next-app --example', () => {
2828
await useTempDir(async (cwd) => {
2929
const projectName = 'valid-example'
3030
const res = await run(
31-
[projectName, '--example', 'basic-css'],
31+
[
32+
projectName,
33+
'--example',
34+
'basic-css',
35+
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
36+
],
3237
nextTgzFilename,
3338
{
3439
cwd,
@@ -53,7 +58,12 @@ describe('create-next-app --example', () => {
5358
await useTempDir(async (cwd) => {
5459
const projectName = 'github-url'
5560
const res = await run(
56-
[projectName, '--example', FULL_EXAMPLE_PATH],
61+
[
62+
projectName,
63+
'--example',
64+
FULL_EXAMPLE_PATH,
65+
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
66+
],
5767
nextTgzFilename,
5868
{
5969
cwd,
@@ -85,6 +95,7 @@ describe('create-next-app --example', () => {
8595
// since vercel/examples is not a template repo, we use the following
8696
// GH#39665
8797
'https://github.com/vercel/nextjs-portfolio-starter/',
98+
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
8899
],
89100
nextTgzFilename,
90101
{
@@ -119,6 +130,7 @@ describe('create-next-app --example', () => {
119130
EXAMPLE_REPO,
120131
'--example-path',
121132
EXAMPLE_PATH,
133+
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
122134
],
123135
nextTgzFilename,
124136
{
@@ -154,6 +166,7 @@ describe('create-next-app --example', () => {
154166
FULL_EXAMPLE_PATH,
155167
'--example-path',
156168
EXAMPLE_PATH,
169+
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
157170
],
158171
nextTgzFilename,
159172
{
@@ -192,6 +205,7 @@ describe('create-next-app --example', () => {
192205
'--example',
193206
'__internal-testing-retry',
194207
'--import-alias=@/*',
208+
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
195209
],
196210
nextTgzFilename,
197211
{
@@ -224,6 +238,7 @@ describe('create-next-app --example', () => {
224238
'--example',
225239
'default',
226240
'--import-alias=@/*',
241+
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
227242
],
228243
nextTgzFilename,
229244
{
@@ -245,7 +260,12 @@ describe('create-next-app --example', () => {
245260
await useTempDir(async (cwd) => {
246261
const projectName = 'invalid-example'
247262
const res = await run(
248-
[projectName, '--example', 'not a real example'],
263+
[
264+
projectName,
265+
'--example',
266+
'not a real example',
267+
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
268+
],
249269
nextTgzFilename,
250270
{
251271
cwd,
@@ -274,6 +294,7 @@ describe('create-next-app --example', () => {
274294
'--no-src-dir',
275295
'--no-tailwind',
276296
'--example',
297+
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
277298
],
278299
nextTgzFilename,
279300
{

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

+3
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+
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
4243
],
4344
nextTgzFilename,
4445
{
@@ -80,6 +81,7 @@ describe('create-next-app', () => {
8081
'--no-tailwind',
8182
'--no-src-dir',
8283
'--no-import-alias',
84+
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
8385
],
8486
nextTgzFilename,
8587
{
@@ -111,6 +113,7 @@ describe('create-next-app', () => {
111113
'--no-src-dir',
112114
'--no-import-alias',
113115
'--skip-install',
116+
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
114117
],
115118
nextTgzFilename,
116119
{

test/integration/create-next-app/lib/specification.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@ export const projectSpecification: ProjectSpecification = {
3030
'node_modules/next',
3131
'.gitignore',
3232
],
33-
deps: ['next', 'react', 'react-dom'],
33+
deps: [
34+
'next',
35+
'react',
36+
'react-dom',
37+
...(process.env.NEXT_RSPACK ? ['next-rspack'] : []),
38+
],
3439
// TODO: Remove @eslint/eslintrc once eslint-config-next is pure Flat config
3540
devDeps: ['eslint', 'eslint-config-next', '@eslint/eslintrc'],
3641
},
@@ -170,12 +175,12 @@ export const projectSpecification: ProjectSpecification = {
170175
},
171176
'app-api': {
172177
js: {
173-
deps: ['next'],
178+
deps: ['next', ...(process.env.NEXT_RSPACK ? ['next-rspack'] : [])],
174179
devDeps: [],
175180
files: ['app/route.js', 'app/[slug]/route.js', 'jsconfig.json'],
176181
},
177182
ts: {
178-
deps: ['next'],
183+
deps: ['next', ...(process.env.NEXT_RSPACK ? ['next-rspack'] : [])],
179184
devDeps: ['@types/node', '@types/react', 'typescript'],
180185
files: [
181186
'app/route.ts',

test/integration/create-next-app/templates/app-api.test.ts

+36-29
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ describe('create-next-app --api (Headless App)', () => {
6969
'--no-turbopack',
7070
'--no-src-dir',
7171
'--no-import-alias',
72+
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
7273
],
7374
nextTgzFilename,
7475
{
@@ -101,6 +102,7 @@ describe('create-next-app --api (Headless App)', () => {
101102
'--no-turbopack',
102103
'--no-src-dir',
103104
'--no-import-alias',
105+
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
104106
],
105107
nextTgzFilename,
106108
{
@@ -130,6 +132,7 @@ describe('create-next-app --api (Headless App)', () => {
130132
'--no-turbopack',
131133
'--src-dir',
132134
'--no-import-alias',
135+
...(process.env.NEXT_RSPACK ? ['--rspack'] : []),
133136
],
134137
nextTgzFilename,
135138
{
@@ -152,35 +155,39 @@ describe('create-next-app --api (Headless App)', () => {
152155
})
153156
})
154157
})
155-
156-
it('should enable turbopack dev with --turbopack flag', async () => {
157-
await useTempDir(async (cwd) => {
158-
const projectName = 'app-turbo'
159-
const { exitCode } = await run(
160-
[
161-
projectName,
162-
'--ts',
163-
'--api',
164-
'--turbopack',
165-
'--no-src-dir',
166-
'--no-import-alias',
167-
],
168-
nextTgzFilename,
169-
{
158+
;(process.env.NEXT_RSPACK ? it.skip : it)(
159+
'should enable turbopack dev with --turbopack flag',
160+
async () => {
161+
await useTempDir(async (cwd) => {
162+
const projectName = 'app-turbo'
163+
const { exitCode } = await run(
164+
[
165+
projectName,
166+
'--ts',
167+
'--api',
168+
'--turbopack',
169+
'--no-src-dir',
170+
'--no-import-alias',
171+
],
172+
nextTgzFilename,
173+
{
174+
cwd,
175+
}
176+
)
177+
178+
// eslint-disable-next-line jest/no-standalone-expect
179+
expect(exitCode).toBe(0)
180+
const projectRoot = join(cwd, projectName)
181+
const pkgJson = require(join(projectRoot, 'package.json'))
182+
// eslint-disable-next-line jest/no-standalone-expect
183+
expect(pkgJson.scripts.dev).toBe('next dev --turbopack')
184+
185+
await tryNextDev({
170186
cwd,
171-
}
172-
)
173-
174-
expect(exitCode).toBe(0)
175-
const projectRoot = join(cwd, projectName)
176-
const pkgJson = require(join(projectRoot, 'package.json'))
177-
expect(pkgJson.scripts.dev).toBe('next dev --turbopack')
178-
179-
await tryNextDev({
180-
cwd,
181-
isApi: true,
182-
projectName,
187+
isApi: true,
188+
projectName,
189+
})
183190
})
184-
})
185-
})
191+
}
192+
)
186193
})

0 commit comments

Comments
 (0)