### What?
Remove one allocation per `transform()` and `minify()`.
### Why?
We don't need to allocate `Compiler` in an `Arc`, because we don't share it.
### What?
Use `swc_atoms::Atom` instead of `String` in `next-swc`.
### Why?
`Atom` does not allocate if another instance has the same value, meaning that `clone()` is a single atomic operation. But `String` allocates regardless of any other occurrence.
### What?
Use `swc_atoms::Atom` instead of `String` in `next-swc`.
### Why?
`Atom` does not allocate if another instance has the same value, meaning that `clone()` is a single atomic operation. But `String` allocates regardless of any other occurrence.
### What?
Use `swc_atoms::Atom` instead of `String` in `next-swc`.
### Why?
`Atom` does not allocate if another instance has the same value, meaning that `clone()` is a single atomic operation. But `String` allocates regardless of any other occurrence.
### What?
Use `swc_atoms::Atom` instead of `String` in `next-swc`.
### Why?
`Atom` does not allocate if another instance has the same value, meaning that `clone()` is a single atomic operation. But `String` allocates regardless of any other occurrence.
### What?
Use `swc_atoms::Atom` instead of `String` in `next-swc`.
### Why?
`Atom` does not allocate if another instance has the same value, meaning that `clone()` is a single atomic operation. But `String` allocates regardless of any other occurrence.
Use the final `__turbopack_context_.X` directly, which saves use the long destructuring.
The original versions (`__turbopack_load__`, `__turbopack_import__`) are still available as the user-facing API (implemented via free var replacements).
src-rolldown-1000 before:
```
input_len 6.776151mb
output_len 1.318701mb
```
src-rolldown-1000 after:
```
input_len 2.879056mb
output_len 1.147727mb
```
```
canary (0f7251fc78):
without sourcemaps:
15,3
506.01s user 104.05s system 780% cpu 1:18.21 total
500.73s user 105.54s system 767% cpu 1:18.98 total
with sourcemaps:
23,3gb
542.87s user 119.60s system 752% cpu 1:28.06 total
537.84s user 117.53s system 799% cpu 1:22.02 total
```
```
after (e09b2a5517):
without sourcemaps:
14,65gb
503.89s user 102.31s system 770% cpu 1:18.63 total
493.39s user 100.04s system 768% cpu 1:17.18 total
494.93s user 101.16s system 769% cpu 1:17.44 total
with sourcemaps:
22,7
529.38s user 115.85s system 785% cpu 1:22.09 total
522.39s user 115.70s system 781% cpu 1:21.66 total
```
Migrate as many things as possible that I could find with:
```
rg '\b(Index|Hash)(Map|Set)<'
```
# Benchmarks
I tried building next-site, differences are likely within noise threshold.
## Before this change
```
$ hyperfine --warmup 1 --runs 5 --prepare 'rm -rf .next' 'TURBOPACK=1 TURBOPACK_BUILD=1 TURBO_ENGINE_READ_ONLY=1 pnpm next build --experimental-build-mode=compile'
Benchmark 1: TURBOPACK=1 TURBOPACK_BUILD=1 TURBO_ENGINE_READ_ONLY=1 pnpm next build --experimental-build-mode=compile
Time (mean ± σ): 27.254 s ± 0.268 s [User: 125.055 s, System: 16.090 s]
Range (min … max): 26.810 s … 27.529 s 5 runs
```
## After this change
```
$ hyperfine --warmup 1 --runs 5 --prepare 'rm -rf .next' 'TURBOPACK=1 TURBOPACK_BUILD=1 TURBO_ENGINE_READ_ONLY=1 pnpm next build --experimental-build-mode=compile'
Benchmark 1: TURBOPACK=1 TURBOPACK_BUILD=1 TURBO_ENGINE_READ_ONLY=1 pnpm next build --experimental-build-mode=compile
Time (mean ± σ): 26.711 s ± 0.461 s [User: 123.910 s, System: 15.667 s]
Range (min … max): 26.346 s … 27.463 s 5 runs
```
This is a follow-up to https://github.com/vercel/next.js/pull/75007
`DashMap` is needed for situations where you have many threads (or tokio tasks) modifying the same data at the same time. It introduces a lot of memory and CPU overhead to create individually lockable `RwLock` shards. This type of data structure implements `Sync`, indicating that it can be shared between threads.
`Rc` is not `Sync` (`Arc` is `Sync`), so wrapping `DashMap` in `Rc` doesn't make a lot of sense: You're paying a pretty high overhead for the ability to share data between threads, and wrapping it in something that does not support sharing data between threads.
This visitor code is entirely single-threaded, so just use `Rc<RefCell<FxHashMap>>` instead. `RefCell` is a very cheap single-threaded version of a `Mutex`. `FxHashMap` is just a `HashMap` with the faster `FxHash` algorithm used.
> Replace hash with faster and better finalized hash. This replaces the previous "fxhash" algorithm originating in Firefox with a custom hasher designed and implemented by Orson Peters (orlp). It was measured to have slightly better performance for rustc, has better theoretical properties and also includes a significantly better string hasher.
https://github.com/rust-lang/rustc-hash/blob/master/CHANGELOG.md
# Benchmarks
Any perf difference either way is too small to be easily measured. Benchmarks here technically show a tiny regression, but that's well within the run-to-run variance I've observed.
## rustc-hash 1.1.0
```
$ hyperfine --warmup 1 --runs 5 --prepare 'rm -rf .next' 'TURBOPACK=1 TURBOPACK_BUILD=1 TURBO_ENGINE_READ_ONLY=1 pnpm next build --experimental-build-mode=compile'
Benchmark 1: TURBOPACK=1 TURBOPACK_BUILD=1 TURBO_ENGINE_READ_ONLY=1 pnpm next build --experimental-build-mode=compile
Time (mean ± σ): 26.736 s ± 0.294 s [User: 122.811 s, System: 15.908 s]
Range (min … max): 26.340 s … 27.165 s 5 runs
```
## rustc-hash 2.1.0
```
$ hyperfine --warmup 1 --runs 5 --prepare 'rm -rf .next' 'TURBOPACK=1 TURBOPACK_BUILD=1 TURBO_ENGINE_READ_ONLY=1 pnpm next build --experimental-build-mode=compile'
Benchmark 1: TURBOPACK=1 TURBOPACK_BUILD=1 TURBO_ENGINE_READ_ONLY=1 pnpm next build --experimental-build-mode=compile
Time (mean ± σ): 27.206 s ± 0.540 s [User: 126.145 s, System: 15.958 s]
Range (min … max): 26.543 s … 27.894 s 5 runs
```
The fxhash crate hasn't been updated in 7 years, the rust-hash crate is actively maintained.
We were using an awkward mix of both, unify on just using rustc-hash.
This is a follow-up to https://github.com/vercel/next.js/pull/75055.
After #75055, the async methods are just facades around the synchronous versions, to avoid breaking the API.
I made this PR using:
```
sg run -p 'ResolvedVc::try_sidecast::<$$$TY>($$$ARGS).await?' -r 'ResolvedVc::try_sidecast_sync::<$$$TY>($$$ARGS)' -U
sg run -p 'ResolvedVc::try_sidecast($$$ARGS).await?' -r 'ResolvedVc::try_sidecast_sync($$$ARGS)' -U
sg run -p 'ResolvedVc::try_downcast::<$$$TY>($$$ARGS).await?' -r 'ResolvedVc::try_downcast_sync::<$$$TY>($$$ARGS)' -U
sg run -p 'ResolvedVc::try_downcast($$$ARGS).await?' -r 'ResolvedVc::try_downcast_sync($$$ARGS)' -U
sg run -p 'ResolvedVc::try_downcast_type::<$$$TY>($$$ARGS).await?' -r 'ResolvedVc::try_downcast_type_sync::<$$$TY>($$$ARGS)' -U
sg run -p 'ResolvedVc::try_downcast_type($$$ARGS).await?' -r 'ResolvedVc::try_downcast_type_sync($$$ARGS)' -U
```
Delete the implementation of the non-sync methods, and then:
```
sg run -p 'ResolvedVc::try_sidecast_sync' -r 'ResolvedVc::try_sidecast' -U
sg run -p 'ResolvedVc::try_downcast_sync' -r 'ResolvedVc::try_downcast' -U
sg run -p 'ResolvedVc::try_downcast_type_sync' -r 'ResolvedVc::try_downcast_type' -U
```
Then rename the methods implementations in `resolved.rs` to match.
### What?
Use `swc_atoms::Atom` instead of `String` in `next-swc`.
### Why?
`Atom` does not allocate if another instance has the same value, meaning that `clone()` is a single atomic operation. But `String` allocates regardless of any other occurrence.
This was available on the old memory backend, this ports it to the new backend, which is important now that it's the default.
Plus, the code's cleaner now that the trait resolution hack I had was cleaned up in #75214!
## What?
Ensures we don't inject React refresh helpers in production:
```
'object' == typeof globalThis.$RefreshHelpers$ &&
null !== globalThis.$RefreshHelpers &&
p.registerExports(v, globalThis.$RefreshHelpers$);
```
Also skips trying to resolve the `react-refresh` package.
<!-- Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that
you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:
## For Contributors
### Improving Documentation
- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR.
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide
### Adding or Updating Examples
- The "examples guidelines" are followed from our contributing doc
https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md
- Make sure the linting passes by running `pnpm build && pnpm lint`. See
https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md
### Fixing a bug
- Related issues linked using `fixes #number`
- Tests added. See:
https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md
### Adding a feature
- Implements an existing feature request or RFC. Make sure the feature
request has been accepted for implementation before opening a PR. (A
discussion must be opened, see
https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added
(https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md
## For Maintainers
- Minimal description (aim for explaining to someone not on the team to
understand the PR)
- When linking to a Slack thread, you might want to share details of the
conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic
behind a change
### What?
### Why?
### How?
Closes NEXT-
Fixes #
-->
### What?
* pass rustflags to windows too
* disable lifo slot to make all tasks stealable
### Why?
Since we do a lot of CPU bound work in tokio tasks this can lead to future polling taking several seconds. With the lifo slot, one task is not stealable and need to wait for these several seconds to be executed. This delays that task and causes reduced parallelization of tasks.
The `"use cache"` directive is not compatible with the Edge runtime.
When the `experimental.useCache` flag is enabled, we now emit a build
error for pages with `export const runtime = 'edge'`. This is analogous
to using the `experimental.dynamicIO` flag.
The other route segment configs that are forbidden when `dynamicIO` is
enabled, are currently still allowed for `useCache`:
- `dynamicParams`
- `dynamic`
- `fetchCache`
- `revalidate`
The issues with the current export statement validation for app router
pages are documented in the added fixtures, see also the inline comments
in the diff.
**View diff without whitespace changes!**
This brings the number of `AssetIdent::path` calls down from 5M to 100k
```
### canary (de984c2695b):
~16,60GB
582.76s user 109.72s system 815% cpu 1:24.95 total
583.30s user 108.45s system 805% cpu 1:25.86 total
### plus mischnic/client-manifest-optimization:
still ~16,60GB
547.70s user 105.24s system 811% cpu 1:20.48 total
550.16s user 108.14s system 782% cpu 1:24.10 total
```
In the SWC transform we're now using the span of the original `"use cache"` function for the generated cache wrapper call, e.g. so that the captured timeout error stack can be source mapped correctly.
This also fixes the wrongly placed `/*#__TURBOPACK_DISABLE_EXPORT_MERGING__*/` marker for the generated
cache wrapper statements.
**Before:**
<img width="1496" alt="404215955-c354d1f5-4aeb-4f35-9385-a9531219dc4c" src="https://github.com/user-attachments/assets/34d1863a-d557-419f-8477-577bd759341b" />
**After:**
<img width="1496" alt="404215977-a0157fad-a1f8-409a-b9b9-9709e07f7c05" src="https://github.com/user-attachments/assets/f00b7776-6674-4714-b425-d0de994abbff" />
Closes NDX-675
This:
- Makes the Endpoint trait not manage any file writing on its own,
instead returning a structure containing OutputAssets, the paths where
the OutputAssets can be found, and the associated Project.
- Allows for OutputAssets to be written at a future point in Turbopack
- Implements `endpoint_write_to_disk` for compatibility in dev. This
continues to be used for prod builds, but in the future it won’t.
In a future PR, production builds will dedupe and unify all output
assets, writing them to disk at once, rather than exposing individual
endpoint writes to JS to occur sequentially.
Test Plan: CI
Same as we were already doing for `ResolvedVc::to_resolved`.
This function essentially just acts like a deref when called on `ResolvedVc`.
I'd eventually like to replace `Vc::resolve` with `Vc::to_resolved`. These are the easiest callsites to remove.
We’re updating the SWC transform to
[track](https://nextjs.org/telemetry) how the "use cache" directive is
used during builds. Each use of "use cache" is counted based on the
handler it’s linked to.
By default, "use cache" counts toward a feature called
"useCache/default". If a custom handler is defined in the Next.js config
(e.g., "custom"), then "use cache: custom" will count toward
"useCache/custom".
The build process will collect these counts and combine them across all
source files and workers. This data is reported under the
NEXT_BUILD_FEATURE_USAGE event, allowing us to filter by "useCache/*" to
see how often each cache handler is used.
*Only support webpack prod build for now.
Closes NDX-683