Why Moving to Rspack and How to Use It with Bazel

yanir manor
3 min readAug 11, 2024

--

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

  1. 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.
  2. 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.
  3. 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.
  4. 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:

  1. 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 in package.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.
  1. 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.

--

--