swc-project/swc
Rust-based platform for the Web
Compiles and transforms JavaScript/TypeScript/HTML/CSS code using native Rust parsers
Source code flows through a multi-stage pipeline: JavaScript APIs receive code and configuration, serialize them across native binding boundaries to Rust, where parsers convert text to AST, transformers modify the AST based on configuration, and code generators output transformed code back through the binding to JavaScript callers.
Under the hood, the system uses 1 feedback loop, 2 data pools, 2 control points to manage its runtime behavior.
A 8-component fullstack. 45054 files analyzed. Data flows through 6 distinct pipeline stages.
How Data Flows Through the System
Source code flows through a multi-stage pipeline: JavaScript APIs receive code and configuration, serialize them across native binding boundaries to Rust, where parsers convert text to AST, transformers modify the AST based on configuration, and code generators output transformed code back through the binding to JavaScript callers.
- Accept source code and configuration — JavaScript APIs in packages/core, packages/html, packages/minifier receive source code strings and configuration objects from users, validating input types and setting defaults
- Serialize across binding boundary — JavaScript configuration is JSON-stringified into Buffer objects and passed to native bindings (Node.js NAPI or WASM), where it gets deserialized back into Rust structs
- Parse source into AST — Rust parsers in swc_ecma_parser or swc_html_parser convert source text into structured AST representations (Program enum for JS/TS, Document for HTML), detecting syntax type from file extensions
- Apply transformations — Various transformer crates modify the AST based on configuration - swc_ecma_transforms for language features, swc_ecma_compat for browser compatibility, swc_html_minifier for HTML optimization [Program → Program]
- Generate optimized code — Code generators in swc_ecma_codegen and swc_html_codegen traverse the transformed AST to produce output source code, optionally generating source maps for debugging [Program → TransformOutput]
- Return to JavaScript — Native bindings serialize the TransformOutput back to JavaScript, where it's returned as objects with code and map properties to the original API caller [TransformOutput]
Data Models
The data structures that flow between stages — the contracts that hold the system together.
bindings/binding_core_node/src/lib.rsstruct with code: String (transformed source), map: Option<String> (source map)
Created by Rust compilation engine, serialized across binding boundary, returned to JavaScript callers
packages/types/index.tsTypeScript interface with compress?: TerserCompressOptions | boolean, format?: JsFormatOptions, mangle?: TerserMangleOptions | boolean, ecma?: TerserEcmaVersion, various boolean flags
Defined by user in JavaScript, validated and passed to Rust minifier through binding serialization
packages/html/index.tsTypeScript interface with filename?: string, collapseWhitespaces?: enum, removeComments?: boolean, minifyJs/Css/Json?: boolean | detailed config objects, various boolean flags for HTML-specific optimizations
Created by user, serialized to Buffer via JSON.stringify, deserialized in Rust binding for HTML processing
crates/swc_ecma_astRust enum with Program::Module(Module) | Program::Script(Script) representing parsed AST
Created by parser from source text, passed through transformation pipeline, consumed by code generator
bindings/binding_html_node/src/lib.rsstruct with tagName: String, namespace: String, attributes: Vec<Attribute>, isSelfClosing: boolean
Extracted from HTML AST during parsing, used for configuration of HTML processing behavior
Hidden Assumptions
Things this code relies on but never validates. These are the things that cause silent failures when the system changes.
All Options properties are JSON-serializable, but complex callback functions or circular references could be passed in minifyJs.parser, minifyCss.parser, or custom minifier configurations
If this fails: JSON.stringify() will throw TypeError or silently drop properties, causing configurations to be lost when crossing the binding boundary to Rust
packages/html/index.ts:toBuffer
System has readable /usr/bin/ldd file for musl detection, but this file may not exist on minimal containers or non-standard Linux distributions
If this fails: Returns null causing fallback to other detection methods, potentially loading wrong native binary (glibc vs musl) and crashing with 'cannot open shared object file' errors
packages/html/binding.js:isMuslFromFilesystem
Global singleton SourceMap can grow indefinitely as compilation sessions accumulate file mappings, but never implements cleanup or size limits
If this fails: Memory usage grows unbounded in long-running processes, eventually causing OOM crashes in Node.js applications that perform many compilation operations
bindings/binding_core_node/src/lib.rs:COMPILER
Buffer.from(JSON.stringify(options)) creates UTF-8 encoded buffer that Rust deserializer expects, but JSON.stringify can produce invalid UTF-8 sequences with surrogate pairs
If this fails: Rust deserialization fails with invalid UTF-8 errors, causing API calls to throw unexpected exceptions instead of validation errors
packages/html/index.ts:minify
Code string and options string are reasonable sizes for memory allocation, but no checks exist for multi-GB inputs
If this fails: Large HTML documents or complex configurations cause native bindings to allocate excessive memory, potentially triggering OOM killer or hanging the process
bindings/binding_html_node/src/lib.rs:MinifyTask
Process.platform and process.arch correctly identify the runtime platform, but these can be spoofed or unavailable in non-Node.js environments
If this fails: Loads wrong native binary for the actual platform, causing 'dynamic library not found' or architecture mismatch crashes at runtime
packages/html/binding.js:requireNative
File extension determines syntax mode (.tsx = TypeScript JSX, .mjs = ES module), but content might not match extension (TypeScript in .js file)
If this fails: Parser uses wrong syntax rules, either failing to parse valid TypeScript or misinterpreting JavaScript as TypeScript, producing incorrect ASTs
bindings/binding_es_ast_viewer/src/lib.rs:parse
Shared COMPILER instance can be safely used across concurrent transform operations, but internal state like SourceMap accumulates data from all operations
If this fails: Concurrent operations may see file mappings or diagnostics from other operations, causing debugging information to leak between unrelated compilations
bindings/binding_core_node/src/lib.rs:get_compiler
Regex string in extractComments.regex is valid JavaScript RegExp pattern, but no validation exists before passing to Rust
If this fails: Invalid regex patterns cause Rust regex compilation to panic, terminating the Node.js process instead of returning a validation error
packages/types/index.ts:JsMinifyOptions.extractComments
Input code parameter accepts string | Buffer, but Buffer.from(code) assumes string encoding is UTF-8 when code is a string
If this fails: Non-UTF-8 strings get incorrectly encoded, causing Rust parser to receive malformed text and either fail parsing or produce wrong output
packages/minifier/src/index.ts:minify
System Behavior
How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.
Data Pools
Shared global SourceMap instance that accumulates file mappings across compilation sessions for debugging
Runtime detection and loading of platform-specific native binaries based on OS/architecture combinations
Feedback Loops
- Binary Loading Fallback (retry, balancing) — Trigger: Native binary load failure. Action: Try alternative binary paths and package names for the same platform. Exit: Successfully loaded binary or exhausted all alternatives.
Delays
- Native Binary Loading (compilation, ~100-500ms) — First API call per process incurs binary loading overhead
Control Points
- SWC_DEBUG (env-var) — Controls: Enables panic backtraces and debug output in native bindings. Default: 1
- Platform Detection (runtime-toggle) — Controls: Which native binary gets loaded based on process.platform and process.arch
Technology Stack
Core parsing, transformation, and code generation engine providing memory safety and performance
Creates Node.js native addons from Rust code, handling JavaScript ↔ Rust data serialization
Enables browser-based compilation by compiling Rust to WebAssembly
Provides type-safe JavaScript APIs and configuration interfaces for end users
Manages the monorepo structure and inter-package dependencies across 70+ packages
Handles CSS parsing and minification when CSS processing is enabled in HTML minifier
Key Components
- COMPILER (factory) — Global singleton that creates and manages the SWC Rust compiler instance with shared SourceMap
bindings/binding_core_node/src/lib.rs - Parser (processor) — Converts JavaScript/TypeScript source code into AST representations, handling different syntax modes (ES, TS, JSX)
crates/swc_ecma_parser - Transformer (transformer) — Applies various code transformations (ES6→ES5, TypeScript→JavaScript, JSX→JS) to AST nodes
crates/swc_ecma_transforms - CodeGenerator (encoder) — Converts transformed AST back into JavaScript source code with optional source maps
crates/swc_ecma_codegen - Minifier (optimizer) — Optimizes JavaScript code for size by removing dead code, renaming variables, and applying compression
crates/swc_ecma_minifier - HtmlMinifier (optimizer) — Optimizes HTML documents by removing whitespace, minifying embedded CSS/JS, and collapsing attributes
bindings/binding_html_node/src/lib.rs - BindingTaskRunner (executor) — Manages async task execution for Node.js bindings, converting between JavaScript Promises and Rust futures
bindings/binding_core_node/src/lib.rs - PlatformDetector (adapter) — Detects runtime platform (OS, architecture, libc variant) and loads appropriate native binary
packages/html/binding.js
Package Structure
Main JavaScript API for SWC compilation and transformation features
Runtime helper functions for transformed code (e.g., class inheritance, async generators)
HTML parsing and minification capabilities
JavaScript minification functionality
React-specific compilation features
TypeScript definitions for SWC APIs and configuration options
Native Node.js binding that exposes Rust compilation engine to JavaScript
WASM binding for browser-based compilation
WASM-based AST visualization tool for JavaScript/TypeScript code
Node.js binding for HTML parsing and minification
WASM binding for HTML processing in browsers
Command-line interface for SWC compilation
Explore the interactive analysis
See the full architecture map, data flow, and code patterns visualization.
Analyze on CodeSeaRelated Fullstack Repositories
Frequently Asked Questions
What is swc used for?
Compiles and transforms JavaScript/TypeScript/HTML/CSS code using native Rust parsers swc-project/swc is a 8-component fullstack written in Rust. Data flows through 6 distinct pipeline stages. The codebase contains 45054 files.
How is swc architected?
swc is organized into 4 architecture layers: Core Rust Engine, Native Bindings, JavaScript API Layer, Distribution Packages. Data flows through 6 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.
How does data flow through swc?
Data moves through 6 stages: Accept source code and configuration → Serialize across binding boundary → Parse source into AST → Apply transformations → Generate optimized code → .... Source code flows through a multi-stage pipeline: JavaScript APIs receive code and configuration, serialize them across native binding boundaries to Rust, where parsers convert text to AST, transformers modify the AST based on configuration, and code generators output transformed code back through the binding to JavaScript callers. This pipeline design reflects a complex multi-stage processing system.
What technologies does swc use?
The core stack includes Rust (Core parsing, transformation, and code generation engine providing memory safety and performance), NAPI-RS (Creates Node.js native addons from Rust code, handling JavaScript ↔ Rust data serialization), WASM (Enables browser-based compilation by compiling Rust to WebAssembly), TypeScript (Provides type-safe JavaScript APIs and configuration interfaces for end users), Yarn Workspaces (Manages the monorepo structure and inter-package dependencies across 70+ packages), lightningcss (Handles CSS parsing and minification when CSS processing is enabled in HTML minifier). A focused set of dependencies that keeps the build manageable.
What system dynamics does swc have?
swc exhibits 2 data pools (SourceMap, Platform Binary Cache), 1 feedback loop, 2 control points, 1 delay. The feedback loops handle retry. These runtime behaviors shape how the system responds to load, failures, and configuration changes.
What design patterns does swc use?
4 design patterns detected: Native Binding Bridge, Platform-Specific Distribution, AST Visitor Pattern, Lazy Singleton Factory.
Analyzed on April 20, 2026 by CodeSea. Written by Karolina Sarna.