Skip to content

[backport] feat(turbopack): add LocalPathOrProjectPath PostCSS config resolution#94284

Merged
lukesandberg merged 1 commit into
next-16-2from
backport-91338-to-next-16-2
May 31, 2026
Merged

[backport] feat(turbopack): add LocalPathOrProjectPath PostCSS config resolution#94284
lukesandberg merged 1 commit into
next-16-2from
backport-91338-to-next-16-2

Conversation

@lukesandberg

Copy link
Copy Markdown
Contributor

…#91338)

Adds a new `experimental.turbopackLocalPostcssConfig` option and
corresponding `PostCssConfigLocation::LocalPathOrProjectPath` variant so
Turbopack can resolve `postcss.config.js` starting from the CSS file's
directory first, falling back to the project root.

Also fixes an issue that surfaces when multiple per-directory
`postcss.config.js` files are used:

**Evaluate pool asset name collisions** — output file names for the
Node.js evaluate pool are now derived from an xxh3 hash of the full
module ident rather than the bare file name, so multiple
`postcss.config.js` files in different directories no longer collide.

Currently Turbopack uses `ProjectPathOrLocalPath` which checks the
project root first, then falls back to the local directory. This means
per-directory `postcss.config.js` files cannot override the root config
— the root config always wins. For projects that need different PostCSS
transforms in different directories (e.g. a monorepo with multiple apps
or style directories), the more specific config should take precedence.

**Turbopack PostCSS resolution**
(`turbopack/crates/turbopack-node/src/transforms/postcss.rs`):
- Added `PostCssConfigLocation::LocalPathOrProjectPath` enum variant
with doc comments on all variants
- Refactored `find_config_in_location()` to express the search order as
a `Vec<FileSystemPath>` built from a single `match`, making each
variant's strategy immediately clear

**Evaluate pool asset file naming**
(`turbopack/crates/turbopack-node/src/evaluate.rs`):
- Replaced file-name-based output path derivation with a deterministic
xxh3 hash of the full module ident
- Adds `turbo-tasks-hash` dependency to `turbopack-node`
- Eliminates name collisions when multiple entries share the same file
name (e.g. per-directory `postcss.config.js` files)

**Next.js config flag** (`packages/next/src/server/config-shared.ts`,
`config-schema.ts`):
- Added `experimental.turbopackLocalPostcssConfig: boolean` option
(opt-in, default `false`)
- Wired through `crates/next-core/src/next_config.rs` → both client and
server contexts (`next_client/context.rs`, `next_server/context.rs`)
- When `true`, uses `LocalPathOrProjectPath`; when `false`/unset, uses
the existing `ProjectPathOrLocalPath` (no behavior change by default)

**E2E test** (`test/e2e/app-dir/turbopack-postcss-multiple-configs/`):
- Runs in both **Turbopack dev and production modes** — skips webpack
only (webpack does not support function-valued PostCSS plugins and the
`turbopackLocalPostcssConfig` flag is Turbopack-specific)
- 5 style directories, each with its own `postcss.config.js` passing a
**unique color option** (`blue`, `purple`, `orange`, `cyan`, `magenta`)
to a shared PostCSS plugin, proving that per-directory config resolution
produces distinct results rather than all sharing the same transform
- Root `postcss.config.js` is a no-op — if only the root config were
used, CSS would remain unmodified
- Test validates all 15 elements (5 dirs × 3 files) render with CSS
module classes
- Test collects all CSS (inline `<style>` tags for dev, linked `.css`
files for production) and asserts each directory's expected color is
present and `color: red` is absent

**Documentation**
(`docs/01-app/03-api-reference/05-config/01-next-config-js/turbopackLocalPostcssConfig.mdx`,
`docs/01-app/03-api-reference/08-turbopack.mdx`):
- New dedicated reference page for
`experimental.turbopackLocalPostcssConfig` covering usage, behavior
table, and a directory-tree example
- Added to the experimental options table in the Turbopack API reference

- [x] `cargo check -p turbo-tasks-backend` passes
- [x] `cargo check -p turbopack-node` and `cargo check -p next-core`
pass
- [x] E2E test `turbopack-postcss-multiple-configs` validates
per-directory PostCSS config resolution across 5 directories with
distinct per-directory colors (Turbopack dev and production modes)
- [x] Test correctly skips in webpack mode and deployment
- [x] Documentation page and experimental options table updated

<!-- NEXT_JS_LLM_PR -->

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Tobias Koppers <sokra@users.noreply.github.com>
(cherry picked from commit 74cdcde)
@github-actions

github-actions Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor

Stats skipped

Commit: c0ec542
View workflow run

@github-actions

github-actions Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor

Tests Passed

Commit: c0ec542

@lukesandberg lukesandberg marked this pull request as ready for review May 31, 2026 17:16
@lukesandberg lukesandberg requested review from bgw and sokra May 31, 2026 17:23

lukesandberg commented May 31, 2026

Copy link
Copy Markdown
Contributor Author

Merge activity

  • May 31, 6:12 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • May 31, 6:12 PM UTC: @lukesandberg merged this pull request with Graphite.

@lukesandberg lukesandberg merged commit c63224f into next-16-2 May 31, 2026
137 of 140 checks passed
@lukesandberg lukesandberg deleted the backport-91338-to-next-16-2 branch May 31, 2026 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants