## What?
This PR reapplies #87746 which adds bundling support for Node.js `worker_threads` in Turbopack.
## Why?
The original PR (#87746) was reverted in #88725 because it broke builds that use packages like `pino` with transports. These packages use dynamic patterns like `join(__dirname, 'lib', 'worker.js')` to resolve worker entry points, which can match non-evaluatable files like `package.json` or `tsconfig.json`.
## How?
This PR reapplies the original changes with the following fixes:
1. **Downgrade errors to warnings in tracing contexts**: When `loose_errors` is enabled (tracing mode) or `in_try` is true, worker entry point validation errors are now emitted as warnings instead of errors. This follows the established Turbopack pattern used in `handle_resolve_error` and other resolve error handling.
2. **Improved error messages**: Error messages for non-chunkable and non-evaluatable worker entry point modules now include:
- The module identifier (so you can see which file caused the issue)
- The issue source location (pointing to the `new Worker()` call in source code)
3. **Added regression test**: A new pino-based test case exercises the `thread-stream` worker pattern that caused the original failure. This test runs in `CodeGenerationAndTracing` mode via `test-start-turbo`.
## Changes from original PR
- Added `source` field to `CodeGenerationIssue` to support showing issue source locations
- Added `get_issue_severity()` helper that checks `loose_errors` and `in_try` to determine severity
- Fixed typo: `"SharedbWorker"` → `"SharedWorker"` in `to_string` implementation
- Added pino regression test in `test/e2e/app-dir/node-worker-threads/`
## Testing
- ✅ `pnpm test-dev-turbo test/e2e/app-dir/node-worker-threads/` - all tests pass
- ✅ `pnpm test-start-turbo test/e2e/app-dir/node-worker-threads/` - all tests pass (exercises bundling mode)
- ✅ Verified test fails without the `loose_errors` fix
- ✅ Verified vercel-docs build succeeds with warnings instead of errors
## What?
Fixes a bug where `react-loadable-manifest.json` in Turbopack dev mode
contained references to chunk files with wrong hashes, causing 404
errors when loading dynamic imports.
## Why?
When using `next/dynamic` with nested imports (e.g., a dynamic component
that itself imports other modules), the chunk files referenced in
`react-loadable-manifest.json` had different hashes than the actual
generated chunk files.
The root cause was that `collect_next_dynamic_chunks` was
**recomputing** chunk content that was already computed by
`make_chunk_group`. This pattern was inherently brittle because Next.js
code had to carefully mirror Turbopack's internal chunking logic to get
consistent hashes.
This brittleness was exposed when the
`turbopackClientSideNestedAsyncChunking` feature was disabled in dev
mode (released in 16.1). The subtle differences in how availability info
was computed led to hash mismatches.
## How?
Instead of recomputing chunks for next/dynamic imports, this PR
preserves the module→async loader mapping from when chunks are first
computed in `make_chunk_group`, and looks up pre-computed chunks
directly. This eliminates the need for Next.js to replicate Turbopack's
chunking logic.
### Key changes:
1. **Extended `MakeChunkGroupResult` and `ChunkGroupResult`** with
`async_loaders_by_module` field
- Maps `ResolvedVc<Box<dyn ChunkableModule>>` → `ResolvedVc<Box<dyn
ChunkItem>>`
- Preserves the module→loader relationship computed during chunking
2. **Eliminated redundancy** in `MakeChunkGroupResult`
- Removed the separate `references` field (was just upcasted async
loaders)
- Added `references()` method that derives references on-demand from the
map
3. **Simplified `collect_next_dynamic_chunks`**
- Now performs simple lookup instead of recomputation
- Removed `module_graph` and `chunking_context` parameters
- Uses `NextDynamicChunkAvailability` enum to access pre-computed chunk
groups
4. **Added regression test** to verify chunk files referenced in
manifest exist
### Files modified:
- `turbopack/crates/turbopack-core/src/chunk/chunk_group.rs` - Add
mapping, remove redundant field
- `turbopack/crates/turbopack-core/src/chunk/chunking_context.rs` -
Extend ChunkGroupResult
- `turbopack/crates/turbopack-browser/src/chunking_context.rs` - Pass
through mapping
- `turbopack/crates/turbopack-nodejs/src/chunking_context.rs` - Pass
through mapping
- `crates/next-api/src/dynamic_imports.rs` - Lookup instead of recompute
- `crates/next-api/src/pages.rs` - Updated caller
- `crates/next-api/src/app.rs` - Updated caller
- `crates/next-core/src/next_app/app_client_references_chunks.rs` -
Initialize empty map
Fixes#87680
<!-- 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
### 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?
Add `useEffectEvent` to the list of invalid React APIs in Server
Components.
### Why?
Using `useEffectEvent` in a Server Component results in a **runtime
error**: TypeError: (0 , react_1.useEffectEvent) is not a function.
Without this fix, developers only discover the mistake at runtime. This
change improves the **Developer Experience (DX) by catching the error
immediately in the IDE.**
#### Expected Behavior
<img width="999" height="566" alt="image"
src="https://github.com/user-attachments/assets/79c1cbf9-ae0e-4ad7-b163-f650fb289a3a"
/>
#### Currently
<img width="1708" height="805" alt="image"
src="https://github.com/user-attachments/assets/a33f73e5-24fd-4405-826a-53f1810154a7"
/>
<img width="2091" height="812" alt="image"
src="https://github.com/user-attachments/assets/ed3f191e-a34d-42dd-8779-1d524f6f035d"
/>
### How?
- Added `useEffectEvent` to Rust RSC transform
(`react_server_components.rs`)
- Added `useEffectEvent` to TypeScript constants (`constant.ts`)
- Added `useEffectEvent` to error formatting (`format-server-error.ts`)
- Added test fixture and updated test file
## Note
This is a reapply of the previous
[PR](https://github.com/vercel/next.js/pull/88950).
With help from @timneutkens, I all previously worked code to ensure
nothing was missed before resubmitting.
Co-authored-by: Tim Neutkens <tim@timneutkens.nl>
## What?
This PR fixes font preloading for MDX pages in Turbopack and adds an e2e
test to verify the fix.
## Why?
When using `next/font` with MDX pages, font preloading was failing with
Turbopack because the LoaderTree was storing the **transformed module
path** instead of the **original source path**.
## The Bug
In Turbopack, MDX files are transformed by adding a `.tsx` extension:
- Source file: `app/page.mdx`
- After transform: `app/page.mdx.tsx`
The `create_module_tuple_code` function in `base_loader_tree.rs` was
using `module.ident().path()` (the transformed path) instead of the
original `path` parameter.
This caused a mismatch at runtime:
- Font manifest key: `[project]/app/page`
- LoaderTree stored: `[project]/app/page.mdx.tsx`
- After stripping `.tsx`: `[project]/app/page.mdx`
- **No match** → fonts not preloaded
## The Fix
Changed `crates/next-core/src/base_loader_tree.rs` to use the original
source path:
```rust
// Before
let module_path = module.ident().path().to_string().await?;
// After
let module_path = path.value_to_string().await?;
```
Now the LoaderTree stores `[project]/app/page.mdx`, which after
stripping `.mdx` at runtime becomes `[project]/app/page`, matching the
font manifest key.
## Test
Added `test/e2e/app-dir/mdx-font-preload/` which verifies:
1. MDX page renders correctly
2. Font class from layout is applied
3. Font is correctly preloaded
## How I tested these changes
```bash
pnpm test-start-turbo test/e2e/app-dir/mdx-font-preload/mdx-font-preload.test.ts
```
---------
Co-authored-by: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com>
This change adds infrastructure for a planned client-side optimization
where the router can infer route structure from previously prefetched
routes, avoiding redundant route tree requests.
When the client prefetches /blog/post-1 and learns the route structure
is /blog/[slug], it could potentially reuse that knowledge for
/blog/post-2 without another server roundtrip. However, if a static
route like /blog/featured exists at the same level, the client needs to
know NOT to apply the dynamic template for that URL.
staticSiblings provides this information. When a dynamic segment like
[slug] has static siblings (e.g., "featured", "archive"), the server
includes them in the prefetch response. The client can then check
whether an incoming URL matches a known static sibling, and if so,
recognize that the previously learned route structure does not apply.
Closes PACK-6539
When `experimental.runtimeServerDeploymentId` is enabled, read the `process.env.NEXT_DEPLOYMENT_ID` and append to the chunks when evaluating the `client-reference-manifest.js`
Originally, I tried to do it after the manifest is loaded (in `loadComponents` or in the `RouteModule.prepare`) to "hydrate" the manifest, but that is too late because the manifest needs to be initialized immediately to make module-evaluation-time server actions work (which need the manifest immediately)
## Summary
This adds a new experimental router method `experimental_gesturePush`
that enables gesture-driven navigation. The feature is gated behind a
new `experimental.gestureTransition` config flag, which implicitly opts
the app into using the experimental React build.
It is _not_ suitable for production use yet; it's a proof-of-concept so
we can test the integration between the Next.js client router and
React's Gesture Transitions experiment. You can use it to build demos,
but it shouldn't be used in a real app.
It dispatches updates through React's useOptimistic hook instead of the
main router state queue, essentially forking the router state until the
gesture completes.
This should only be called inside `startGestureTransition`. It's a
low-level method that is not meant to be used in application code, only
in libraries that know how to properly integrate with both Next and
React.
## Test Plan
- E2E test that simulates a gesture by holding an async transition open
between button clicks
- Run: `pnpm testonly test/e2e/app-dir/gesture-transitions`
Add support for the `--debug-build-paths` flag in Turbopack builds. Previously this flag only affected which routes were prerendered (statically generated), but the bundler still compiled all routes.
Now routes are filtered early in `Project::entrypoints()`, so excluded routes are never compiled by Turbopack. Framework routes like `/_not-found` and `/_error` are always included to ensure the runtime works correctly.
This significantly reduces build times in large apps when building individual routes for debugging purposes. It also allows us to exclude building incompatible paths in end-to-end tests depending on whether `__NEXT_CACHE_COMPONENTS` is defined or not (see upstack PR).
Reverts vercel/next.js#87746
because of this build error:
```
> Build error occurred
Error: Turbopack build failed with 1 errors:
./node_modules/.pnpm/thread-stream@3.1.0/node_modules/thread-stream/index.js
non-evaluatable module
Worker thread module must be evaluatable
```
Add support for bundling worker_threads workers
Previously we only supported tracing dependencies of worker threads. However, this could trigger issues if the callsite was getting bundled since we would believe that the file was both bundled and unbundled.
The solution is to support bundling modules using worker threads and implementing the threads. This requires a new reference and loader module type which follows the patter of async-loaders and webworkers.
An interesting consideration is about file extensions. `new Worker(...)` takes a relative or absolute filepath, in node 23+ that means you can load typescript files directly, so we support the same. If you want to load a `.ts` file you need to write `foo.ts` we don't do any pattern rewriting.
This fixes a bug reported by an X user: https://x.com/strugglercss/status/2002504736860484008?s=20. The problem with the previous approach is that we would record the reference as 'traced', but if you did `new Worker(__filename,...)` then we would end up with 'traced references' to a file that was bundled. This caused issues during tracing when we tried to add CachedExternalModule references to the nft json files
```
Error [TurbopackInternalError]: NftJsonAsset: cannot handle filepath url
Debug info:
- Execution of get_all_written_entrypoints_with_issues_operation failed
- Execution of EntrypointsOperation::new failed
- Execution of all_entrypoints_write_to_disk_operation failed
- Execution of Project::emit_all_output_assets failed
- Execution of emit_assets failed
- Execution of emit failed
- Execution of <NftJsonAsset as Asset>::content failed
- NftJsonAsset: cannot handle filepath url
at <unknown> (TurbopackInternalError: NftJsonAsset: cannot handle filepath url) {
```
there `url` was due to a `require('url')` statement in a bundled file this caused us to produce an external shim, but a `new Worker(__filename)` caused us to also create a traced reference to the same file. The problem there was simply that the `ident()` for a `CachedExternalModule` contains a dummy filepath that broke the nft.json asset production. The root issue here is that the `FilePathModuleReference` was using the wrong `AssetContext` to construct the referenced module which lead to the wrong files being traced. After investigation @mischnic and I determined that that was an insufficient fix since we really do need to rewrite the reference. Proper bundling support fixes this directly and the pattern here paves the way for more worker support in the future.
This doesn't seem like the only way a synthetic module (like an extern module) might end up as a dependency of traced module, so a more robust solution is probably in order.
Update the bug report link to use the new bugs.nextjs.org service
instead of the direct GitHub discussions URL. Also shares more code when
handling terminals that don't support links.
Test Plan: Added a deliberate panic to a turbotask, verified the link.
### What?
Part of PACK-1007
Adds `condition.query` support to Turbopack's loader rules, enabling loaders to match based on import query strings (e.g., `import './file?raw'`). This mirrors webpack's `resourceQuery` functionality.
The `query` condition accepts either a string (exact match) or RegExp (pattern match).
Adds tests and documentation for the new `condition.query` option.
### How to use
```js
// next.config.js
module.exports = {
turbopack: {
rules: {
'*.txt': [
// String: exact match
{ condition: { query: '?raw' }, loaders: ['raw-loader'], as: '*.js' },
// RegExp: pattern match
{ condition: { query: /\?transform/ }, loaders: ['transform-loader'], as: '*.js' },
],
},
},
}
```
### What?
Refactor ModuleGraph to be a strongly consistent snapshot of the module graph. This should avoid eventually consistency problems where different versions of single module graphs do not fit together.
# Optimize issue filtering in Next.js and Turbopack
## What?
This PR introduces an `IssueFilter` system to control which issues are reported based on severity and location
## Why?
To improve performance, we shouldn't spend time formatting issues that will never be displayed to a user.
## How?
- Added `IssueFilter` to control which issues are displayed based on severity and location
- Created a specialized `InNodeModules` context condition for better readability
- Implemented `warnings_and_foreign_errors()` filter that shows:
- Warnings and errors from application code
- Only errors from node_modules
- Applied the filter throughout Next.js and Turbopack's issue reporting system
- Refactored issue collection to filter early rather than collecting everything first
### What?
Replaces `is_reference_used` with `unused_references` and uses the new keyed invalidation. This avoid having a `is_reference_used` for each reference in the application
I added this as an option in https://github.com/vercel/next.js/pull/81818 as a solution for users with corporate firewalls that MITM TLS traffic.
Reqwest 0.13.x now uses `rustls-platform-verifier` by default, which doesn't have the tradeoffs that `rustls-native-certs` had. We should now pick up and work with system certs by default, and we no longer depend on shipping our own blob of trusted PKI roots! (though wasmer still pulls this in...)
This PR was generated with Opus + OpenCode, but there was a ton of manual iteration to get it working on CI.
### TLS Provider
`reqwest` now defaults to `aws-lc-rs` instead of `ring`. This causes a few problems:
- On Windows, this requires cmake and NASM. There's a prebuilt NASM blob we can use, but it still appears to need cmake. We could install this in CI, but I don't want to make Windows development any more complicated than it already is.
- On Linux, there are issues with it picking up the wrong glibc version in our CI: https://github.com/aws/aws-lc-rs/issues/673
We just use this for fetching Google Fonts, so it's not worth it: Fall back to using `ring` on these platforms.
### CI Testing
Manually triggered a build-and-release job so that it tries to build for the whole platform matrix: https://github.com/vercel/next.js/actions/runs/20936098900
### Manual Testing
Followed the test plan in https://github.com/vercel/next.js/pull/81818

Before:
```
Module not found: Can't resolve 'next/dist/esm/build/templates/helpers'
failed to analyze ecmascript module '[project]/node_modules/.pnpm/next@file+..+next-repo-2bf56e024dbccc85257a8c308492f2375d690b206153b02d3bea2029707d4c38+packa_tacnzof7rtmb5bwqa7bdnfcdbq/node_modules/next/dist/esm/build/templates/helpers.js [ssr] (ecmascript)'
Caused by:
- failed to parse [project]/node_modules/.pnpm/next@file+..+next-repo-2bf56e024dbccc85257a8c308492f2375d690b206153b02d3bea2029707d4c38+packa_tacnzof7rtmb5bwqa7bdnfcdbq/node_modules/next/dist/esm/build/templates/helpers.js
- Transforming and/or parsing of [project]/node_modules/.pnpm/next@file+..+next-repo-2bf56e024dbccc85257a8c308492f2375d690b206153b02d3bea2029707d4c38+packa_tacnzof7rtmb5bwqa7bdnfcdbq/node_modules/next/dist/esm/build/templates/helpers.js failed
- failed to deserialize `swc_common::plugin::diagnostics::PluginCorePkgDiagnostics`
- Mismatch { name: "array", found: 48 }
Debug info:
- Execution of <ModuleAssetContext as AssetContext>::process_resolve_result failed
- Execution of <ModuleAssetContext as AssetContext>::process failed
- Execution of <EcmascriptModuleAsset as Module>::side_effects failed
- Execution of analyze_ecmascript_module failed
- failed to analyze ecmascript module '[project]/node_modules/.pnpm/next@file+..+next-repo-2bf56e024dbccc85257a8c308492f2375d690b206153b02d3bea2029707d4c38+packa_tacnzof7rtmb5bwqa7bdnfcdbq/node_modules/next/dist/esm/build/templates/helpers.js [ssr] (ecmascript)'
- Execution of <EcmascriptModuleAsset as EcmascriptParsable>::failsafe_parse failed
- Execution of parse failed
- failed to parse [project]/node_modules/.pnpm/next@file+..+next-repo-2bf56e024dbccc85257a8c308492f2375d690b206153b02d3bea2029707d4c38+packa_tacnzof7rtmb5bwqa7bdnfcdbq/node_modules/next/dist/esm/build/templates/helpers.js
- Transforming and/or parsing of [project]/node_modules/.pnpm/next@file+..+next-repo-2bf56e024dbccc85257a8c308492f2375d690b206153b02d3bea2029707d4c38+packa_tacnzof7rtmb5bwqa7bdnfcdbq/node_modules/next/dist/esm/build/templates/helpers.js failed
- failed to deserialize `swc_common::plugin::diagnostics::PluginCorePkgDiagnostics`
- Mismatch { name: "array", found: 48 }
Import map: aliased to module 'next' with subpath '/dist/esm/build/templates/helpers' inside of [project]/
https://nextjs.org/docs/messages/module-not-found
```
After:
```
./packages/next/document.js
Failed to execute SWC plugin
An unexpected error occurred when executing an SWC EcmaScript transform plugin.
This might be due to a version mismatch between the plugin and Next.js.
Failed to execute @swc/plugin-react-remove-properties
Caused by:
0: failed to deserialize `swc_common::plugin::diagnostics::PluginCorePkgDiagnostics`
1: Mismatch { name: "array", found: 48 }
```
This PR refactors the Resolution Plugin traits to add new `Always` or
`Never` enum variants to `resolve condition`. This allow plugins (like
[ExternalsPlugin](https://github.com/utooland/utoo/pull/2494) when no
externals are configured) to skip the expensive `matches()` task calls
entirely. Testing on a medium project showed a reduction of ~1.4k
`resolve_call` tasks. I think this can be shared to upstream for future
improvement of `resolve plugin`
See the metrics for improvements.
<img width="1400" height="600" alt="image"
src="https://github.com/user-attachments/assets/06eae96e-070a-43c3-9f68-a3a27ee7dc0d"
/>
---------
Co-authored-by: Niklas Mischkulnig <4586894+mischnic@users.noreply.github.com>
The transform output for 'use cache' uses `Object.defineProperty` and
`Array.prototype.slice`. In theory, it's possible for a module to shadow
those names and break it:
```ts
// i want to suffer!
const Array = {}
const Object = {}
async function cached() {
"use cache"
...
}
```
We should defensively make sure that our transform's output refers to
the actual Object/Array builtins, not whatever's in scope for that name.
We can do this by using an unresolved syntax context for the
identifiers. This is what we do for `require()` elsewhere:
https://github.com/vercel/next.js/blob/6805af48baf1128e6b2a9e8f1752ee5982f02c60/crates/next-custom-transforms/src/transforms/track_dynamic_imports.rs#L119-L122
Using `quote_ident!(unresolved_ctxt, "Array")` will cause SWC to rename
any local redefinitions of `Array` to something that doesn't clash
(which can be seen in the added snapshots).
## What?
Improves the error shown when `generateMetadata` or `metadata` is
exported from a Client Component.
Also updated the documentation to further explain why it can only be
used in a server component and the steps to follow to resolve the error.
Using `taint` APIs from React without enabling `experimental.taint` will
error at runtime because it needs to bundle experimental React, making
it hard to catch and potentially leading to downtime. This updates our
transform to throw an error if we detect that it's imported but `taint`
isn't enabled.
Fixes NAR-690
### What?
Usually we persist the database every 2 minutes inside of `next build`, so you can continue from a partial build.
But in CI that doesn't make sense, so this changes it to only persist on shutdown.
### What?
Simplifies the graph traversal.
Allows the GraphStore to store edges and nodes.
This no longer forces us to abuse the node type to store edge info, which actually has lead to a race condition problem which made the module graph non-deterministic.
Removes `skip_duplicated` and made the AdjacencyMap always skip duplicates. That simplifies the implementation. We never not skipped duplicates and that rarely makes sense anyway since any cycle would make it traverse forever...
Also removed a bunch of unused stuff...
* remove `traverse_edges_from_entry_dfs` it is dead
* rename a number of traversal methods to shorter names. mostly by dropping `from_entries` which i don't believe is useful.
* rename `travserve_edges_from_entries_dfs_reversed` to `traverse_edges_reverse_dfs` which is a bit better, but could probably still use some work.
I explored ways to share logic across our DFS implementations and ultimately determined that the juice wasn't worth the squeeze
I grepped for `Serialize` and `Deserialize`, and (because it's hard to automate this) went through everything by hand to try to remove as many unused trait implementations as possible.
Refactor the `is_marked_side_effect_free` API
* Rename `side_effects`
* Change it to return `ModuleSideEffects` instead of a `bool`
* Remove the `side_effect_packages` from its parameters, instead arrange to pass that to the EcmascriptModule constructor since that is where we need it.
- This cleans up callsites and fixes a tiny issue where we construct that glob multiple times.
Removing the automatic `serde` derives from `#[turbo_tasks::value]` should remove most of the macro expansion. I'll follow up with removing all the manual derives.
This also removes `Serialize` from `NextConfig`, leaving only `Deserialize`. The `Serialization` derive is no longer needed after some of @mischnic's fixes to edge templates.
Because this is trivially-eliminated dead code, there should be no user-facing benefit from removing this code, but there should be some improvements to our own workflows.
## Build Time: `cargo build -p next-swc-napi`
This gives a ~2% improvement to cold cargo build times with the debug profile.
```
$ hyperfine -w 1 -r 10 -p 'git co 3bb0bcbf82 && cargo clean' -p 'git co bgw/rm-value-serde && cargo clean' 'cargo build -p next-swc-napi' 'cargo build -p next-swc-napi'
Benchmark 1: cargo build -p next-swc-napi
Time (mean ± σ): 226.424 s ± 2.819 s [User: 1943.869 s, System: 85.058 s]
Range (min … max): 222.736 s … 232.369 s 10 runs
Benchmark 2: cargo build -p next-swc-napi
Time (mean ± σ): 220.957 s ± 6.535 s [User: 1940.188 s, System: 87.074 s]
Range (min … max): 213.891 s … 231.464 s 10 runs
Summary
cargo build -p next-swc-napi ran
1.02 ± 0.03 times faster than cargo build -p next-swc-napi
```
This is in addition to the ~2% improvement observed in https://github.com/vercel/next.js/pull/86631
**Percentage improvements to incremental build times are likely greater than shown here**, as cold builds include all of our dependencies, which are not touched by this PR.
Implements a minimal custom serde `Serializer` and `Deserializer` on top of bincode with a custom self-describing format. The API is exposed as functions that can be used in `#[bincode(with = "...")]` attributes.
This doesn't encode as efficiently as `pot`, but it lets us get rid of that dependency entirely. It also gives us a more efficient option than `serde_json` for certain values.