vercel/next.js
next-swc
Purpose
@next/swc is the package that distributes the native binaries consumed by packages/next. It contains no real source code — it is a thin wrapper that downloads or builds the napi-rs binding produced from crates/next-napi-bindings. The Rust implementation of every SWC transform that Next.js applies (JSX import source, server actions, dynamic IO, next/font preloading, etc.) lives in crates/next-custom-transforms and is exposed through this package.
Source: packages/next-swc/. Backing crates: crates/next-napi-bindings/, crates/next-custom-transforms/, crates/wasm/.
Directory layout
packages/next-swc/
├── package.json
└── native/ # Built or downloaded .node binariesThe directory deliberately holds only the platform-specific binaries. The full binding API surface is generated from Rust by napi-rs.
How the binary gets there
Two paths produce packages/next-swc/native/*.node:
graph TD
Install[pnpm install] --> Postinstall[scripts/install-native.mjs]
Postinstall --> Has{Local node_modules<br/>has @next/swc?}
Has -- yes --> Skip[skip]
Has -- no --> Fetch[fetch published binary<br/>from npm]
Build[pnpm swc-build-native] --> Cargo[cargo build --release<br/>-p next-napi-bindings]
Cargo --> Move[scripts/build-native.ts<br/>moves .node into native/]The scripts/install-native.mjs postinstall script picks the platform-correct binary from npm. For local development on transforms, pnpm swc-build-native rebuilds from source. After switching branches, delete packages/next-swc/native/*.node and re-install to pick up the npm-published binary again — a stale local build is a common cause of unexplained Turbopack errors.
Consumers
packages/next/src/build/swc/ loads the native binding. Two consumption modes:
- Direct napi — Node.js callers via
next-napi-bindings(the default). - WASM fallback —
crates/wasm/produces a wasm-bindgen build for environments where the native binary cannot run (notably some serverless edges and StackBlitz).
Custom transforms
The actual transforms live at crates/next-custom-transforms/. Examples:
next/fontresolution and preload injection- Server actions (
'use server'directive plumbing) - Dynamic IO instrumentation
import.meta.urlrewrites for static analysis- Page extensions normalization
Each transform is implemented as an SWC visitor pass and registered in the per-runtime config produced by crates/next-core/.
Targets
The published @next/swc package ships native binaries for these platforms (driven by scripts/publish-native.js and the release-next-rspack.yml and per-platform GitHub Actions workflows):
darwin-arm64,darwin-x64linux-x64-gnu,linux-x64-musl,linux-arm64-gnu,linux-arm64-muslwin32-arm64-msvc,win32-x64-msvcwasm(viacrates/wasm)
Each platform has its own scoped npm package (@next/swc-darwin-arm64, etc.) that the user installs as an optional dependency through Next.js's optional-dependencies block.
Key source files
| File | Purpose |
|---|---|
packages/next-swc/package.json |
Manifest pointing at platform-specific subpkgs |
crates/next-napi-bindings/src/lib.rs |
napi-rs bindings (the entry the binary exposes) |
crates/next-custom-transforms/src/lib.rs |
Visitor registration |
crates/wasm/src/lib.rs |
wasm-bindgen wrapper |
scripts/install-native.mjs |
Postinstall binary picker |
scripts/build-native.ts |
Build script invoked by pnpm swc-build-native |
scripts/publish-native.js |
Per-platform publish |
Related crates
The Rust side is documented under crates/:
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.