Rationale of Rspack Custom Binding
The reason why Rspack is so fast is that it's written in Rust and so as the Rspack's internal builtin plugins and builtin loaders.
For most of the time, We assume you've been using Rspack JavaScript API and writing Rspack JavaScript Plugins. And you might probably heard there're some overheads when using JavaScript API. The rumour is true! Rspack is mostly written in Rust and providing the adapting layer with JavaScript API requires a lot of hassle of passing values back and forth between Rust and JavaScript. This creates a lot of overheads and performance issues.
But have you ever wondered if there's a way to extend Rspack's functionality by writing native Rust code and not requiring to sacrifice the performance or if you're able to use the rich Rust APIs? And the answer is yes. This is where Rspack Custom Binding comes in.
To get started with Rspack Custom Binding, you need to know the surface level of how Rspack binding works.
How Rspack Binding Works
If you are using the @rspack/cli
or @rspack/core
and not knowing what a custom binding is, you are using Rspack binding. It's a simple architecture that allows you to extend Rspack's functionality by leveraging the Rspack JavaScript API. It's just the same as how you use the Webpack JavaScript API to extend Webpack.
Let's take a deep dive into the architecture. It contains 3 parts:
npm:@rspack/core
: The JavaScript API layer of Rspack. Written in JavaScript.npm:@rspack/binding
: The Node.js Addon of Rspack.crate:rspack_binding_api
: The N-API glue layer of Rspack. Written in Rust.
flowchart TD Core("npm:@rspack/core") style Core stroke-width:0px,color:#FFDE59,fill:#545454 Core --> Binding("npm:@rspack/binding") style Binding stroke-width:0px,color:#FFDE59,fill:#545454 Binding --> APIs("crate:rspack_binding_api") style APIs stroke-width:0px,color:#FFDE59,fill:#545454
crate:rspack_binding_api
The N-API glue layer of Rspack.
This layer contains a glue code that bridges the gap between N-API-compatible runtimes, which, most of the time, is Node.js and Rust Core crates.
npm:@rspack/binding
The Node.js Addon of Rspack.
This layer links crate:rspack_binding_api
and compiles it into a Node.js Addon (a *.node
file) with NAPI-RS. The functionalities that npm:@rspack/core
provides are mostly exposed by the Node.js Addon in npm:@rspack/binding
.
Note: Maybe you have checked out the code on npm and it does not contain the *.node
file. This is because the *.node
files are dispatched by the @rspack/binding-*
packages (e.g. @rspack/binding-darwin-arm64
) for different platforms. Don't worry about this at the moment. We will get into the details in the custom binding section.
npm:@rspack/core
The JavaScript API layer of Rspack.
The internal of npm:@rspack/core
is written in JavaScript. It bridges the gap between the Node.js Addon in npm:@rspack/binding
and Rspack JavaScript API.
npm:@rspack/cli
is a command line tool that uses npm:@rspack/core
to build your project.
How Rspack Custom Binding Works
Let's use the diagram below to understand how a custom binding works. It shows a "Before" state, representing the standard Rspack setup, and an "After" state, which illustrates the custom binding approach.
In the Before state, your project uses the default Rspack binding. This is created solely from crate:rspack_binding_api
, the core glue layer between Rust and Node.js.
In the After state, you introduce your own native code. As the diagram shows, your User Customizations (like custom Rust plugins) are combined with the original crate:rspack_binding_api
.
This combination produces a new, personalized Custom Binding. This becomes your project's new Node.js addon, allowing you to inject high-performance, custom logic directly into Rspack's build process.
Crucially, you can continue to use npm:@rspack/core
with your custom binding. This allows you to benefit from native performance and customization without rewriting the JavaScript API layer, reusing all the features it provides. We will cover how to integrate @rspack/core
with a custom binding in a later section.
flowchart LR subgraph Before ["_Before_"] Original("crate:rspack_binding_api") style Original stroke-width:0px,color:#FFDE59,fill:#545454 end subgraph After ["_After_"] Plugin("User Customizations:<br>- custom plugins") style Plugin stroke-width:0px,color:#AB7F45,fill:#FFE2B1 API("crate:rspack_binding_api") style API stroke-width:0px,color:#FFDE59,fill:#545454 Plugin --> CustomBinding("Custom Binding = <br>crate:rspack_binding_api + User Customizations") API --> CustomBinding style CustomBinding stroke-width:0px,color:#AB7F45,fill:#FFE2B1 end Before -.-> After style Before stroke-dasharray: 5 5 style After stroke-dasharray: 5 5
Next Steps
Now you have a basic understanding of how Rspack Custom Binding works. Let's move on to the Create From Template guide to set up your development environment.