Why Moving to Rspack and How to Use It with Bazel
Introduction to Rspack
Rspack is a next-generation JavaScript bundler designed for high performance, scalability, and ease of use. It stands out with its focus on speed, modern architecture, and support for the latest web development features. Rspack provides several advantages over traditional bundlers like Webpack, especially in large-scale projects where build speed and efficiency are critical.
Benefits of Moving to Rspack
- Performance: Rspack is optimized for speed, significantly reducing build times. This is crucial for large projects where long build times can hinder development and deployment.
- Modern Architecture: Rspack leverages modern technologies and practices, ensuring compatibility with the latest JavaScript features and frameworks. It supports ES modules, tree shaking, and other advanced optimizations out of the box.
- Scalability: Rspack is designed to handle large codebases efficiently, making it suitable for enterprise-level projects. It can manage complex dependency graphs and optimize the output effectively.
- Ease of Use: Rspack’s configuration is straightforward and developer-friendly. It offers sensible defaults and powerful customization options, making it easy to get started while providing flexibility for advanced use cases.
Integrating Rspack with Bazel
Bazel is a powerful build system that excels in managing large codebases with complex dependencies. Integrating Rspack with Bazel allows you to leverage Rspack’s bundling capabilities within Bazel’s robust build environment. Here’s how to get started:
Bazel Workspace File
The WORKSPACE
file is used to declare external dependencies for your Bazel project. Here’s a detailed breakdown of each section in the provided WORKSPACE
file:
Loading http_archive Rule:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
- This line loads the
http_archive
rule, which is used to fetch external repositories.
Fetching aspect_rules_js:
http_archive(
name = "aspect_rules_js",
sha256 = "dda5fee3926e62c483660b35b25d1577d23f88f11a2775e3555b57289f4edb12",
strip_prefix = "rules_js-1.6.9",
url = "https://github.com/aspect-build/rules_js/archive/refs/tags/v1.6.9.tar.gz",
)
- This fetches the
rules_js
repository, which provides rules for JavaScript development with Bazel.
Loading rules_js_dependencies:
load("@aspect_rules_js//js:repositories.bzl", "rules_js_dependencies")
rules_js_dependencies()
- Loads and initializes the dependencies required by the
rules_js
repository.
Registering Node.js Toolchains:
load("@rules_nodejs//nodejs:repositories.bzl", "DEFAULT_NODE_VERSION", "nodejs_register_toolchains")
nodejs_register_toolchains(
name = "nodejs",
node_version = DEFAULT_NODE_VERSION,
)
Registers the Node.js toolchain with Bazel, allowing you to use Node.js in your build.
Importing NPM Packages:
load("@aspect_rules_js//npm:npm_import.bzl", "npm_translate_lock")
npm_translate_lock(
name = "npm",
pnpm_lock = "//:pnpm-lock.yaml",
verify_node_modules_ignored = "//:.bazelignore",
)
- Imports NPM packages specified in a
pnpm-lock.yaml
file, making them available for Bazel to use.
Loading npm_repositories:
load("@npm//:repositories.bzl", "npm_repositories")
npm_repositories()
Loads additional NPM repositories.
Bazel Build File
The BUILD
file defines the build rules for your project. Here’s a detailed breakdown of each section:
- Loading Bazel Rules:
load("@npm//:defs.bzl", "npm_link_all_packages")
load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_to_bin")
load("@npm//:@rsbuild/core/package_json.bzl", rsbuild_bin = "bin")
- Loads the necessary Bazel rules for linking NPM packages, copying files, and using Rspack.
Linking All NPM Packages:
npm_link_all_packages(name = "node_modules")
- This macro creates a
link_npm_package
rule for each third-party package listed inpackage.json
.
Defining Config Files and Build Dependencies:
CONFIGS = [
"rsbuild.config.mjs",
"package.json",
]
BUILD_DEPS = [":node_modules/" + d for d in [
"@rsbuild/core",
"@rsbuild/plugin-react",
"react",
"react-dom",
]]
CONFIGS
lists the configuration files required by Rspack.BUILD_DEPS
lists the necessary build dependencies, including Rspack core, the React plugin, and React libraries.
Copying Source Files:
copy_to_bin(
name = "srcs_export",
srcs = glob([
"src/**/*.css",
"src/**/*.svg",
"src/**/*.js",
"src/**/*.jsx",
]),
)
- Copies source files (CSS, SVG, JS, JSX) to the
bin
directory for the build process.
- Defining the Rspack Build Rule:
rsbuild_bin.rsbuild(
name = "rsbuild",
srcs = BUILD_DEPS + CONFIGS + [":srcs_export"],
args = ["build --config rsbuild.config.mjs"],
chdir = package_name(),
out_dirs = ["dist"],
visibility = ["//visibility:public"],
)
Defines the rsbuild
rule to use Rspack for building the project.
name
specifies the rule name.srcs
lists the sources and configuration files.args
specifies the build command and configuration file.chdir
sets the working directory.out_dirs
defines the output directories.visibility
makes the rule publicly visible.
Rspack Configuration
Create an Rspack configuration file (rsbuild.config.mjs
) to define your build settings:
import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';
export default defineConfig({
plugins: [pluginReact()],
});
Full code example:
https://github.com/yanirmanor/bazel-rspack
Conclusion
Moving to Rspack offers significant performance, scalability, and modern feature support advantages. By integrating Rspack with Bazel, you can harness the strengths of both tools to create a powerful, efficient build system for your JavaScript projects. The configuration process is straightforward, allowing you to set up and start benefiting from Rspack’s capabilities quickly.