Unlock the Power of Custom SWC Plugins: A Step-by-Step Guide
The world of frontend web development is constantly evolving, and one of the most exciting recent developments is the emergence of Speedy Web Compiler (SWC). As a high-performance JavaScript/TypeScript compiler written in Rust, SWC has the potential to revolutionize the way we approach build pipelines for modern web projects. In this article, we’ll delve into the world of custom SWC plugins, exploring how to write, compile, and integrate them into your webpack builds.
A Word of Caution
Before we dive in, it’s essential to note that the SWC plugin system is still experimental. As such, you should be prepared to deal with potential API instability and breaking changes. However, the concepts and approaches shared in this article should remain valid, even as the APIs evolve.
Setting Up the Project
To get started, we’ll create a simple plugin that transforms console.log statements into console.debug statements. While this plugin may not be particularly useful in real-life scenarios, it serves as an excellent example to demonstrate the basic concepts of SWC plugin development.
First, let’s install the SWC command-line interface using Rust nightly-2022-09-23. We’ll also add a Wasm compile target and create a new SWC plugin project.
Implementing the SWC Plugin
With our project set up, let’s start implementing our custom SWC plugin. We’ll use the swc_core
v.0.69 and implement the VisitMut
trait for a given struct called TransformVisitor
. This trait allows us to implement various methods that will be called when the Abstract Syntax Tree (AST) is traversed.
In our example, we’ll implement the visit_mut_call_expr
method, which will be called whenever a call expression, such as console.log()
, is encountered. We’ll also introduce some constants and implement our actual plugin logic, including drilling down the AST of the call expression and updating the callee to use the debug call instead of the log call.
Creating the Plugin Test Cases
Once we’ve implemented our logic, let’s create some test cases to ensure everything is working as expected. We’ll use the test-harness
macro to create test cases for our plugin and run them using cargo test
.
Building the SWC Plugin
With our plugin tested and validated, let’s build it using the following command: wasm-pack build --target wasm32-wasi
. This will create our Wasm file, which we can then use in our webpack configuration.
Testing the Plugin with Webpack
Now it’s time to test our SWC plugin with webpack. Let’s set up a basic JavaScript project with webpack and create an index.js
file with some console.log statements. We’ll then create a webpack.config.js
file that configures swc-loader and our custom plugin.
The Results
When we run webpack, our plugin should be called, and the console.log statements should be replaced with console.debug statements. We can verify this by checking the output in build/bundle.js
.
Conclusion
In this article, we’ve explored the world of custom SWC plugins, demonstrating how to write, compile, and integrate them into your webpack builds. While the plugin system is still experimental, it’s already possible to port complex Babel plugins to SWC by replicating the AST-traversal and modification logic and porting it to Rust. With SWC, we have the opportunity to rebuild and rethink some of the existing machinery, improving performance by orders of magnitude.