Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,7 @@ const nextConfig = {
module.exports = nextConfig
```

> **Good to know:** `sassOptions` are not typed outside of `implementation` because Next.js does not maintain the other possible properties.
> **Good to know:**
>
> - `sassOptions` are not typed outside of `implementation` because Next.js does not maintain the other possible properties.
> - The `functions` property for defining custom Sass functions is only supported with webpack. When using Turbopack, custom Sass functions are not available because Turbopack's Rust-based architecture cannot directly execute JavaScript functions passed through this option.
22 changes: 12 additions & 10 deletions docs/01-app/03-api-reference/08-turbopack.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -72,16 +72,16 @@ Turbopack in Next.js has **zero-configuration** for the common use cases. Below

### CSS and styling

| Feature | Status | Notes |
| ------------------ | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Global CSS** | **Supported** | Import `.css` files directly in your application. |
| **CSS Modules** | **Supported** | `.module.css` files work natively (Lightning CSS). |
| **CSS Nesting** | **Supported** | Lightning CSS supports [modern CSS nesting](https://lightningcss.dev/). |
| **@import syntax** | **Supported** | Combine multiple CSS files. |
| **PostCSS** | **Supported** | Automatically processes `postcss.config.js` in a Node.js worker pool. Useful for Tailwind, Autoprefixer, etc. |
| **Sass / SCSS** | **Supported** (Next.js) | For Next.js, Sass is supported out of the box. In the future, Turbopack standalone usage will likely require a loader config. |
| **Less** | Planned via plugins | Not yet supported by default. Will likely require a loader config once custom loaders are stable. |
| **Lightning CSS** | **In Use** | Handles CSS transformations. Some low-usage CSS Modules features (like `:local/:global` as standalone pseudo-classes) are not yet supported. [See below for more details.](#unsupported-and-unplanned-features) |
| Feature | Status | Notes |
| ------------------ | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Global CSS** | **Supported** | Import `.css` files directly in your application. |
| **CSS Modules** | **Supported** | `.module.css` files work natively (Lightning CSS). |
| **CSS Nesting** | **Supported** | Lightning CSS supports [modern CSS nesting](https://lightningcss.dev/). |
| **@import syntax** | **Supported** | Combine multiple CSS files. |
| **PostCSS** | **Supported** | Automatically processes `postcss.config.js` in a Node.js worker pool. Useful for Tailwind, Autoprefixer, etc. |
| **Sass / SCSS** | **Supported** (Next.js) | For Next.js, Sass is supported out of the box. Custom Sass functions (`sassOptions.functions`) are not supported because Turbopack's Rust-based architecture cannot directly execute JavaScript functions, unlike webpack's Node.js environment. Use webpack if you need this feature. In the future, Turbopack standalone usage will likely require a loader config. |
| **Less** | Planned via plugins | Not yet supported by default. Will likely require a loader config once custom loaders are stable. |
| **Lightning CSS** | **In Use** | Handles CSS transformations. Some low-usage CSS Modules features (like `:local/:global` as standalone pseudo-classes) are not yet supported. [See below for more details.](#unsupported-and-unplanned-features) |

### Assets

Expand Down Expand Up @@ -175,6 +175,8 @@ Some features are not yet implemented or not planned:
- `:import` and `:export` ICSS rules.
- `composes` in `.module.css` composing a `.css` file. In webpack this would treat the `.css` file as a CSS Module, with Turbopack the `.css` file will always be global. This means that if you want to use `composes` in a CSS Module, you need to change the `.css` file to a `.module.css` file.
- `@import` in CSS Modules importing `.css` as a CSS Module. In webpack this would treat the `.css` file as a CSS Module, with Turbopack the `.css` file will always be global. This means that if you want to use `@import` in a CSS Module, you need to change the `.css` file to a `.module.css` file.
- **`sassOptions.functions`**
Custom Sass functions defined in `sassOptions.functions` are not supported. This feature allows defining JavaScript functions that can be called from Sass code during compilation. Turbopack's Rust-based architecture cannot directly execute JavaScript functions passed through `sassOptions.functions`, unlike webpack's Node.js-based sass-loader which runs entirely in JavaScript. If you're using custom Sass functions, you'll need to use webpack instead of Turbopack.
- **`webpack()` configuration** in `next.config.js`
Turbopack replaces webpack, so `webpack()` configs are not recognized. Use the [`turbopack` config](/docs/app/api-reference/config/next-config-js/turbopack) instead.
- **Yarn PnP**
Expand Down
3 changes: 2 additions & 1 deletion packages/next/errors.json
Original file line number Diff line number Diff line change
Expand Up @@ -890,5 +890,6 @@
"889": "Unknown \\`cacheLife()\\` profile \"%s\" is not configured in next.config.js\\nmodule.exports = {\n cacheLife: {\n \"%s\": ...\\n }\n}",
"890": "Received an underlying cookies object that does not match either `cookies` or `mutableCookies`",
"891": "Failed to read build paths file \"%s\": %s",
"892": "Failed to resolve glob pattern \"%s\": %s"
"892": "Failed to resolve glob pattern \"%s\": %s",
"893": "The \"sassOptions.functions\" option is not supported when using Turbopack. Custom Sass functions are only available with webpack. Please remove the \"functions\" property from your sassOptions in %s."
}
13 changes: 13 additions & 0 deletions packages/next/src/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,19 @@ function assignDefaultsAndValidate(
)
}

// Validate sassOptions.functions is not used with Turbopack
if (
process.env.TURBOPACK &&
result.sassOptions &&
'functions' in result.sassOptions
) {
throw new Error(
`The "sassOptions.functions" option is not supported when using Turbopack. ` +
`Custom Sass functions are only available with webpack. ` +
`Please remove the "functions" property from your sassOptions in ${configFileName}.`
)
}

if (isStableBuild()) {
// Prevents usage of certain experimental features outside of canary
if (result.experimental?.turbopackFileSystemCacheForBuild) {
Expand Down
54 changes: 54 additions & 0 deletions test/unit/isolated/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,60 @@ describe('config', () => {
)
})

it('Should throw an error when sassOptions.functions is used with Turbopack', async () => {
const originalTurbopack = process.env.TURBOPACK
process.env.TURBOPACK = '1'

try {
await expect(async () => {
// Use a unique directory to avoid cache conflicts
await loadConfig(PHASE_DEVELOPMENT_SERVER, '<rootDir>-turbopack-test', {
customConfig: {
sassOptions: {
functions: {
'get($keys)': function (keys) {
return 'test'
},
},
},
},
})
}).rejects.toThrow(
/The "sassOptions\.functions" option is not supported when using Turbopack/
)
} finally {
if (originalTurbopack === undefined) {
delete process.env.TURBOPACK
} else {
process.env.TURBOPACK = originalTurbopack
}
}
})

it('Should allow sassOptions.functions when not using Turbopack', async () => {
const originalTurbopack = process.env.TURBOPACK
delete process.env.TURBOPACK

try {
const config = await loadConfig(PHASE_DEVELOPMENT_SERVER, '<rootDir>', {
customConfig: {
sassOptions: {
functions: {
'get($keys)': function (keys) {
return 'test'
},
},
},
},
})
expect((config as any).sassOptions.functions).toBeDefined()
} finally {
if (originalTurbopack !== undefined) {
process.env.TURBOPACK = originalTurbopack
}
}
})

it('Should not throw an error when two versions of next.config.js are present', async () => {
const config = await loadConfig(
PHASE_DEVELOPMENT_SERVER,
Expand Down
Loading