Files
2bf38b0115 feat: add experimental.swcEnvOptions for SWC preset-env configuration (#92272)
### What?

Add `experimental.swcEnvOptions` to expose SWC's preset-env `env`
configuration options — including `mode`, `coreJs`, `include`,
`exclude`, `skip`, `shippedProposals`, `forceAllTransforms`, `debug`,
and `loose`.

### Why?

Currently Next.js only passes `env.targets` (derived from browserslist)
to SWC for **syntax downleveling**, but does not expose the polyfill
injection capabilities that SWC already supports. This means:

- Users who need automatic core-js polyfills (e.g.
`Array.prototype.at()`, `Promise.withResolvers()`, `Set` methods) have
no built-in way to get them.
- The only workarounds are importing `core-js` globally (which bloats
bundles significantly) or ejecting to Babel with `useBuiltIns: 'usage'`
(which sacrifices SWC's performance benefits).
- In the Babel era, Next.js supported this via `@babel/preset-env`'s
`useBuiltIns` (PR #10574). That capability was lost when Next.js
migrated to SWC.

### How?

A new `experimental.swcEnvOptions` config is added. Its properties are
spread into the `env` block that Next.js passes to SWC for client-side
compilation, alongside the existing browserslist-derived `targets`.
Server-side compilation is unaffected (always targets `node`).

The option surface mirrors [SWC's preset-env
docs](https://swc.rs/docs/configuration/supported-browsers) 1:1, keeping
it familiar and forward-compatible.

```js
// next.config.js
module.exports = {
  experimental: {
    swcEnvOptions: {
      mode: 'usage',
      coreJs: '3.38',
    },
  },
}
```
#### Changes:
config-shared.ts — type definition with JSDoc
config-schema.ts — zod validation
next-swc-loader.ts → swc/options.ts — plumb config into the SWC env
block
Unit tests (6 cases) + e2e test (dev & production)

Related issues #66562, #63104, #74978
Related discussion #46724

---------

Co-authored-by: Benjamin Woodruff <[email protected]>
2026-04-03 20:27:04 -07:00

9 lines
174 B
TypeScript

import { ReactNode } from 'react'
export default function Root({ children }: { children: ReactNode }) {
return (
<html>
<body>{children}</body>
</html>
)
}