diff --git a/docs/advanced-features/compiler.md b/docs/advanced-features/compiler.md
index 9e1549972178c..439474fa11f33 100644
--- a/docs/advanced-features/compiler.md
+++ b/docs/advanced-features/compiler.md
@@ -7,9 +7,10 @@ description: Learn about the Next.js Compiler, written in Rust, which transforms
Version History
-| Version | Changes |
-| --------- | --------------------------------------------------------------- |
-| `v12.0.0` | Next.js Compiler [introduced](https://nextjs.org/blog/next-12). |
+| Version | Changes |
+| --------- | ---------------------------------------------------------------------------------------------------------------------------------- |
+| `v12.1.0` | Added support for Styled Components, Jest, Relay, Remove React Properties, Legacy Decorators, Remove Console, and jsxImportSource. |
+| `v12.0.0` | Next.js Compiler [introduced](https://nextjs.org/blog/next-12). |
@@ -30,21 +31,7 @@ We chose to build on SWC for a few reasons:
- **WebAssembly:** Rust's support for WASM is essential for supporting all possible platforms and taking Next.js development everywhere.
- **Community:** The Rust community and ecosystem are amazing and still growing.
-## Experimental Features
-
-### Minification
-
-You can opt-in to using the Next.js compiler for minification. This is 7x faster than Terser.
-
-```js
-// next.config.js
-
-module.exports = {
- swcMinify: true,
-}
-```
-
-If you have feedback about `swcMinify`, please share it on the [feedback discussion](https://github.com/vercel/next.js/discussions/30237).
+## Supported Features
### Styled Components
@@ -56,7 +43,7 @@ First, update to the latest version of Next.js: `npm install next@latest`. Then,
// next.config.js
module.exports = {
- experimental: {
+ compiler: {
// ssr and displayName are configured by default
styledComponents: true,
},
@@ -101,7 +88,7 @@ To enable [Relay](https://relay.dev/) support:
```js
// next.config.js
module.exports = {
- experimental: {
+ compiler: {
relay: {
// This should match relay.config.js
src: './',
@@ -123,7 +110,7 @@ To remove properties matching the default regex `^data-test`:
```js
// next.config.js
module.exports = {
- experimental: {
+ compiler: {
reactRemoveProperties: true,
},
}
@@ -134,7 +121,7 @@ To remove custom properties:
```js
// next.config.js
module.exports = {
- experimental: {
+ compiler: {
// The regexes defined here are processed in Rust so the syntax is different from
// JavaScript `RegExp`s. See https://docs.rs/regex.
reactRemoveProperties: { properties: ['^data-custom$'] },
@@ -142,22 +129,6 @@ module.exports = {
}
```
-### Legacy Decorators
-
-Next.js will automatically detect `experimentalDecorators` in `jsconfig.json` or `tsconfig.json` and apply that. This is commonly used with older versions of libraries like `mobx`.
-
-This flag is only supported for compatibility with existing applications. We do not recommend using legacy decorators in new applications.
-
-First, update to the latest version of Next.js: `npm install next@latest`. Then, update your `jsconfig.json` or `tsconfig.json` file:
-
-```js
-{
- "compilerOptions": {
- "experimentalDecorators": true
- }
-}
-```
-
### Remove Console
This transform allows for removing all `console.*` calls in application code (not `node_modules`). Similar to `babel-plugin-transform-remove-console`.
@@ -167,7 +138,7 @@ Remove all `console.*` calls:
```js
// next.config.js
module.exports = {
- experimental: {
+ compiler: {
removeConsole: true,
},
}
@@ -178,7 +149,7 @@ Remove `console.*` output except `console.error`:
```js
// next.config.js
module.exports = {
- experimental: {
+ compiler: {
removeConsole: {
exclude: ['error'],
},
@@ -186,6 +157,22 @@ module.exports = {
}
```
+### Legacy Decorators
+
+Next.js will automatically detect `experimentalDecorators` in `jsconfig.json` or `tsconfig.json`. Legacy decorators are commonly used with older versions of libraries like `mobx`.
+
+This flag is only supported for compatibility with existing applications. We do not recommend using legacy decorators in new applications.
+
+First, update to the latest version of Next.js: `npm install next@latest`. Then, update your `jsconfig.json` or `tsconfig.json` file:
+
+```js
+{
+ "compilerOptions": {
+ "experimentalDecorators": true
+ }
+}
+```
+
### importSource
Next.js will automatically detect `jsxImportSource` in `jsconfig.json` or `tsconfig.json` and apply that. This is commonly used with libraries like Theme UI.
@@ -195,11 +182,27 @@ First, update to the latest version of Next.js: `npm install next@latest`. Then,
```js
{
"compilerOptions": {
- "jsxImportSource": true
+ "jsxImportSource": 'preact'
}
}
```
+## Experimental Features
+
+### Minification
+
+You can opt-in to using the Next.js compiler for minification. This is 7x faster than Terser.
+
+```js
+// next.config.js
+
+module.exports = {
+ swcMinify: true,
+}
+```
+
+If you have feedback about `swcMinify`, please share it on the [feedback discussion](https://github.com/vercel/next.js/discussions/30237).
+
## Unsupported Features
When your application has a `.babelrc` file, Next.js will automatically fall back to using Babel for transforming individual files. This ensures backwards compatibility with existing applications that leverage custom Babel plugins.
diff --git a/errors/ignored-compiler-options.md b/errors/ignored-compiler-options.md
new file mode 100644
index 0000000000000..edab33451d6ec
--- /dev/null
+++ b/errors/ignored-compiler-options.md
@@ -0,0 +1,9 @@
+# ignored-compiler-options
+
+#### Why This Error Occurred
+
+Options under the `compiler` key in `next.config.js` only apply to the new Rust based compiler and will be ignored if Babel is used instead. This message will appear if Next.js detects a Babel configuration file while `compiler` options are configured in `next.config.js`
+
+### Useful Links
+
+- [Next.js Compiler](https://nextjs.org/docs/advanced-features/compiler)
diff --git a/errors/manifest.json b/errors/manifest.json
index 568ca2fffdafb..a7e0bc694424a 100644
--- a/errors/manifest.json
+++ b/errors/manifest.json
@@ -32,7 +32,10 @@
"title": "404-get-initial-props",
"path": "/errors/404-get-initial-props.md"
},
- { "title": "amp-bind-jsx-alt", "path": "/errors/amp-bind-jsx-alt.md" },
+ {
+ "title": "amp-bind-jsx-alt",
+ "path": "/errors/amp-bind-jsx-alt.md"
+ },
{
"title": "amp-export-validation",
"path": "/errors/amp-export-validation.md"
@@ -89,9 +92,18 @@
"title": "conflicting-ssg-paths",
"path": "/errors/conflicting-ssg-paths.md"
},
- { "title": "css-global", "path": "/errors/css-global.md" },
- { "title": "css-modules-npm", "path": "/errors/css-modules-npm.md" },
- { "title": "css-npm", "path": "/errors/css-npm.md" },
+ {
+ "title": "css-global",
+ "path": "/errors/css-global.md"
+ },
+ {
+ "title": "css-modules-npm",
+ "path": "/errors/css-modules-npm.md"
+ },
+ {
+ "title": "css-npm",
+ "path": "/errors/css-npm.md"
+ },
{
"title": "custom-error-no-custom-404",
"path": "/errors/custom-error-no-custom-404.md"
@@ -100,7 +112,10 @@
"title": "doc-crossorigin-deprecated",
"path": "/errors/doc-crossorigin-deprecated.md"
},
- { "title": "duplicate-sass", "path": "/errors/duplicate-sass.md" },
+ {
+ "title": "duplicate-sass",
+ "path": "/errors/duplicate-sass.md"
+ },
{
"title": "empty-configuration",
"path": "/errors/empty-configuration.md"
@@ -121,7 +136,10 @@
"title": "export-all-in-page",
"path": "/errors/export-all-in-page.md"
},
- { "title": "export-image-api", "path": "/errors/export-image-api.md" },
+ {
+ "title": "export-image-api",
+ "path": "/errors/export-image-api.md"
+ },
{
"title": "export-no-custom-routes",
"path": "/errors/export-no-custom-routes.md"
@@ -154,7 +172,10 @@
"title": "gssp-component-member",
"path": "/errors/gssp-component-member.md"
},
- { "title": "gssp-export", "path": "/errors/gssp-export.md" },
+ {
+ "title": "gssp-export",
+ "path": "/errors/gssp-export.md"
+ },
{
"title": "gssp-mixed-not-found-redirect",
"path": "/errors/gssp-mixed-not-found-redirect.md"
@@ -163,12 +184,18 @@
"title": "gssp-no-mutating-res",
"path": "/errors/gssp-no-mutating-res.md"
},
- { "title": "head-build-id", "path": "/errors/head-build-id.md" },
+ {
+ "title": "head-build-id",
+ "path": "/errors/head-build-id.md"
+ },
{
"title": "href-interpolation-failed",
"path": "/errors/href-interpolation-failed.md"
},
- { "title": "improper-devtool", "path": "/errors/improper-devtool.md" },
+ {
+ "title": "improper-devtool",
+ "path": "/errors/improper-devtool.md"
+ },
{
"title": "incompatible-href-as",
"path": "/errors/incompatible-href-as.md"
@@ -177,8 +204,14 @@
"title": "inline-script-id",
"path": "/errors/inline-script-id.md"
},
- { "title": "install-sass", "path": "/errors/install-sass.md" },
- { "title": "install-sharp", "path": "/errors/install-sharp.md" },
+ {
+ "title": "install-sass",
+ "path": "/errors/install-sass.md"
+ },
+ {
+ "title": "install-sharp",
+ "path": "/errors/install-sharp.md"
+ },
{
"title": "invalid-assetprefix",
"path": "/errors/invalid-assetprefix.md"
@@ -251,7 +284,10 @@
"title": "link-passhref",
"path": "/errors/link-passhref.md"
},
- { "title": "manifest.json", "path": "/errors/manifest.json" },
+ {
+ "title": "manifest.json",
+ "path": "/errors/manifest.json"
+ },
{
"title": "minification-disabled",
"path": "/errors/minification-disabled.md"
@@ -264,7 +300,10 @@
"title": "missing-env-value",
"path": "/errors/missing-env-value.md"
},
- { "title": "multi-tabs", "path": "/errors/multi-tabs.md" },
+ {
+ "title": "multi-tabs",
+ "path": "/errors/multi-tabs.md"
+ },
{
"title": "nested-reserved-page",
"path": "/errors/nested-reserved-page.md"
@@ -305,8 +344,14 @@
"title": "next-start-serverless",
"path": "/errors/next-start-serverless.md"
},
- { "title": "no-cache", "path": "/errors/no-cache.md" },
- { "title": "no-css-tags", "path": "/errors/no-css-tags.md" },
+ {
+ "title": "no-cache",
+ "path": "/errors/no-cache.md"
+ },
+ {
+ "title": "no-css-tags",
+ "path": "/errors/no-css-tags.md"
+ },
{
"title": "no-document-import-in-page",
"path": "/errors/no-document-import-in-page.md"
@@ -379,17 +424,26 @@
"title": "popstate-state-empty",
"path": "/errors/popstate-state-empty.md"
},
- { "title": "postcss-function", "path": "/errors/postcss-function.md" },
+ {
+ "title": "postcss-function",
+ "path": "/errors/postcss-function.md"
+ },
{
"title": "postcss-ignored-plugin",
"path": "/errors/postcss-ignored-plugin.md"
},
- { "title": "postcss-shape", "path": "/errors/postcss-shape.md" },
+ {
+ "title": "postcss-shape",
+ "path": "/errors/postcss-shape.md"
+ },
{
"title": "prefetch-true-deprecated",
"path": "/errors/prefetch-true-deprecated.md"
},
- { "title": "prerender-error", "path": "/errors/prerender-error.md" },
+ {
+ "title": "prerender-error",
+ "path": "/errors/prerender-error.md"
+ },
{
"title": "production-start-no-build-id",
"path": "/errors/production-start-no-build-id.md"
@@ -402,7 +456,10 @@
"title": "public-next-folder-conflict",
"path": "/errors/public-next-folder-conflict.md"
},
- { "title": "react-version", "path": "/errors/react-version.md" },
+ {
+ "title": "react-version",
+ "path": "/errors/react-version.md"
+ },
{
"title": "render-no-starting-slash",
"path": "/errors/render-no-starting-slash.md"
@@ -427,13 +484,22 @@
"title": "static-dir-deprecated",
"path": "/errors/static-dir-deprecated.md"
},
- { "title": "threw-undefined", "path": "/errors/threw-undefined.md" },
+ {
+ "title": "threw-undefined",
+ "path": "/errors/threw-undefined.md"
+ },
{
"title": "undefined-webpack-config",
"path": "/errors/undefined-webpack-config.md"
},
- { "title": "url-deprecated", "path": "/errors/url-deprecated.md" },
- { "title": "webpack5", "path": "/errors/webpack5.md" },
+ {
+ "title": "url-deprecated",
+ "path": "/errors/url-deprecated.md"
+ },
+ {
+ "title": "webpack5",
+ "path": "/errors/webpack5.md"
+ },
{
"title": "client-side-exception-occurred",
"path": "/errors/client-side-exception-occurred.md"
@@ -446,8 +512,14 @@
"title": "link-multiple-children",
"path": "/errors/link-multiple-children.md"
},
- { "title": "no-img-element", "path": "/errors/no-img-element.md" },
- { "title": "no-head-element", "path": "/errors/no-head-element.md" },
+ {
+ "title": "no-img-element",
+ "path": "/errors/no-img-element.md"
+ },
+ {
+ "title": "no-head-element",
+ "path": "/errors/no-head-element.md"
+ },
{
"title": "non-dynamic-getstaticpaths-usage",
"path": "/errors/non-dynamic-getstaticpaths-usage.md"
@@ -543,6 +615,10 @@
{
"title": "deleting-query-params-in-middlewares",
"path": "/errors/deleting-query-params-in-middlewares.md"
+ },
+ {
+ "title": "ignored-compiler-options",
+ "path": "/errors/ignored-compiler-options.md"
}
]
}
diff --git a/packages/next/build/swc/options.js b/packages/next/build/swc/options.js
index 71504105236b4..2d2cbee22fa8b 100644
--- a/packages/next/build/swc/options.js
+++ b/packages/next/build/swc/options.js
@@ -81,14 +81,14 @@ export function getBaseSWCOptions({
},
},
sourceMaps: jest ? 'inline' : undefined,
- styledComponents: nextConfig?.experimental?.styledComponents
+ styledComponents: nextConfig?.compiler?.styledComponents
? {
displayName: Boolean(development),
}
: null,
- removeConsole: nextConfig?.experimental?.removeConsole,
- reactRemoveProperties: nextConfig?.experimental?.reactRemoveProperties,
- relay: nextConfig?.experimental?.relay,
+ removeConsole: nextConfig?.compiler?.removeConsole,
+ reactRemoveProperties: nextConfig?.compiler?.reactRemoveProperties,
+ relay: nextConfig?.compiler?.relay,
}
}
diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts
index c710bd5c1712b..20c86444faa5a 100644
--- a/packages/next/build/webpack-config.ts
+++ b/packages/next/build/webpack-config.ts
@@ -86,6 +86,7 @@ const devtoolRevertWarning = execOnce(
)
let loggedSwcDisabled = false
+let loggedIgnoredCompilerOptions = false
function getOptimizedAliases(): { [pkg: string]: string } {
const stubWindowFetch = path.join(__dirname, 'polyfills', 'fetch', 'index.js')
@@ -436,6 +437,13 @@ export default async function getBaseWebpackConfig(
loggedSwcDisabled = true
}
+ if (!loggedIgnoredCompilerOptions && !useSWCLoader && config.compiler) {
+ Log.info(
+ '`compiler` options in `next.config.js` will be ignored while using Babel https://next.js.org/docs/messages/ignored-compiler-options'
+ )
+ loggedIgnoredCompilerOptions = true
+ }
+
const getBabelOrSwcLoader = (isMiddleware: boolean) => {
return useSWCLoader
? {
@@ -1517,6 +1525,18 @@ export default async function getBaseWebpackConfig(
new Map([
['swcLoader', useSWCLoader],
['swcMinify', config.swcMinify],
+ ['swcRelay', !!config.compiler?.relay],
+ ['swcStyledComponents', !!config.compiler?.styledComponents],
+ [
+ 'swcReactRemoveProperties',
+ !!config.compiler?.reactRemoveProperties,
+ ],
+ [
+ 'swcExperimentalDecorators',
+ !!jsConfig?.compilerOptions?.experimentalDecorators,
+ ],
+ ['swcRemoveConsole', !!config.compiler?.removeConsole],
+ ['swcImportSource', !!jsConfig?.compilerOptions?.jsxImportSource],
])
),
].filter(Boolean as any as ExcludesFalse),
@@ -1627,10 +1647,10 @@ export default async function getBaseWebpackConfig(
runtime,
swcMinify: config.swcMinify,
swcLoader: useSWCLoader,
- removeConsole: config.experimental.removeConsole,
- reactRemoveProperties: config.experimental.reactRemoveProperties,
- styledComponents: config.experimental.styledComponents,
- relay: config.experimental.relay,
+ removeConsole: config.compiler?.removeConsole,
+ reactRemoveProperties: config.compiler?.reactRemoveProperties,
+ styledComponents: config.compiler?.styledComponents,
+ relay: config.compiler?.relay,
})
const cache: any = {
diff --git a/packages/next/build/webpack/plugins/telemetry-plugin.ts b/packages/next/build/webpack/plugins/telemetry-plugin.ts
index e961aacb05e6f..fe1f370a283bb 100644
--- a/packages/next/build/webpack/plugins/telemetry-plugin.ts
+++ b/packages/next/build/webpack/plugins/telemetry-plugin.ts
@@ -6,6 +6,12 @@ type Feature =
| 'next/dynamic'
| 'swcLoader'
| 'swcMinify'
+ | 'swcRelay'
+ | 'swcStyledComponents'
+ | 'swcReactRemoveProperties'
+ | 'swcExperimentalDecorators'
+ | 'swcRemoveConsole'
+ | 'swcImportSource'
interface FeatureUsage {
featureName: Feature
@@ -35,7 +41,16 @@ const FEATURE_MODULE_MAP: ReadonlyMap = new Map([
])
// List of build features used in webpack configuration
-const BUILD_FEATURES: Array = ['swcLoader', 'swcMinify']
+const BUILD_FEATURES: Array = [
+ 'swcLoader',
+ 'swcMinify',
+ 'swcRelay',
+ 'swcStyledComponents',
+ 'swcReactRemoveProperties',
+ 'swcExperimentalDecorators',
+ 'swcRemoveConsole',
+ 'swcImportSource',
+]
/**
* Plugin that queries the ModuleGraph to look for modules that correspond to
diff --git a/packages/next/server/config-shared.ts b/packages/next/server/config-shared.ts
index c7f4037e6a808..e7ad981516692 100644
--- a/packages/next/server/config-shared.ts
+++ b/packages/next/server/config-shared.ts
@@ -75,17 +75,6 @@ export interface NextJsWebpackConfig {
export interface ExperimentalConfig {
disablePostcssPresetEnv?: boolean
- removeConsole?:
- | boolean
- | {
- exclude?: string[]
- }
- reactRemoveProperties?:
- | boolean
- | {
- properties?: string[]
- }
- styledComponents?: boolean
swcMinify?: boolean
swcFileReading?: boolean
cpus?: number
@@ -118,11 +107,6 @@ export interface ExperimentalConfig {
urlImports?: NonNullable['buildHttp']
outputFileTracingRoot?: string
outputStandalone?: boolean
- relay?: {
- src: string
- artifactDirectory?: string
- language?: 'typescript' | 'flow'
- }
}
/**
@@ -376,6 +360,30 @@ export interface NextConfig extends Record {
*/
swcMinify?: boolean
+ /**
+ * Optionally enable compiler transforms
+ *
+ * @see [Supported Compiler Options](https://nextjs.org/docs/advanced-features/compiler#supported-features)
+ */
+ compiler?: {
+ reactRemoveProperties?:
+ | boolean
+ | {
+ properties?: string[]
+ }
+ relay?: {
+ src: string
+ artifactDirectory?: string
+ language?: 'typescript' | 'flow'
+ }
+ removeConsole?:
+ | boolean
+ | {
+ exclude?: string[]
+ }
+ styledComponents?: boolean
+ }
+
/**
* Enable experimental features. Note that all experimental features are subject to breaking changes in the future.
*/
diff --git a/packages/next/server/config.ts b/packages/next/server/config.ts
index 6a64992688521..04a1727eddf2d 100644
--- a/packages/next/server/config.ts
+++ b/packages/next/server/config.ts
@@ -365,6 +365,48 @@ function assignDefaults(userConfig: { [key: string]: any }) {
result.swcMinify = (result.experimental as any).swcMinify
}
+ if (result.experimental && 'relay' in (result.experimental as any)) {
+ Log.warn(
+ `\`relay\` has been moved out of \`experimental\` and into \`compiler\`. Please update your ${configFileName} file accordingly.`
+ )
+ result.compiler = result.compiler || {}
+ result.compiler.relay = (result.experimental as any).relay
+ }
+
+ if (
+ result.experimental &&
+ 'styledComponents' in (result.experimental as any)
+ ) {
+ Log.warn(
+ `\`styledComponents\` has been moved out of \`experimental\` and into \`compiler\`. Please update your ${configFileName} file accordingly.`
+ )
+ result.compiler = result.compiler || {}
+ result.compiler.styledComponents = (
+ result.experimental as any
+ ).styledComponents
+ }
+
+ if (
+ result.experimental &&
+ 'reactRemoveProperties' in (result.experimental as any)
+ ) {
+ Log.warn(
+ `\`reactRemoveProperties\` has been moved out of \`experimental\` and into \`compiler\`. Please update your ${configFileName} file accordingly.`
+ )
+ result.compiler = result.compiler || {}
+ result.compiler.reactRemoveProperties = (
+ result.experimental as any
+ ).reactRemoveProperties
+ }
+
+ if (result.experimental && 'removeConsole' in (result.experimental as any)) {
+ Log.warn(
+ `\`removeConsole\` has been moved out of \`experimental\` and into \`compiler\`. Please update your ${configFileName} file accordingly.`
+ )
+ result.compiler = result.compiler || {}
+ result.compiler.removeConsole = (result.experimental as any).removeConsole
+ }
+
if (result.swcMinify) {
Log.warn(
'SWC minify release candidate enabled. https://nextjs.org/docs/messages/swc-minify-enabled'
diff --git a/packages/next/telemetry/events/build.ts b/packages/next/telemetry/events/build.ts
index 0be4c5d4e79a9..e68bbda1dd6d6 100644
--- a/packages/next/telemetry/events/build.ts
+++ b/packages/next/telemetry/events/build.ts
@@ -134,6 +134,12 @@ export type EventBuildFeatureUsage = {
| 'optimizeFonts'
| 'swcLoader'
| 'swcMinify'
+ | 'swcRelay'
+ | 'swcStyledComponents'
+ | 'swcReactRemoveProperties'
+ | 'swcExperimentalDecorators'
+ | 'swcRemoveConsole'
+ | 'swcImportSource'
| 'build-lint'
invocationCount: number
}
diff --git a/test/development/basic/styled-components/next.config.js b/test/development/basic/styled-components/next.config.js
index b125c0d794776..91f693fda5258 100644
--- a/test/development/basic/styled-components/next.config.js
+++ b/test/development/basic/styled-components/next.config.js
@@ -1,5 +1,5 @@
module.exports = {
- experimental: {
+ compiler: {
styledComponents: true,
},
}
diff --git a/test/integration/relay-graphql-swc-multi-project/project-a/next.config.js b/test/integration/relay-graphql-swc-multi-project/project-a/next.config.js
index 79ef26c30f3a1..49b503b7fde0a 100644
--- a/test/integration/relay-graphql-swc-multi-project/project-a/next.config.js
+++ b/test/integration/relay-graphql-swc-multi-project/project-a/next.config.js
@@ -1,7 +1,7 @@
const relay = require('../relay.config')
module.exports = {
- experimental: {
+ compiler: {
relay: {
src: './pages',
artifactDirectory: './__generated__',
diff --git a/test/integration/relay-graphql-swc-multi-project/project-b/next.config.js b/test/integration/relay-graphql-swc-multi-project/project-b/next.config.js
index 79ef26c30f3a1..49b503b7fde0a 100644
--- a/test/integration/relay-graphql-swc-multi-project/project-b/next.config.js
+++ b/test/integration/relay-graphql-swc-multi-project/project-b/next.config.js
@@ -1,7 +1,7 @@
const relay = require('../relay.config')
module.exports = {
- experimental: {
+ compiler: {
relay: {
src: './pages',
artifactDirectory: './__generated__',
diff --git a/test/integration/relay-graphql-swc-single-project/next.config.js b/test/integration/relay-graphql-swc-single-project/next.config.js
index ef214a05ace7a..89574d57d1a6b 100644
--- a/test/integration/relay-graphql-swc-single-project/next.config.js
+++ b/test/integration/relay-graphql-swc-single-project/next.config.js
@@ -1,7 +1,7 @@
const relay = require('./relay.config')
module.exports = {
- experimental: {
+ compiler: {
relay,
},
}
diff --git a/test/integration/telemetry/jsconfig.swc b/test/integration/telemetry/jsconfig.swc
new file mode 100644
index 0000000000000..a178f9dcd04a7
--- /dev/null
+++ b/test/integration/telemetry/jsconfig.swc
@@ -0,0 +1,5 @@
+{
+ "compilerOptions": {
+ "experimentalDecorators": true
+ }
+}
\ No newline at end of file
diff --git a/test/integration/telemetry/next.config.swc b/test/integration/telemetry/next.config.swc
new file mode 100644
index 0000000000000..6394ffee943d8
--- /dev/null
+++ b/test/integration/telemetry/next.config.swc
@@ -0,0 +1,14 @@
+module.exports = {
+ swcMinify: true,
+ compiler: {
+ relay: {
+ // This should match relay.config.js
+ src: './',
+ artifactDirectory: './__generated__',
+ language: 'typescript',
+ },
+ styledComponents: true,
+ removeConsole: true,
+ reactRemoveProperties: true,
+ },
+}
diff --git a/test/integration/telemetry/test/index.test.js b/test/integration/telemetry/test/index.test.js
index add5b0d9665bc..ba86d775b31f3 100644
--- a/test/integration/telemetry/test/index.test.js
+++ b/test/integration/telemetry/test/index.test.js
@@ -619,12 +619,14 @@ describe('Telemetry CLI', () => {
const optimizeFonts = regex.exec(stderr).pop()
expect(optimizeFonts).toContain(`"featureName": "optimizeFonts"`)
expect(optimizeFonts).toContain(`"invocationCount": 1`)
- const swcLoader = regex.exec(stderr).pop()
- expect(swcLoader).toContain(`"featureName": "swcLoader"`)
- expect(swcLoader).toContain(`"invocationCount": 1`)
- const swcMinify = regex.exec(stderr).pop()
- expect(swcMinify).toContain(`"featureName": "swcMinify"`)
- expect(swcMinify).toContain(`"invocationCount": 0`)
+ regex.exec(stderr).pop() // swcLoader
+ regex.exec(stderr).pop() // swcMinify
+ regex.exec(stderr).pop() // swcRelay
+ regex.exec(stderr).pop() // swcStyledComponents
+ regex.exec(stderr).pop() // swcExperimentalDecorators
+ regex.exec(stderr).pop() // swcReactRemoveProperties
+ regex.exec(stderr).pop() // swcRemoveConsole
+ regex.exec(stderr).pop() // swcImportSource
const image = regex.exec(stderr).pop()
expect(image).toContain(`"featureName": "next/image"`)
expect(image).toContain(`"invocationCount": 1`)
@@ -636,6 +638,60 @@ describe('Telemetry CLI', () => {
expect(dynamic).toContain(`"invocationCount": 1`)
})
+ it('emits telemetry for usage of swc', async () => {
+ await fs.remove(path.join(appDir, 'next.config.js'))
+ await fs.remove(path.join(appDir, 'jsconfig.json'))
+ await fs.rename(
+ path.join(appDir, 'next.config.swc'),
+ path.join(appDir, 'next.config.js')
+ )
+ await fs.rename(
+ path.join(appDir, 'jsconfig.swc'),
+ path.join(appDir, 'jsconfig.json')
+ )
+ const { stderr } = await nextBuild(appDir, [], {
+ stderr: true,
+ env: { NEXT_TELEMETRY_DEBUG: 1 },
+ })
+ await fs.remove(path.join(appDir, 'next.config.js'))
+ await fs.remove(path.join(appDir, 'jsconfig.json'))
+
+ const regex = /NEXT_BUILD_FEATURE_USAGE[\s\S]+?{([\s\S]+?)}/g
+ regex.exec(stderr).pop() // optimizeCss
+ regex.exec(stderr).pop() // build-lint
+ regex.exec(stderr).pop() // optimizeFonts
+ const swcLoader = regex.exec(stderr).pop()
+ expect(swcLoader).toContain(`"featureName": "swcLoader"`)
+ expect(swcLoader).toContain(`"invocationCount": 1`)
+ const swcMinify = regex.exec(stderr).pop()
+ expect(swcMinify).toContain(`"featureName": "swcMinify"`)
+ expect(swcMinify).toContain(`"invocationCount": 1`)
+ const swcRelay = regex.exec(stderr).pop()
+ expect(swcRelay).toContain(`"featureName": "swcRelay"`)
+ expect(swcRelay).toContain(`"invocationCount": 1`)
+ const swcStyledComponents = regex.exec(stderr).pop()
+ expect(swcStyledComponents).toContain(
+ `"featureName": "swcStyledComponents"`
+ )
+ expect(swcStyledComponents).toContain(`"invocationCount": 1`)
+ const swcReactRemoveProperties = regex.exec(stderr).pop()
+ expect(swcReactRemoveProperties).toContain(
+ `"featureName": "swcReactRemoveProperties"`
+ )
+ expect(swcReactRemoveProperties).toContain(`"invocationCount": 1`)
+ const swcExperimentalDecorators = regex.exec(stderr).pop()
+ expect(swcExperimentalDecorators).toContain(
+ `"featureName": "swcExperimentalDecorators"`
+ )
+ expect(swcExperimentalDecorators).toContain(`"invocationCount": 1`)
+ const swcRemoveConsole = regex.exec(stderr).pop()
+ expect(swcRemoveConsole).toContain(`"featureName": "swcRemoveConsole"`)
+ expect(swcRemoveConsole).toContain(`"invocationCount": 1`)
+ const swcImportSource = regex.exec(stderr).pop()
+ expect(swcImportSource).toContain(`"featureName": "swcImportSource"`)
+ expect(swcImportSource).toContain(`"invocationCount": 0`)
+ })
+
it('emits telemetry for usage of `optimizeCss`', async () => {
await fs.rename(
path.join(appDir, 'next.config.optimize-css'),