Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(next): next.config.ts #57656

Closed
wants to merge 129 commits into from

Conversation

devjiwonchoi
Copy link
Contributor

@devjiwonchoi devjiwonchoi commented Oct 28, 2023

Ported to #63051

What?

This PR initiated support of next.config.ts using SWC and webpack.

  • Add docs for next.config.ts.
  • Modify create-next-app for TS to create next.config.ts by default.

Why?

Next.js provides a TypeScript-first development experience for building your React application.

This PR can resolve the two main needs:

  1. Import TS files to the config.
  2. Conduct a type check directly by importing type not JSDoc.

As mentioned in #35969 (comment), it became possible to transpile the config fast enough to have less pain on DX.
The current method impacts the transpilation time less than a 0.1s increase in HMR.

x-ref: #5318 #35969 #44632 #50121 #50126

How?

Used webpack as mentioned in #50126 (review), only on cases where the config imports other modules.

  1. Transpile-only with SWC if the config has no valid imports(types or unused), which is the case for most users.
  2. If the imports are given, bundle with webpack to resolve imports with various conditions and extensions.
  3. To import Native ESM packages in the CommonJS(default for Next.js) project, next.config.mts can handle it.
  4. On the production server, use build cache if exists.

Restrictions

  • The compiled config will be stored in the .next directory, regardless of the distDir option in the config.
  • The __filename will return next.config.ts instead of the default behavior returning the absolute file path.

Expected & Edge Cases

Added tests for the cases below:

  • config as an async function
  • export { x as default }
  • import alias (tsconfig baseUrl and paths)
  • import from node_modules
  • use Node.js API (fs, path, etc.)
  • nested imports (config -> A -> B)
  • migration from next.config.js without change

Native ESM (package.json type: module)

  • importing .cts
  • importing .cjs
  • importing .js (ESM)

CJS

  • importing Native ESM packages (use next.config.mts)
  • importing .mts
  • importing .mjs
  • importing .js (CJS)

Transpilation Speed Profile (format: second)

Open Stats

Test Settings

next.config.ts

Transpile-only (no import)

import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
  env: {
    foo: 'foo',
  },
}

export default nextConfig

Bundle-webpack (has import)

import type { NextConfig } from 'next'
import { foo } from './foo'

const nextConfig: NextConfig = {
  env: {
    foo,
  },
}

export default nextConfig

next dev

Transpile-only (no import)

0.002s
0.002s
0.001s
0.002s
0.002s

Bundle-webpack (has import)

0.069s
0.073s
0.070s
0.069s
0.069s

next build

Transpile-only (no import)

3.237s
3.231s
3.379s
3.481s
3.654s

Bundle-webpack (has import)

3.374s
3.372s
3.332s
3.768s
3.424s

next start

Transpile-only (no import)

0.001s
0.001s
0.001s
0.001s
0.001s

Bundle-webpack (has import)

0.001s
0.001s
0.001s
0.001s
0.001s

Spec

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.1.0: Mon Oct  9 21:32:11 PDT 2023; root:xnu-10002.41.9~7/RELEASE_ARM64_T6030
  Available memory (MB): 18432
  Available CPU cores: 11
Binaries:
  Node: 18.17.1
  npm: 9.6.7
  Yarn: N/A
  pnpm: 8.15.1
Relevant Packages:
  next: 14.1.2-canary.2 // Latest available version is detected (14.1.2-canary.2).
  eslint-config-next: 14.1.2-canary.2
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.2.2
Next.js Config:
  output: N/A

@ijjk
Copy link
Member

ijjk commented Oct 28, 2023

Allow CI Workflow Run

  • approve CI run for commit: 1a61b97

Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer

@devjiwonchoi devjiwonchoi marked this pull request as ready for review October 28, 2023 06:28
@vercel-spaces
Copy link

vercel-spaces bot commented Oct 28, 2023

Notifying the following users due to files changed in this PR based on this repo's notify modifiers:

@timneutkens, @ijjk, @shuding, @huozhi:

packages/next/src/server/config.ts

@kdy1
Copy link
Member

kdy1 commented Oct 28, 2023

swc-loader does not have caching logic because transforming every time with SWC was faster than caching due to comparison cost and extra FS operations. Did you profile it?

@devjiwonchoi
Copy link
Contributor Author

I'll remove the caching part. Thank you!

ref: #57656 (comment)

Co-authored-by: Donny/강동윤 <kdy1997.dev@gmail.com>
@devjiwonchoi devjiwonchoi changed the title feat(next-config): Support next config as TypeScript file feat(next): Support next.config.ts Oct 28, 2023
@AhmedBaset
Copy link
Contributor

I opened a PR https://github.com/devjiwonchoi/next.js/pull/1 to make create-next-app create next.config.ts by default when using TypeScript

@devjiwonchoi devjiwonchoi requested a review from a team as a code owner March 3, 2024 13:57
@devjiwonchoi devjiwonchoi requested review from jh3y and molebox and removed request for a team, SukkaW and falsepopsky March 3, 2024 13:57
@@ -319,6 +319,7 @@ When you need to declare custom types, you might be tempted to modify `next-env.

| Version | Changes |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `v14.2.0` | `next.config.ts` support added for TypeScript projects. |
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Temporarily set version as v14.2.0

@devjiwonchoi devjiwonchoi requested a review from samcx as a code owner March 4, 2024 01:31
Copy link
Contributor Author

@devjiwonchoi devjiwonchoi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ijjk These were the final attempts I tried before moving back to webpack.

const swc = transformSync(code, swcOptions)
return originalCompile.call(this, swc.code, filename)
if (isESM) {
// TODO: Implement importing ESM
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to modify require.extensions['.js'] behavior as:

if (isESM) {
  delete (require as any).extensions['.js']
  transformableExtensions.push('.js')
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Received error:

> Build error occurred
Error [ERR_REQUIRE_ESM]: require() of ES Module /tmp/node_modules/esm/foo.js from /tmp/next.config.cjs not supported.
Instead change the require of foo.js in /tmp/next.config.cjs to a dynamic import() which is available in all CommonJS modules.
    at require.extensions.<computed> [as .js]

@@ -101,7 +106,6 @@ export async function transpileConfig({
throw error
} finally {
await unlink(tempConfigPath).catch(() => {})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revert the .js hook.

transformableExtensions.forEach((ext) => delete require.extensions[ext])
require.extensions['.js'] = originalJsHandler
await unlink(tempConfigPath).catch(() => {})

@devjiwonchoi devjiwonchoi closed this by deleting the head repository Mar 8, 2024
@AhmedBaset
Copy link
Contributor

Why this was closed?

@devjiwonchoi
Copy link
Contributor Author

I accidentally deleted the head, finding a way to restore it 😅

@devjiwonchoi devjiwonchoi mentioned this pull request Mar 8, 2024
17 tasks
@joulev
Copy link
Contributor

joulev commented Mar 8, 2024

Phew, I was really looking forward to this feature, and it would be a shame if this was closed intentionally. Please keep up the good work, a large number of users will benefit from this feature!

@devjiwonchoi
Copy link
Contributor Author

@joulev Thank you for your support! I'll do my best to ship it as efficiently as possible. 😄

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 23, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
create-next-app Related to our CLI tool for quickly starting a new Next.js application. locked type: next
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants