Native addon carriers

September 13, 2026 · View on GitHub

@swc/core, @swc/html, @swc/minifier, and @swc/react-compiler ship a single self-loading, zstd-compressed .node file on the targets below. The existing package names, native filenames, optional platform dependencies, JavaScript loaders, exports, and Node engine declarations remain unchanged. Standalone swc executables and WASM packages are not compressed by this step.

SystemCarriersExisting raw addons
macOSx86_64-apple-darwin, aarch64-apple-darwin
Windowsx86_64-pc-windows-msvc, aarch64-pc-windows-msvci686-pc-windows-msvc
Linux GNUx86_64-unknown-linux-gnu, aarch64-unknown-linux-gnuarmv7-unknown-linux-gnueabihf, powerpc64le-unknown-linux-gnu, s390x-unknown-linux-gnu
Linux muslx86_64-unknown-linux-musl, aarch64-unknown-linux-musl

First load and cache

The native carrier decodes the original stripped addon, verifies its length, native image format, and SHA-512 digest, and forwards native registration to that verified image. Materialized bytes are identical to the stripped build input. Corrupt payloads and materialization failures produce actionable ERR_SWC_NATIVE_* errors.

The default cache is isolated by user and addressed by the raw image's SHA-512. It uses the existing private loader's user-cache root: an absolute XDG_CACHE_HOME when available on Unix, otherwise the user's cache directory (~/Library/Caches on macOS or ~/.cache on Linux), and LOCALAPPDATA/swc on Windows. Files live under swc-native-<effective UID or user SID>/v1/. Cache hits are verified before loading. Unique staging files, locks, and atomic replacement prevent concurrent first loads from observing partially written images. Corrupt regular cache entries are repaired from the verified payload.

SWC_NATIVE_BINDING_CACHE is the only carrier runtime control:

ValueBehavior
Unset or emptyUse the default user cache and eligible filesystem replacement.
0Materialize a unique temporary image; never replace the installed carrier. Unix unlinks it after loading; Windows retains a delete-on-close handle until process teardown.
Absolute directoryUse this cache root, falling back to the default user cache if unusable.
Other relative valueThrow a configuration error.

Failure of both a custom root and the default root throws. An executable cache filesystem is required; a Linux noexec cache is rejected. Existing cache namespaces retain at most three inactive-or-current raw images.

On writable APFS or btrfs, the loader may atomically replace its installed carrier with the original addon under transparent filesystem compression. The current process loads a separate verified temporary image. Read-only, hardlinked, unsupported, or unsuitable installations use the cache. Windows keeps the carrier DLL in place and requests NTFS compression on decoded cache files. The sibling CLI is never part of materialization or replacement.

Release verification

The existing raw napi-rs build finishes first, including its final strip steps. The finalizer packs that exact input at zstd level 16, builds a carrier in a temporary location, finishes carrier strip/signing, and verifies the completed native image. Only then does a same-filesystem atomic operation replace the selected addon. Failure or a carrier at least as large as the raw input fails the build. Excluded addons stay on their existing raw path.

Reports are separate CI artifacts, never npm compression sidecars. Each record binds the release version, build type, source commit, product, target, native filename, raw SHA-512, final SHA-512, and any existing CLI hashes.

One shared release gate requires all 48 artifacts: 32 valid carriers and 16 unchanged raw addons. It revalidates the exact npm tarball contents after assembly and prepack, requires each carrier to be smaller, and requires sum(carrier bytes) <= sum(selected raw bytes) / 2. Missing runtime checks, missing reports, duplicate targets, hash mismatches, and raw substitutions stop publication. Publishing consumes those exact verified tarballs with lifecycle scripts disabled. Verification-only runs never publish.

The job summary and JSON artifacts report raw size, compressed frame size, payload size (including its 96-byte header), carrier size, reduction ratio, npm tarball size, and load timings. Timings are medians of 15 fresh Node processes per case, measured around package loading. Cold means an empty materialization cache; warm means an already populated verified cache. These are not claims about an empty operating-system page cache. Disposable hardlinked carrier copies prevent filesystem self-replacement from disguising warm-cache costs. Representative x64 jobs require at most 100 ms cold overhead and 25 ms warm overhead over the corresponding raw addon.

Node 20/22 checks exercise every selected target through product tests and installed tarball resolution. Standalone smoke scripts also exercise Linux GNU x64 at core's Node 10.0.0 boundary, HTML/minifier's issue-requested 14.0.0 boundary, minifier's declared 12.0.0 boundary, and React Compiler's 20.0.0 boundary. Tooling uses modern Node independently of those test subprocesses. Actual native file loading is checked so another addon or WASM fallback cannot hide a carrier failure. Native APFS, btrfs, and Windows lifecycle checks are required before release activation; a cross-target Rust check alone is not native execution evidence.

Local checks

Initialize submodules before validation:

git submodule update --init --recursive
node --test scripts/native/*.test.mjs
cargo test -p swc_native_addon -p swc_native_addon_pack -p binding_native_addon
python3 crates/swc_native_addon/scripts/msrv.py
cargo fmt --all
cargo clippy --all --all-targets -- -D warnings

Build and test each affected native product through its package scripts, and run (cd packages/core && pnpm build:dev && pnpm test). The private implementation guide lists the explicit filesystem tests and minimum-Node fixture command. Report unavailable commands with their actual missing host, filesystem, tool, or credential reason. Npm minor changesets and synchronized versioning are managed externally.

See the integration verification record for observed local measurements, failed acceptance checks, and unavailable hosts.