Relevant source files
The following files were used as context for generating this wiki page:
- packages/next/src/build/swc/index.ts
- packages/next/taskfile-swc.js
- packages/next/src/build/swc/options.ts
- packages/next/taskfile.js
- packages/next/src/build/webpack/loaders/next-swc-loader.ts
- packages/next/src/build/swc/generated-wasm.d.ts
- packages/next/src/build/swc/install-bindings.ts
- packages/next/src/cli/next-info.ts
- packages/next-mdx/mdx-rs-loader.js
- packages/next/src/build/webpack/loaders/lightningcss-loader/src/loader.ts
- packages/next/src/build/swc/jest-transformer.ts
- packages/next/src/build/next-config-ts/require-hook.ts
- packages/next/src/lib/download-swc.ts
- packages/next-swc/package.json
- packages/next-codemod/bin/transform.ts
- packages/next/src/build/next-config-ts/transpile-config.ts
- packages/next/src/build/swc/loaderWorkerPool.ts
- packages/next/src/server/dev/dev-validation-worker-pool.ts
- packages/next/src/build/babel/preset.ts
- packages/next/src/build/swc/generated-native.d.ts
- packages/next/src/build/swc/types.ts
- packages/next/src/build/webpack/loaders/next-app-loader/index.ts
Overview
The SWC compiler integration in Next.js serves as the high-performance native compilation and minification engine, replacing traditional JavaScript-based toolchains for parsing, transforming, and bundling application source code. Built around Rust-powered Node-API (NAPI-RS) bindings and WebAssembly fallbacks, the compiler subsystem powers core tasks including JavaScript and TypeScript transpilation, React JSX/TSX transformations, CSS processing via Lightning CSS, MDX compilation, and incremental building with Turbopack. By handling computationally intensive abstract syntax tree (AST) operations natively, it solves performance bottlenecks associated with large-scale JavaScript toolchains while maintaining seamless interoperability with Webpack loaders and testing environments.
Sources: packages/next/src/build/swc/index.ts:1307-1324, packages/next/src/build/webpack/loaders/next-swc-loader.ts:31-34, packages/next/src/build/swc/generated-native.d.ts:74-78
Binary Discovery and Loading Lifecycle
Architecture Target Resolution and Native Binding Loading
The SWC compiler initializes by attempting to load native Node-API bindings compiled for the host operating system and CPU architecture. The loader resolves environment-specific binaries through NAPI-RS packages (@next/swc-<triple>), querying the loaded binary's target metadata via getTargetTriple.
export declare function getTargetTriple(): stringSources: packages/next/src/build/swc/generated-native.d.ts:108-108
export function getBinaryMetadata() {
return {
target: loadedBindings?.getTargetTriple?.(),
}
}Sources: packages/next/src/build/swc/index.ts:1864-1868
WebAssembly Fallback Mechanics
When native Node-API bindings cannot be loaded or resolved, the loader falls back to WebAssembly implementations. The loading sequence checks for a local test directory via NEXT_TEST_WASM_DIR before iterating through production WebAssembly distribution packages.
async function loadWasmRawBindings(importPath = ''): Promise<RawWasmBindings> {
let attempts = []
// Used by `run-tests` to force use of a locally-built wasm binary. This environment variable is
// unstable and subject to change.
const testWasmDir = process.env.NEXT_TEST_WASM_DIR
if (testWasmDir) {
// assume these are node.js bindings and don't need a call to `.default()`
const rawBindings = await import(
pathToFileURL(path.join(testWasmDir, 'wasm.js')).toString()
)
infoLog(`next-swc build: wasm build ${testWasmDir}`)
return rawBindings
} else {
for (let pkg of ['@next/swc-wasm-nodejs', '@next/swc-wasm-web']) {Sources: packages/next/src/build/swc/index.ts:1328-1343
> [!NOTE]
> The WebAssembly initialization path distinguishes between Node.js and browser or web environments. When loading `@next/swc-wasm-web`, the loader explicitly invokes the exported `default()` initialization method to set up memory instances before binding execution.Sources: packages/next/src/build/swc/index.ts:1355-1361
The fallback mechanism records detailed failure diagnostics when modules are missing or encounter load errors, collecting failure attempts until a valid binding instance is established or all options are exhausted.
} catch (e: any) {
// Only log attempts for loading wasm when loading as fallback
if (importPath) {
if (e?.code === 'ERR_MODULE_NOT_FOUND') {
attempts.push(`Attempted to load ${pkg}, but it was not installed`)
} else {
attempts.push(
`Attempted to load ${pkg}, but an error occurred: ${e.message ?? e}`
)
}Sources: packages/next/src/build/swc/index.ts:1364-1373
Package Caching and Binary Download Management
If required packages are absent from local directories, the extraction subsystem downloads compressed distribution tarballs from the active registry into a designated cache directory (next-swc).
const cacheDirectory = getCacheDirectory(
'next-swc',
process.env['NEXT_SWC_PATH']
)
const extractFromTar = () =>
x({
file: path.join(cacheDirectory, tarFileName),
cwd: outputDirectory,
strip: 1,
})
if (!fs.existsSync(path.join(cacheDirectory, tarFileName))) {
Log.info(`Downloading swc package ${pkgName}... to ${cacheDirectory}`)
await fs.promises.mkdir(cacheDirectory, { recursive: true })
const tempFile = path.join(
cacheDirectory,
`${tarFileName}.temp-${Date.now()}`
)
const registry = getRegistry()
const downloadUrl = `${registry}${pkgName}/-/${tarFileName}`
await fetch(downloadUrl).then((res) => {Sources: packages/next/src/lib/download-swc.ts:17-41
| Download Function | Target Package Variant | Destination Directory Parameter |
|---|---|---|
downloadNativeNextSwc | @next/swc-${triple} | bindingsDirectory |
downloadWasmSwc | @next/swc-wasm-${variant} | wasmDirectory |
Sources: packages/next/src/lib/download-swc.ts:108-146
The cache manager restricts resource bloat by enforcing a strict retention ceiling, automatically pruning older version directories exceeding the configured storage limit.
const MAX_VERSIONS_TO_CACHE = 8Sources: packages/next/src/lib/download-swc.ts:10-10
const cacheFiles = await fs.promises.readdir(cacheDirectory)
if (cacheFiles.length > MAX_VERSIONS_TO_CACHE) {
cacheFiles.sort((a, b) => {
if (a.length < b.length) return -1
return a.localeCompare(b)
})
// prune oldest versions in cache
for (let i = 0; i++; i < cacheFiles.length - MAX_VERSIONS_TO_CACHE) {
await fs.promises
.unlink(path.join(cacheDirectory, cacheFiles[i]))
.catch(() => {})
}
}Sources: packages/next/src/lib/download-swc.ts:91-105
Synchronous Installation and On-Demand Fetching
Deferred Bundle Loading
The SWC installation workflow avoids eager loading of compiler modules by deferring package requirements. Loading the main index module transitively pulls in configuration dependencies that evaluate process.env.NODE_ENV at require time. By routing installation requests through an isolated installer script, the process guarantees environment variables are configured before React or bundler modules initialize.
/**
* This module provides a way to install SWC bindings without eagerly loading the entire swc/index module.
*
* The swc/index module can transitively load other modules (like webpack-config) that import React,
* and React's entry point checks process.env.NODE_ENV at require time to decide whether to load
* the development or production bundle. By deferring the require of swc/index until this function
* is called, we ensure NODE_ENV is set before React is loaded.
*/
/**
* Loads and caches the native bindings. This is idempotent and should be called early so bindings
* can be accessed synchronously later.
*
* @param useWasmBinary - Whether to use WASM bindings instead of native bindings
*/
export async function installBindings(
useWasmBinary: boolean = false
): Promise<void> {
// Lazy require to avoid loading swc/index (and transitively webpack-config/React)
// before NODE_ENV is set
const { loadBindings } = require('./index') as typeof import('./index')
await loadBindings(useWasmBinary)
}Sources: packages/next/src/build/swc/install-bindings.ts:1-23
Note
The installBindings helper is fully idempotent and caches native bindings internally so that subsequent synchronous compiler accesses complete without asynchronous overhead.
Sources: packages/next/src/build/swc/install-bindings.ts:11-18
On-Demand Binary Extraction and Pruning
When native bindings or WebAssembly packages are missing from local directories, the extraction subsystem streams tarball archives from the package registry into temporary cache locations before unpacking them.
if (!fs.existsSync(path.join(cacheDirectory, tarFileName))) {
Log.info(`Downloading swc package ${pkgName}... to ${cacheDirectory}`)
await fs.promises.mkdir(cacheDirectory, { recursive: true })
const tempFile = path.join(
cacheDirectory,
`${tarFileName}.temp-${Date.now()}`
)
const registry = getRegistry()
const downloadUrl = `${registry}${pkgName}/-/${tarFileName}`
await fetch(downloadUrl).then((res) => {
const { ok, body } = res
if (!ok || !body) {
Log.error(`Failed to download swc package from ${downloadUrl}`)
}
if (!ok) {
throw new Error(`request failed with status ${res.status}`)
}
if (!body) {
throw new Error('request failed with empty body')
}
const cacheWriteStream = fs.createWriteStream(tempFile)
return body.pipeTo(
new WritableStream({
write(chunk) {
return new Promise<void>((resolve, reject) =>
cacheWriteStream.write(chunk, (error) => {
if (error) {
reject(error)
return
}
resolve()
})
)
},
close() {
return new Promise<void>((resolve, reject) =>
cacheWriteStream.close((error) => {
if (error) {
reject(error)
return
}
resolve()
})
)
},
})
)
})
await fs.promises.access(tempFile) // ensure the temp file existed
await fs.promises.rename(tempFile, path.join(cacheDirectory, tarFileName))
} else {
Log.info(`Using cached swc package ${pkgName}...`)
}Sources: packages/next/src/lib/download-swc.ts:29-88
To prevent unbounded disk utilization in the cache directory, the manager evaluates cached version counts and prunes stale artifacts when entries exceed the retention threshold.
const cacheFiles = await fs.promises.readdir(cacheDirectory)
if (cacheFiles.length > MAX_VERSIONS_TO_CACHE) {
cacheFiles.sort((a, b) => {
if (a.length < b.length) return -1
return a.localeCompare(b)
})
// prune oldest versions in cache
for (let i = 0; i++; i < cacheFiles.length - MAX_VERSIONS_TO_CACHE) {
await fs.promises
.unlink(path.join(cacheDirectory, cacheFiles[i]))
.catch(() => {})
}
}Sources: packages/next/src/lib/download-swc.ts:91-105
Supported NAPI Targets
The build pipeline defines target triplets and architectures for native compilation and packaging within the NAPI configuration manifest.
| Target Architecture & OS Triple | Description |
|---|---|
x86_64-apple-darwin | 64-bit macOS (Intel) |
x86_64-pc-windows-msvc | 64-bit Windows (MSVC) |
x86_64-unknown-linux-gnu | 64-bit Linux (GLIBC) |
i686-pc-windows-msvc | 32-bit Windows (MSVC) |
aarch64-unknown-linux-gnu | ARM64 Linux (GLIBC) |
aarch64-apple-darwin | ARM64 macOS (Apple Silicon) |
x86_64-unknown-linux-musl | 64-bit Linux (MUSL) |
aarch64-unknown-linux-musl | ARM64 Linux (MUSL) |
aarch64-pc-windows-msvc | ARM64 Windows (MSVC) |
wasm32-wasip1-threads | WebAssembly WASIp1 with threads |
Sources: packages/next-swc/package.json:25-38
Compilation Options and Transform Normalization
Parser and Base Options Construction
SWC compiler options are assembled through getBaseSWCOptions, which inspects configuration files, compiler flags, and bundle layers to construct unified parser and transformation targets. The parser configuration automatically distinguishes between TypeScript and ECMAScript syntax based on file extensions while enabling dynamic imports and import attributes.
export function getParserOptions({ filename, jsConfig, ...rest }: any) {
const isTSFile = filename.endsWith('.ts')
const hasTsSyntax = isTypeScriptFile(filename)
const enableDecorators = Boolean(
jsConfig?.compilerOptions?.experimentalDecorators
)
return {
...rest,
syntax: hasTsSyntax ? 'typescript' : 'ecmascript',
dynamicImport: true,
decorators: enableDecorators,
// Exclude regular TypeScript files from React transformation to prevent e.g. generic parameters and angle-bracket type assertion from being interpreted as JSX tags.
[hasTsSyntax ? 'tsx' : 'jsx']: !isTSFile,
importAssertions: true,
}
}Sources: packages/next/src/build/swc/options.ts:39-54
Warning
Regular TypeScript files exclude React transformation inside the parser config to prevent generic parameters and angle-bracket type assertions from being misparsed as JSX tags. Sources: packages/next/src/build/swc/options.ts:50-51
React and Styling Transform Normalization
The transformation pipeline normalizes compiler settings for React, Emotion, and styled-components depending on whether code runs in server or client layers. When Emotion options are configured and the bundle does not target the React server layer, the import source defaults to @emotion/react.
react: {
importSource:
jsConfig?.compilerOptions?.jsxImportSource ??
(compilerOptions?.emotion && !isReactServerLayer
? '@emotion/react'
: 'react'),
runtime: 'automatic',
pragmaFrag: 'React.Fragment',
throwIfNamespace: true,
development: !!development,
useBuiltins: true,
refresh: !!hasReactRefresh,
},Sources: packages/next/src/build/swc/options.ts:153-165
CSS-in-JS transformations for Emotion and styled-components are omitted on the server layer when building Server Components, avoiding client-only integration overhead during server compilation.
// Disable css-in-js libs (without client-only integration) transform on server layer for server components
...(!isReactServerLayer && {
emotion: getEmotionOptions(compilerOptions?.emotion, development),
styledComponents: getStyledComponentsOptions(
compilerOptions?.styledComponents,
development
),
}),Sources: packages/next/src/build/swc/options.ts:215-222
Emotion label generation and auto-formatting options normalize user-provided configurations through explicit conditional branches.
| Emotion Config Property | Default / Behavior |
|---|---|
enabled | true when emotion options are present |
autoLabel | Determined by string value (dev-only, always, never) |
sourcemap | Enabled in development mode when source maps are requested |
importMap | Custom import mappings passed directly to the transform |
Sources: packages/next/src/build/swc/options.ts:291-312
Parallel Transformation and Worker Pools
Loader Worker Pool Scheduling
SWC bindings register a worker scheduler via runLoaderWorkerPool to spawn and manage individual Node.js worker threads for parallel AST processing. Each worker pool is keyed by a composite identifier combining the current working directory and filename.
function getPoolId(cwd: string, filename: string) {
return `${cwd}:${filename}`
}
export async function runLoaderWorkerPool(
bindings: typeof import('./generated-native'),
bindingPath: string
) {
bindings.registerWorkerScheduler(
(creation) => {
const {
options: { filename, cwd },
} = creation
const poolId = getPoolId(cwd, filename)
const worker = new Worker(/* turbopackIgnore: true*/ filename, {
workerData: {
bindingPath,
cwd,
},
})
// This will cause handing when run in jest worker, but not as a first level thread of nodejs thread
// worker.unref()
const workers =
loaderWorkers[poolId] || (loaderWorkers[poolId] = new Map())
workers.set(worker.threadId, worker)
},
(termination) => {
const {
options: { filename, cwd },
workerId,
} = termination
const poolId = getPoolId(cwd, filename)
const workers = loaderWorkers[poolId]
workers.get(workerId)?.terminate()
workers.delete(workerId)
}
)Sources: packages/next/src/build/swc/loaderWorkerPool.ts:5-47
Warning
Calling worker.unref() causes hanging when workers run inside a Jest environment; it remains commented out in the implementation to ensure proper lifecycle management under test runners.
Sources: packages/next/src/build/swc/loaderWorkerPool.ts:28-29
Development Validation Worker Pool
The development validation system maintains a dedicated worker pool instance via installDevValidationWorker to offload validation logic and isolate runtime module states from the main thread.
const worker = new Worker(workerPath, {
maxRetries: 0,
numWorkers: 1,
// Always worker-threads, regardless of `experimental.workerThreads`.
// Unlike the `'use cache'` probe (which follows the flag), validation has
// no reason to prefer a child process: it doesn't need process-level
// isolation (a worker thread already has its own V8 heap and module
// registry, so the reloaded route is isolated from the main thread), and
// threads let a superseded validation be aborted mid-run through a shared
// `SharedArrayBuffer`, which a separate process can't receive. Threads
// also carry the transported Flight bytes as typed arrays via structured
// clone, with no JSON round-trip to corrupt them.
enableWorkerThreads: true,
// Listing the method explicitly tells jest-worker to skip the discovery
// `require()` it would otherwise do in the parent process to enumerate
// the module's exports. This worker's top-level imports (`require-hook`,
// `node-environment`) run runtime setup meant only for the isolated
// worker thread, so they must not be evaluated in the parent.
exposedMethods: [
'runDevValidation',
'applyHmrUpdate',
'invalidateCaches',
],
forkOptions: {
env: {
...process.env,
NODE_OPTIONS: workerNodeOptions,
},
},
}) as Worker & ValidationPoolSources: packages/next/src/server/dev/dev-validation-worker-pool.ts:157-186
| Worker Configuration Property | Value / Behavior |
|---|---|
maxRetries | 0 |
numWorkers | 1 |
enableWorkerThreads | true |
exposedMethods | runDevValidation, applyHmrUpdate, invalidateCaches |
Sources: packages/next/src/server/dev/dev-validation-worker-pool.ts:158-179
Note
Thread-based validation uses a SharedArrayBuffer to mirror abort signals across thread boundaries, allowing an in-flight validation run to be canceled mid-run at its next depth boundary.
Sources: packages/next/src/server/dev/dev-validation-worker-pool.ts:234-243
Configuration and Jest Transpilation Hooks
TypeScript Configuration Transpilation
The configuration transpilation pipeline transforms TypeScript configuration files such as next.config.ts into executable CommonJS modules using SWC. The transpileConfig function coordinates loading the local tsconfig.json compiler options, configuring parser syntax, and falling back or executing through native bindings.
function resolveSWCOptions(
cwd: string,
compilerOptions: RelevantCompilerOptions
): SWCOptions {
return {
jsc: {
parser: {
syntax: 'typescript',
},
...(compilerOptions.paths ? { paths: compilerOptions.paths } : {}),
...(compilerOptions.baseUrl
? // Needs to be an absolute path.
{ baseUrl: path.resolve(cwd, compilerOptions.baseUrl) }
: compilerOptions.paths
? // If paths is given, baseUrl is required.
{ baseUrl: compilerOptions.pathsBasePath ?? cwd }
: {}),
},
module: {
type: 'commonjs',
},
isModule: 'unknown',
env: {
targets: {
// Setting the Node.js version can reduce unnecessary code generation.
node: process?.versions?.node ?? '20.19.0',
},
},
} satisfies SWCOptions
}Sources: packages/next/src/build/next-config-ts/transpile-config.ts:14-43
Note
If process.env.__NEXT_NODE_NATIVE_TS_LOADER_ENABLED is set to true, the pipeline checks Node.js built-in TypeScript strip or transform features before falling back to SWC-based transpilation.
Sources: packages/next/src/build/next-config-ts/transpile-config.ts:69-78
When compiling configuration code, handleCJS inspects the resulting source for require( expressions. If present, it activates registerHook to dynamically intercept subsequent module imports during execution.
// register require hook only if require exists
if (code.includes('require(')) {
registerHook(swcOptions)
hasRequire = true
}
Sources: packages/next/src/build/next-config-ts/transpile-config.ts:133-138
Require Hook Management
The require hook utility overrides Node.js extension handlers (.js, .ts, .cts, .mts, .cjs, .mjs) to synchronously transpile required files on the fly.
for (const ext of extensions) {
const oldHook = require.extensions[ext] ?? oldJSHook
require.extensions[ext] = function (mod: any, oldFilename) {
const _compile = mod._compile
mod._compile = function (code: string, filename: string) {
const swc = transformSync(code, swcOptions)
return _compile.call(this, swc.code, filename)
}
return oldHook(mod, oldFilename)
}
}Sources: packages/next/src/build/next-config-ts/require-hook.ts:30-42
| Extension | Hook Action |
|---|---|
.js | Falls back to oldJSHook; if ERR_REQUIRE_ESM occurs, reads file content and compiles via SWC. |
.ts, .cts, .mts, .cjs, .mjs | Overrides mod._compile to transform source text using transformSync before native compilation. |
Sources: packages/next/src/build/next-config-ts/require-hook.ts:6-42
Warning
SWC is loaded lazily via require('../swc') inside registerHook to prevent loading development React binaries before NODE_ENV is initialized.
Sources: packages/next/src/build/next-config-ts/require-hook.ts:10-12
Jest Transformation Hook
The Jest transformer integrates SWC into test suites by exposing a createTransformer factory that constructs synchronous transform options for each test file.
const createTransformer: TransformerCreator<
SyncTransformer<JestTransformerConfig>,
JestTransformerConfig
> = (inputOptions) => ({
process(src, filename, jestOptions) {
const jestConfig = getJestConfig(jestOptions)
const swcTransformOpts = getJestSWCOptions({
isServer:
jestConfig.testEnvironment === 'node' ||
jestConfig.testEnvironment.includes('jest-environment-node'),
filename,
configDir: inputOptions?.configDir,
jsConfig: inputOptions?.jsConfig,
resolvedBaseUrl: inputOptions?.resolvedBaseUrl,
pagesDir: inputOptions?.pagesDir,
serverComponents: inputOptions?.serverComponents,
modularizeImports: inputOptions?.modularizeImports,
swcPlugins: inputOptions?.swcPlugins,
compilerOptions: inputOptions?.compilerOptions,
imageConfig: inputOptions?.imageConfig,
serverReferenceHashSalt: '',
esm:
isSupportEsm &&
isEsm(Boolean(inputOptions?.isEsmProject), filename, jestConfig),
})
return transformSync(src, { ...swcTransformOpts, filename })
},
})Sources: packages/next/src/build/swc/jest-transformer.ts:82-111
The transformer evaluates the test environment and file extensions to determine ECMAScript module support before dispatching to transformSync.
function isEsm(
isEsmProject: boolean,
filename: string,
jestConfig: Config.ProjectConfig
): boolean {
return (
(/\.jsx?$/.test(filename) && isEsmProject) ||
jestConfig.extensionsToTreatAsEsm?.some((ext: any) =>
filename.endsWith(ext)
)
)
}Sources: packages/next/src/build/swc/jest-transformer.ts:69-80
Diagnostic Telemetry and Failure Recovery
Load Failure Events and WebAssembly Fallback Tracking
When native Node-API bindings fail to load, loadWasmRawBindings tracks each failure attempt across packages like @next/swc-wasm-nodejs and @next/swc-wasm-web. If a module is missing, it records ERR_MODULE_NOT_FOUND events or accumulates fallback error strings before raising the complete attempt list.
async function loadWasmRawBindings(importPath = ''): Promise<RawWasmBindings> {
let attempts = []
// Used by `run-tests` to force use of a locally-built wasm binary. This environment variable is
// unstable and subject to change.
const testWasmDir = process.env.NEXT_TEST_WASM_DIR
if (testWasmDir) {
// assume these are node.js bindings and don't need a call to `.default()`
const rawBindings = await import(
pathToFileURL(path.join(testWasmDir, 'wasm.js')).toString()
)
infoLog(`next-swc build: wasm build ${testWasmDir}`)
return rawBindings
} else {
for (let pkg of ['@next/swc-wasm-nodejs', '@next/swc-wasm-web']) {
try {
let pkgPath = pkg
if (importPath) {
// the import path must be exact when not in node_modules
pkgPath = path.join(importPath, pkg, 'wasm.js')
}
const importedRawBindings = await import(
pathToFileURL(pkgPath).toString()
)
let rawBindings
if (pkg === '@next/swc-wasm-web') {
// https://rustwasm.github.io/docs/wasm-bindgen/examples/without-a-bundler.html
// `default` must be called to initialize the module
rawBindings = await importedRawBindings.default!()
} else {
rawBindings = importedRawBindings
}
infoLog(`next-swc build: wasm build ${pkg}`)
return rawBindings
} catch (e: any) {
// Only log attempts for loading wasm when loading as fallback
if (importPath) {
if (e?.code === 'ERR_MODULE_NOT_FOUND') {
attempts.push(`Attempted to load ${pkg}, but it was not installed`)
} else {
attempts.push(
`Attempted to load ${pkg}, but an error occurred: ${e.message ?? e}`
)
}
}
}
}
}
throw attempts
}
// helper for tryLoadWasmWithFallback / loadBindings.
async function loadWasm(importPath = '') {
const rawBindings = await loadWasmRawBindings(importPath)
function removeUndefined(obj: any): any {
// serde-wasm-bindgen expect that `undefined` values map to `()` in rust, but we want to treat
// those fields as non-existent, so remove them before passing them to rust.
//
// The native (non-wasm) bindings use `JSON.stringify`, which strips undefined values.
if (typeof obj !== 'object' || obj === null) {
return obj
}
if (Array.isArray(obj)) {
return obj.map(removeUndefined)
}
const newObj: { [key: string]: any } = {}
for (const [k, v] of Object.entries(obj)) {
if (typeof v !== 'undefined') {
newObj[k] = removeUndefined(v)
}
}
return newObj
}
// Note wasm binary does not support async intefaces yet, all async
// interface coereces to sync interfaces.Sources: packages/next/src/build/swc/index.ts:1328-1414
Warning
When NEXT_TEST_WASM_DIR is set, raw bindings are loaded directly from the local test directory via file URLs without invoking an initialization function, whereas @next/swc-wasm-web requires a explicit call to .default() to initialize the module.
Sources: packages/next/src/build/swc/index.ts:1331-1361
Lockfile Management and Edge Runtime Diagnostics
The native binding layer exposes explicit methods for file locking and runtime analysis, including lockfileTryAcquire, lockfileTryAcquireSync, lockfileUnlock, and lockfileUnlockSync. Additionally, warnForEdgeRuntime analyzes source code to produce NapiSourceDiagnostic warnings for production and development targets.
rspack: {
getModuleNamedExports: function (
resourcePath: string
): Promise<string[]> {
return bindings.getModuleNamedExports(resourcePath)
},
warnForEdgeRuntime: function (
source: string,
isProduction: boolean
): Promise<NapiSourceDiagnostic[]> {
return bindings.warnForEdgeRuntime(source, isProduction)
},
},
expandNextJsTemplate(
content: Buffer,
templatePath: string,
nextPackageDirPath: string,
replacements: Record<`VAR_${string}`, string>,
injections: Record<string, string>,
imports: Record<string, string | null>
): string {
return bindings.expandNextJsTemplate(
content,
templatePath,
nextPackageDirPath,
replacements,
injections,
imports
)
},
lockfileTryAcquire(filePath: string, content?: string | null) {
return bindings.lockfileTryAcquire(filePath, content)
},
lockfileTryAcquireSync(filePath: string, content?: string | null) {
return bindings.lockfileTryAcquireSync(filePath, content)
},
lockfileUnlock(lockfile: Lockfile) {
return bindings.lockfileUnlock(lockfile)
},
lockfileUnlockSync(lockfile: Lockfile) {
return bindings.lockfileUnlockSync(lockfile)
},Sources: packages/next/src/build/swc/index.ts:1762-1803
| Binding Method | Parameter Types | Purpose |
|---|---|---|
lockfileTryAcquire | `filePath: string, content?: string | null` |
lockfileTryAcquireSync | `filePath: string, content?: string | null` |
lockfileUnlock | lockfile: Lockfile | Asynchronously releases an acquired lockfile reference. |
lockfileUnlockSync | lockfile: Lockfile | Synchronously releases an acquired lockfile reference. |
warnForEdgeRuntime | source: string, isProduction: boolean | Scans source code for unsupported features and returns an array of NapiSourceDiagnostic objects. |
Sources: packages/next/src/build/swc/index.ts:1768-1803, packages/next/src/build/swc/types.ts:103-109
Related
On This Page
OverviewBinary Discovery and Loading LifecycleArchitecture Target Resolution and Native Binding LoadingWebAssembly Fallback MechanicsPackage Caching and Binary Download ManagementSynchronous Installation and On-Demand FetchingDeferred Bundle LoadingOn-Demand Binary Extraction and PruningSupported NAPI TargetsCompilation Options and Transform NormalizationParser and Base Options ConstructionReact and Styling Transform NormalizationParallel Transformation and Worker PoolsLoader Worker Pool SchedulingDevelopment Validation Worker PoolConfiguration and Jest Transpilation HooksTypeScript Configuration TranspilationRequire Hook ManagementJest Transformation HookDiagnostic Telemetry and Failure RecoveryLoad Failure Events and WebAssembly Fallback TrackingLockfile Management and Edge Runtime DiagnosticsRelated