skip to content

Let’s Learn Rspack

with Zack Jackson

How does Rspack, a Rust-based web bundler, make devs’ lives easier? Core team member Zack Jackson shows us how it works.

Topics

Transcript

Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.

JASON LENGSTORF: Hello, everyone. And welcome to another episode of Learn With Jason. Today, on the show, we are going to be tackling bundling and all the complexity that comes with it and the wonderful world of how to make them more performant.
I have a very experienced engineer, let me bring to the stage, Zack Jackson. Zack, how are you doing?

ZACK JACKSON: Doing great, how are you?

JASON LENGSTORF: I feel like we had a really great conversation�

ZACK JACKSON: It was Render ATL.

JASON LENGSTORF: Had a great conversation about the stuff you were working on. I'm pumped it's happening now. I'm really excited to talk about what you're working on. Do you want to give us a bit of a background on who you are?

ZACK JACKSON: Yeah, sure. I work� so, I'm infrastructure architect at ByteDance. I've spent time in web infra stuff. My main thing was bundling. That's what I've done, bundlingrelated stuff, working on bundlers, plugins. I'm most wellknown for Module Federation. It's the ability to share chunks or parts of different bundles with code reuse. Lots of work in the open source space, generally toward, like, enterprisetype issues.

JASON LENGSTORF: Got it. You say you've been working on bundles for most of your career. Do you mean crossproject? How far back does that go?

ZACK JACKSON: I would say, probably 2014. I had just gotten into, like, web development. I had� I mean, this is back in the [Indiscernible] days, how long ago it was, you know, I think what started it all out was, I was working on some WordPresstype project and it was a consultant's fee. I had gotten kind of tired of the redundancy of it. I had built a tool that would take a sketch file design and convert it into a WordPress theme and would generate all the template files and all the PHP based on tags you would put in Sketch. This was way before any bundling came out. When Webpack came out, it was like, wow, we have� the big thing around Webpack was you have this view. Understood your CSS and your JavaScript and how they actually connected to each other and images and so on. And that was, like, I would say� I don't know, I really enjoyed that concept after having to deal with janky things with a site. We're talking 2014 up until now. I think I really got serious into the open source space probably in 2015 or 2016? That's where things kind of accelerated a little more.

JASON LENGSTORF: Absolutely. So, today, we are working on a project� and I'm going to let you describe it because I'm pretty sure I wouldn't do it justice. What is the project you're maintaining today?

ZACK JACKSON: Um, so there's a few. But, the big one is Rspack and Module Federation. Those were the biggest two install base. We also have a couple other things that be work on, mike Midscene, which is AIpowered, endtoend testing framework. We've got links we're about to release next month, which is going to be our answer to React Native. But the big one is going to be Rspack and so Rspack� we refer to it internally as the Rstack just because the idea behind Rspack was we had built it to serve the business's needs, there are 20,000 frontend repos, the challenge we had kind of had was building it atscale was a real problem. So a lot of the builds are Webpackbased and, you know, we've got projects that are 100 gigs, plus, in repo size. We have a really, really customized build pipeline. In China, we have to deploy apps to WeChat and it uses JSON Module Formats. So you can't just bundle ESM and ship it. Your chunks are actually JSON, themselves, so you have to have a really specialized build pipeline that can handle the U.S. Outlets and quirky apps or native apps. So having one tool that could do it all, you know, is economical. So, obviously, we used Webpack as our building layer and then the reason� and so what Rspack essentially started out as is, let's rewrite Webpack onetoone in Rust. The cost of compute was� so, we tried two options. One, how expensive is the problem in terms of product latency, build's taking 40+ minutes. And what about migrating Vite? We had tried two years ago, tried to migrate to Vite and the problem is, like, it doesn't serve the needs of the company, which is one of the reasons Webpack is so useful, but not everybody needs all the power that Webpack could bring. You know, we've gotten a lot of people who hate that configuration style or writing a plugin for it. It can do everything and most people only need it to do 10% of its capability.

JASON LENGSTORF: Right. You launched this project to rebuild Webpack onetoone in Rust. You mentioned the cost. I think it's just helpful to sort of enumerate what those costs are because it can be tempting to say, oh, something is slow, rebuild it in Rust. It decimates any gains you could get otherwise, but in the case of ByteDance, you said thousands or tens of thousands of repos and gigabytes, so the efficiency of going from JavaScript to Rust does bear out over time and the speed gains. If there's 20,000 repos, there's 20,000+ engineers. Having any of them sitting idle, that adds up to be tens of millions of dollars of waste over the cover of the year. The cost of a few engineers for Rspack, the economics work out.

ZACK JACKSON: This is the economies of scale issue, which is, I think is another reason by� I know there's mixed feelings around when an enterprise company owns open source. Usually, we're like� the community's funny about it. What I've also found is and of these problems can't really be solved unless you have a problem you experience yourself, large enough to solve it, thing like treeshaking isn't a weakened project you create. We've been using� just an example of code operation, Terser. That's been the standard since 2015, almost 10 years, and there hasn't really been any change to Terser at all because somebody wrote it at work and even though there's drawbacks� our bundles leave 40% dead code in the build, but because of design decisions made 10 years ago, due to the compute complexity, they had decided, okay, well, we should just optimize it at the chunk level. It would be too slow to optimize, onebyone, so they do group and optimize instead of analyze optimize, group and optimize again. So, just to give of give you the idea. We've been stuck with 40% more bloat in the code, mostly because it's a hard problem and you need resources to solve it.
So, anyway, getting offtrack. Yeah, so, the challenge we had seen really was, okay, so if we move off of Webpack, the cost of doing so was, you know, extravagant. You've got 20,000 repos, you have to move 20,000 repos. We own a couple popular apps so you can imagine the business risk in maybe moving, you know, a billionuser app or whatever over to a brandnew pipeline they may or may not work. So, there's one, just the time and the manpower to actually rewrite the entire pipeline and, two, can the thing we're going to do what we need it to do right out of the box? No, which was like another big challenge.
I know Vite's working on this now with Rolldown. This was a major issue that stopped us from looking into it, the unbundled mode, it makes things really fast because you don't have to build all the dependencies up front so the app technically starts up right away. But at ByteDance, that would end up, you know� and I don't think Vite has a really� like� proper HMR implementation. Maybe they do now. When we used it, it was Live Reload Base and each one took 10 minutes. When you're pulling down a 3 gigabyte app? It's the network overhead that pulling, you know, several gigabytes in 10,000 slices. Or maybe they have it unchecked. So it's not even, technically, HTTP/2 can handle sending that down. The user environment� cool, two Chrome extensions and that ruins your speed. Trying to keep everybody building in the dev environment the same way, it ended up being more oncall support than any other option, as well.
And also, like, optimization, basically, we were had the spot where Webpack works, but it's too slow and we had done a bunch of tests to see how fast does a build need to be to actually� before you enter diminishing returns. We have a lot of data and a lot of apps so we have a pretty good sample size on our own so what we had found is if your CI pipeline takes over 30 minutes, that adds about...what was it? I think it's a 1,600 hours or was it minutes? I think it adds 1,600 minutes of product latency. So, if� so, basically, if the build takes 30 minutes to run, that branch will most likely only merge in 1,600� in, like, 16 hours' time.

JASON LENGSTORF: 26 hours?

ZACK JACKSON: Yeah. That would be the latency you would see getting adding on to anything going out the type. You would kind of get lost and� just think about, like, the mechanics of doing your work. The build's going to take 40 minutes, maybe you'll watch it for 10. Oh, well, there's a queue to walk the release through. When that build step, like, becomes such a delay, the velocity drops.

JASON LENGSTORF: And you're going to make a mistake the first time. Something's going to get caught in CI. If you've got a twoday lag between realizing there's a problem and when you can actually ship that problem� I remember working� when I was at IBM, we weren't quite that bad, but it was a solid fullday effort to get something through into production.

ZACK JACKSON: If you think about that full day, as well, how much of that is spent shipping value versus running around infrastructure.

JASON LENGSTORF: Send a DM, making sure someone's actually looking at your build. Is it stuck?

ZACK JACKSON: Arguments about who goes into the merge queue first. None of that's� deliverable. You know, none of that is valueadded.

JASON LENGSTORF: I think the thing that got me about that, it made me feel less like I was building and more like I was the caretaker of this PR. I didn't feel like a developer.

ZACK JACKSON: Exactly. And so, you know, that's kind of� I think one of the things that ByteDance is, like, very wellknown for, in general, is their ability to ship apps quickly. There's� so, there's a really good article, I always recommend people read, called How ByteDance Became the World's Most Valuable Startup. It does a good job detailing how the company's organized. It also makes a lot more sense why we would care about something like this because, you know, the idea I think is, well, if you can� there was a quote from somebody else who was at one of the fan companies who said they had worked on one of our apps and they had done this at another company before and it took us, I think, three months to do it and they said, at the other company, it would have taken closer to 18 months to ship the same thing.
So, like, you know, how fast you get it, the faster you can iterate, the faster you can iterate theories, the faster you can find things that work. Output speed and efficiency is really, really important.

JASON LENGSTORF: Absolutely.

ZACK JACKSON: This is where Rspack came along. We knew we had latency between a day and two days if the build is over this much time. If the build stays within the fiveminute range, the turnaround time on the merge is 20minute latency if you can keep the build within that fiveminute window because the dev is hot in their head, they're still communicating, the thing's ready, I've seen it on stage. So in whole getting it out the door is just much faster because nobody, like, has to meander off somewhere else. Just from the measurements we saw, that was essentially it, the faster the build, the shorter the minutes are it gets to prod by an order of magnitude.
We needed something that was guaranteed to have no risk to the business to do it and something that would keep oncall pressure really low. 80 people on our infra team and we are responsible for all of the web infra work at the company. If you've got tens of thousands of devs and a problem pops up, how fast that'll eat into your manpower time. Making sure something's going to work and continue to work and more or less work autonomously is an important thing.
We started out with building out Rspack, which is what we refer to is the base layer. Rspack is our build engine. How we refer to it internally is the Rstack. At the company, we have modern JS. We've got Rspress because we need to generate a lot of docs. We author libraries so this thing broke out and� most people don't want to config a Webpack so we have something called Rsbuild, it's essentially like a Vitestyle configuration style.

JASON LENGSTORF: Right defaults baked in.

ZACK JACKSON: Default's baked in. There's a reset you add on. If you want to say, control an environment, there's an Environments object. We have load bundle, which is similar to Vite's Import Module. So it's essentially the same kind of thing that we have and those were all areas that were really missing in Webpack because Webpack, yeah, it was really good at doing the work, but it was not very friendly to interact with. Like, daytoday. I want it to do its job well, but I want to configure it without 30 minutes on a new project every day.

JASON LENGSTORF: Sure, yeah. [Laughter].

ZACK JACKSON: Trying to lower that barrier of, hey, here's a thing that will just work. We want to build everything so that this is not� we don't want to build a giant, monolithic solution, because it's harder to maintain and less adaptable. We want to layer all of our infrastructure. Internally, we have a layer, everything's built off of something else, built off of something else. We do the same thing with the Rstack. Everything's independent, but it's designed to work well with another product of ours, so if you want bundle analysis and documentation, those two are built to work together, but they're not built to make you use them both.

JASON LENGSTORF: Got it. So, it's very� it's, like, modular, but modular in a way that's not fragments like the ecosystem can be. You get modules, but one module's built by somebody over here, another module's built by another maintainer. They don't know about each other. You have to be ready to deal with that.

ZACK JACKSON: A good example is, let's say you have Next.js and Storybook, welcome to hell. [Laughter]. I don't know if it works with Vite or not. Imagine you have one where, oh, this uses a different build tool but you need them both. This one might not have that convention anymore. Hey, here's the same thing and it's all the same build engine under the hood and it all works well together and it's familiar, it saves a lot of time and helps us expand our ecosystem in a useful way. But�

JASON LENGSTORF: Question in the chat about how you manage testing?

ZACK JACKSON: Currently, we use Vite Test. We're considering an Rstest. I'm very for because I want to have unit testing for Module Federation but for that to work, I need a transformer that understands federated imports, so having Rspackbased transformer for testing means that testing libraries would understand remote components and could pull them in ondemand and test your foreign modules from other users. So, I'm very bullish on that one.

JASON LENGSTORF: Cool. Very cool. Okay. I want to� I want to make sure we've got enough time to kind of try this out and, like, put something together so we've got about 60 minutes left on the clock, so why don't I take us over to our screenshare. I'm going to share this whole window. Let's get�

ZACK JACKSON: One more thing to include in there. Why we built it, we obviously built it for our own needs and the open source said� we kind of looked at it and said, due to the number of apps we support, opensourcing this doesn't add much more burden to us. Open source contribute 20% of the workload. The product� it already worked internally. The biggest thing about what we've seen in building out Rspack has been the ROI on it. I think for every dollar we invest, we get something like $70 back in yield on it.

JASON LENGSTORF: That's� and this is where I think the economies of scale become mindboggling. When you're a small startup, you're like, of course we can't do that, we can't afford to put a fulltime engineer on an open source project. When you're the size of tens of thousands of employees, you almost can't afford not to. It's interesting how that shifts over time.

ZACK JACKSON: Yeah. Per year, I think it's yielding hundreds of millions.

JASON LENGSTORF: That's nuts. That is unbelievable. [Laughter].

ZACK JACKSON: Given� given the cost of developing it is a fraction of that and also because� especially because we also have, like, members from all over the world so we don't have to always pay U.S. Prices for everything, so it's also made the feasibility of building all this stuff out a lot� you know� a lot more realistic and because of time zone differences, we also have six days a week, 18 hours a day.

JASON LENGSTORF: That's cool. That's very, very cool. Okay. So I'm sharing your� your Bluesky, do you want me to share a different profile?

ZACK JACKSON: Probably my Twitter profile would be the one I'm the most active on. Twitter's the one where I'm most active on here. All the updates, and stuff like that, will show up over there.

JASON LENGSTORF: Got it. And we are talking about Rspack today.

ZACK JACKSON: If you do want to try it out, what I would suggest is we go for Rsbuild. That's the whole collection. And so, Rsbuild, go for it right away. Rspack Vanilla is only useful if you have a Webpack config. If you want to use our ecosystem for new builds, use Rsbuild. It's easier to extend and enhance. It's very Vite familiar. So, this is what I would suggest is your main use point for stuff.

JASON LENGSTORF: Got it. Okay. Let me just update that right there, then. So we're going to learn Rsbuild today. I'm excited because it's been a while since I've explored build tools. You know, once I made the switch from Webpack to Vite, I kind of stopped thinking about it entirely so I'm interested to see how this space has evolved in the few years since.
What's the first thing I should do?

ZACK JACKSON: So, let's go to the Quick Start. There should be a little generate thing on how to generate it. Yeah, creating a project. Yeah.

JASON LENGSTORF: And I just realized, I got to do a quick shoutout here, we've got a live captioner here, Vanessa, from White Coat Captioning. This is made possible through our sponsor, Tuple. It is great if you want to start up a remote session and it has a lot of nice things to make that pair programming work well.
I have my NPM Create. Close this one and I'm going to move to my GitHub folder and we'll build it in here. Why is this so tiny? Okay. Let's� NPM Create Rsbuild Latest. We'll call this Let's Learn Rsbuild. Probably ESLint.

ZACK JACKSON: I like to go with this one.

JASON LENGSTORF: Let's go in here. NPMinstall. Let me actually open this project. What profile am I in right now? That's the problem. Okay. All right. So, this is our project, we are going to "getinit" just to get this showing up here properly. Now we have our source. There we go. So this looks pretty familiar from what I typically do. We've got the, you know, the app TSX for React, the CSS folder, our root render, all that good stuff.
So, what are the things we need to know when we're climbing into a project?

ZACK JACKSON: It's also extremely minimalistic. Considering this is somewhere deep down, you can see why I prefer this configuration because this is your full config to get up and running, which is�

JASON LENGSTORF: And this feels very similar� it gives me the same sense of relief I get looking at a Vite config.

ZACK JACKSON: Vite changed the game on what it means to configure a build and that's something when we were creating Rspack, we definitely took a nod to, you know, their� took a nod to what they had done, changed the landscape and ensure that, you know, I think this is why it got so popular is it got rid of bundling hell and it was fast.
So, essentially, yeah, this is what you got to work with. Some useful things to know about it are the define config, maybe if we jump to the build config, there are various options if we go to "config." Yeah. So, you can see, here, we've kind of got our toplevel ways to configure it, if you want to control anything with HTML, you would put an HTML on there. What I find myself working with is Source and Server and Dev areas. Those are, like, the main things, like, if I want to� if you want to use Define, Source Define plugins, how you could put stat env variables. Anything to do with your server, setting up ports, bases, things like that. The Tools areas is quite nice. While Rsbuild simplifies this, the Tools section gives you access to Rspack. If you click on that one, this will let you break into the Webpack Build Config again. So now Rsbuild, it extracts most of what you do. If you want to write a loader, you could go, like, api.transform, like you would do in ES Builder in Vite. But if there's something deep, sometimes I need to dig in here and change the chunk formatting options or, you know, something that's lowerlevel, you can easily tap and still hook into Rspack and inject a Webpack plugin or modify something deeper that maybe the tool doesn't expose for the 90 percentile use case.

JASON LENGSTORF: Got it. Okay. Okay.

ZACK JACKSON: It does not restrict you from accessing the underlying tool.

JASON LENGSTORF: I can see how this is nice, too, because it means if you want to set�

ZACK JACKSON: It's not like a CRA, it'll give you lots of control over that. Let's go to "plugin" in the menu up here. Just in the top� yeah, there we are. Then if we just go to Plugin System and Development in the right menu at the bottom there, then there should be� yeah. I think this� does it say anywhere? Does it show us our hooks we provide? Okay. So, here we go. So, yeah, then go to the API. Yeah, so you can see, these are some of the hooks. If you wanted to write your own little plugin, these are some of the hooks you can access, that allow you to kind of control or change or modify the lifecycle of the build and things like that and there's some cool ones on there, like the one I use a lot is api.transform, which I think is probably� these are all the lifecycle hooks. It might be under the API section, the next menu tab over, but there's a whole bunch in here that, yeah, and I think in the Build Core...

JASON LENGSTORF: Would it be�

ZACK JACKSON: There. That would probably be faster.

JASON LENGSTORF: Plugin Core.

ZACK JACKSON: If you want to make a custom plugin, if you wanted to do a loader, this is where you do a loader. You can do Transform and Resolve works the same way. You can access Webpack, but if you don't have experience in Webpack, or you're more familiar with the Vite ecosystem, you can customize this thing however you want by having your own, little setup there. A lot of it might be under here, like�.transform. There's another one for Resolve, as well. There you go, "resolve data request." What's cool about "resolve data," is it's based on who's asking for it. Whenever I would use ES Build, resolving is a onetime. I can't say, okay, I want to resolve this thing, but who's importing it? Was index.js importing it? Based on that, I want to change the resolve rules. It hooks into Normal Module Replacement, which is a superpowerful module resolution layer.
Just to give you an idea on some of the� if you ever want to go and fiddle with something, this is kind of the cool areas of it. For most people, though, it's just going to be that Config page and maybe pulling one or two offtheshelf plugins.

JASON LENGSTORF: When you get into bundlers, what I find really fascinating about them is at the end of the day, they are� it's a pipeline that we're dropping a file in and we get something else out the end and we just get to decide what happens along the way and so a lot of stuff that feels like we have no control over it is actually really configurable if you can get to that layer of what your bundling tool is doing and the part that I found really interesting is I found all sorts of interesting use cases. I had an instance where I am, like, some link, where everything had been turned into an Amazon referral link, right. And so instead of me having to do a "find and replace" across everything, instead, I was able to write a quick "replace" and log where the link was so I had a hit list to go edit those files later, but it didn't have to be done all at once, in one content management push. That was a content management thing that I was able to control because I understood how to tap into the bundler process and do these transforms.
It really is interesting if you are doing sites that have Markdown, you can make some really interesting changes and transforms into your sites, with the caveat of course that every plugin you build has to be maintained. [Laughter].

ZACK JACKSON: I would say, this is what got me into bundlers in the beginning is, wait, you're telling me the thing I write, or the developer writes, is really just a suggestion to the bundler? When I heard that, I think my younger, powerhungry self got obsessed with that. I've got the keys to the kingdom here. I had been through a lot of bureaucratic things and let's talk about doing something for six months and do nothing. One of them was the bundler. I don't need to ask permission from anybody in I write a plugin to do the refractor internally. Nobody understands what it's doing and I can do an entire company in one hit if I trust my ability to write the plugin. [Laughter]. That one will come back to bite you if you don't write the plugin well. That's a tough one to answer. [Laughter]. Luckily, that's never happened. I would not suggest that as a solution, but the nice thing about these tools is, oh, what if you have a really large codebase or a regex, can't kind and replace these things. What about twitching between two different libraries, a bunch of weird cases where this could be logistically a lot of dev hours to shift these around. With a bundler, there's lots of ways to say, hey, we're going to restructure how it works either permanently or as a crutch until engineering can get around to doing it everywhere.

JASON LENGSTORF: Yeah. Yeah. Yeah. I can see exactly why you got so into this because it really does just feel� I don't know. There's something� I feel like every once in a while, you figure out the layer underneath a layer and that feeling as we describe as being able to see the Matrix and you realize you can actually do a lot more than you thought. You suddenly gain a level of agency that you maybe you thought was for someone else. Understanding bundlers� I keep making up new words as I try to say this. Understanding bundlers is something that give you that feeling, you're so capable if you can figure out how the bundler works.

ZACK JACKSON: In my career, I would say there's almost nothing you can't solve for a company if you can wield their bundler well. Whatever problem they're going to run into, if the engineering can't do it, you can� as long as you know how to do it, you can definitely orchestrate that at a larger scale. I think the other thing about knowing a bundler is it's also good careerwise because I don't run across a lot of people who actually know how to use these tools or work� one, there's working on them, which maybe that's a little� maybe that's for people like me, who really, you know, have nothing better to do with their lives. But� [Laughter]. But, you know, knowing how to use the tool and leverage it really, really well. How I got into the bundlers was, oh, this is neat and this is helpful and I know how to split chunks. That is what led me into building Module Federation. But, I also got several jobs in my early career just because I knew how to configure Webpack 2 very, very well. That was it. That was my only criteria was, I could do it.

JASON LENGSTORF: I got a job, early on, because I built Babel plugins. This was before schema federation existed in GraphQL. That led to me getting several opportunities, just because I figured out how to make that stuff work, people thought I was a wizard.

ZACK JACKSON: Yeah. There aren't that many� I would say, the pool of talent is very, very small for these type of things. AST, if you do all that stuff. ByteDance is probably not the best example because everybody's like that here. [Laughter]. You know, at most places that I've gone to, that maybe aren't� the big tech companies, you're going to find there's only a handful, maybe, of people who really understand this stuff well. And, you know, it's� it's a very valuable skill to have because there's a much smaller pool of people who would know how to do it and once you progress enough up into an org or a product, eventually, you're going to come to the issue of the build does not work right out the box and we need it to be tailored for the needs of the company.

JASON LENGSTORF: Absolutely. Well, I mean, yeah. So, knowing that the superpower is available to people, let's talk a little bit about� I mean, I guess what's a good way to dig into this and show people how this works because this is going to work just like Vite. We've got a React app running. I'm relatively confident if I NPM here� that's not the window I meant to open. Let me take it over here. Come on, buddy, what are you doing? Come on. Here. Jeez. There we go. [Laughter]. Make that as hard as possible on myself. So, this is us running our app and it's just like I would expect from any other bundler. So that, in and of itself, is very cool, and this is being done under the hood with Rust so we know as the app gets bigger, the compute overhead of doing the bundling work is not going to be the bottleneck for us, most likely.
So, what do we� how do we� where do you want to go next? What do you want to show off here?

ZACK JACKSON: Hmmm.

JASON LENGSTORF: We do have a question, how does one go down the learning path of getting into all this? That's a great question. When I was learning, I basically� I think I learned by reading source code and it was not fun. [Laughter].

ZACK JACKSON: Yeah, that was� that was how� I asked, hey, how can I help with Webpack? Start with Compiler Class and work your way down and that's essentially what I did. Unfortunately, bundlers is a space where it's very much brute force. How I learned was by reading other people's Webpack plugins and reverseengineering them. I would say that now, you've got ChatGPT, so it's a lot easier to gets over those first few hills of� I would say, it's  the important part isn't really, oh, like, how does this work? Or, I don't know. How do I say it? For me, I don't need to know how to write a plugin. I need to know what a correct plugin looks like and how to navigate the codebase. ChatGPT knows every hook. Do you know how to navigate the API to tell it, hey, I need you to do this or that? And so, you know, I think with the AI tools, it helps a lot, but most of the stuff is navigation.
Scan through the docs, understand how you can configure it from the outside. I don't know, when I was building Module Federation, I need something that works like externals plugins, but something that works like a resolves to a resolve alias. So, it's another plugin called Resolver Plugin. Boom. You start to navigate through it like that. A lot of it looking at prior art. Seeing how people solve the issues and then, you know, like� probably the first� easiest way to do is to just start by writing something. Make a it little plugin that does something you want it to do, a loader�

JASON LENGSTORF: Can I make a request? I want to� I want to just say, like, my favorite thing, um� so, we'll say this� can we just write a quick plugin that will change this to pizza or something?

ZACK JACKSON: Yeah, that is fantastic. Yeah, let's do that. Let's go over to our config and go to Plugins and put an object on there if you don't want to make a new file.

JASON LENGSTORF: Okay.

ZACK JACKSON: And then I think it will be� let's just pull the docs open, as well. I think we can return a setup function in here, but let's just get our� our� our docs open.

JASON LENGSTORF: This is going to be� is it going to be Transform�

ZACK JACKSON: It would be the Transform one.

JASON LENGSTORF: Here's Transform...

ZACK JACKSON: Okay. So, Name Setup. Create an object, or stick that at the top of your file.

JASON LENGSTORF: Okay. And so this would be�

ZACK JACKSON: "Replace plugin."

JASON LENGSTORF: Butt replacer is the funniest thing you could have said. I love it. [Laughter]. There's our setup.

ZACK JACKSON: Then you would pass your API.

JASON LENGSTORF: So we pass in the API in the argument here and now we have access to api.transform. Right.

ZACK JACKSON: Uhhuh.

JASON LENGSTORF: Okay. And, in here, we can test� and in our case, we're going to� we know it's going to be a JSX. Can we do anywhere that you find a "but," you change it?

ZACK JACKSON: You can say, "test any JSX or TSX file." We're having to pipe it from Rust back to JS. It is the singlethreaded nature of JavaScript. Every type a call comes back from Rust, it has to queue whoever's calls are going off. If you have 10,000 in there, I have to wait for the bindings. We could speed this up a ton. We have been thinking about, well, what if Rspack had its own JS Runtime integrated into it? You don't have to send anything back to Node. I could evaluate JavaScript in Rust and using Quick JS and spawn JS and in theory, JavaScript could be quick again.
You train it to the loader you want so we're parsing less stuff and then now you could go "code.replace," I believe it is.

JASON LENGSTORF: I guess we can just do one of these...

ZACK JACKSON: And then I think it accepts� you can return a string or you have to return an object with, like, code and you optionally can return the source map updates. We can check what the doc example�

JASON LENGSTORF: The doc example is returning the string so we can just return the string?

ZACK JACKSON: Yeah.

JASON LENGSTORF: Theoretically, what happens when I go back to this tab, what we should see is it's replaced and there it is. Right. So, this is� this is the kind of stuff that we can get into and this is obviously a pretty contrived example. This is what showed up on the screen and this is the code we wrote, right. So you have a huge amount of control over what happens in this sort of thing. So you can imagine, like� I think the thing that really stands out to me is when you're doing a gnarly rebrand project and you know that there are brand colors hardcoded all over the codebases across every project in your� your org, you can start doing things where you know, like, hey, there are 90 shades of teal and your company color is teal, you can find the shades and transform them to be the right company color and flag it so you can fix it for real and use that as a way to fail the build if they're using the wrong brand colors after a certain deadline. You suddenly have a lot of agency, as a design systems manager or as a� as, like, an ops engineer, if someone is doing something you go is not allowed, you can start by fixing it for them and then start by� and by, you know, making it an actual buildfailing violation. Just really, really powerful stuff you can do.

ZACK JACKSON: So another cool thing� or the thing that I've loved the most� so I'm in the process of migrating� I'm taking the Remix/React Rooter7 project and I've ported its Vite plugin to Rsbuild so what I have admired most in doing all that� right before I did it, internally, I had just ported them from a Webpack version, from the Bring Your Own Build Remix and I migrated that one to Rspack and it was definitely� it was a labor of love for a little bit there. [Laughter]. And so then once I had got done with that, I'm like, okay, cool, Stockholm Syndrome, let's do it again, but with Rsbuild. You have to coordinate the client and the server resources very specifically. The server depends on the browser build. You have to coordinate which one goes first and doing those types of things, in Webpack, is very clunky. To configure them both and this build still needs to keep going and I need to add some piece of string, I have to inject that into the server or what if I don't know it until after blah, blah, blah. You write JS files and have the other one try to read the JSON files. They don't really work well together.
On� go to our Rspress website. Maybe something we can try� sorry, Rsbuild. So many names. Search for serverside rendering. This is something that I really appreciated, is the simplicity� try SSR, see�

JASON LENGSTORF: Multienvironment builds?

ZACK JACKSON: So, this is� so, if you scroll down in here, you can get a bit of an idea of, oh, here's how a� you know, you could create an SSRtype build. They are pretty horrible.

JASON LENGSTORF: They are. I thought I was going to build my own framework and I walked away from that fast.

ZACK JACKSON: Yeah, it's definitely not for the font of heart. This is how you could set up a build if you had multienvironment builds. This is, more or less, what the React 7 build looks like, under the hood. I use the API Modify Environment config and am I modifying web or Node or define them ahead of time and then chain on to them. But essentially, the ability to be able to set up both your environments, however you want them to, and then I don't know if we can see it. It might be in this doc here. Search and see if there's something called Load Bundle. Yeah, there we are.

JASON LENGSTORF: Load and execute bundles on the server side. Okay. Okay.

ZACK JACKSON: This is something I've wanted in various tools. Vite has something like Execute Module. But, yeah. So, essentially, I wanted something very much like this, which allows me to load a bundle as part of the building steps or, like, during the build pipeline of Rsbuild, maybe I want to essentially transform or compile something, maybe my infrastructure to start the server is something, as well. Build and load the orchestration layer and that kickstarts the app running itself. But� so, Load Bundle is really neat. It's an integrated dev server. I was working on a Cloudflare, I could register middlewares and say, "server.loadbundlemain" and access the server build after it's been done and pass that through as a piece of middleware. So Cloudflare and Wrangler, it could access the server and would also give me access to the bundler's primitives. I could start a build on the spot. Or, I could go, hey, await bundle, request response next. Return. And, then, there you go.

JASON LENGSTORF: My "but" replacer is barely scratching the surface of what's possible here. [Laughter]. Which is fair. [Laughter].

ZACK JACKSON: So, we can� so, maybe� let me see. Oh, we have a chat here, perfect. I can send you the pull request got for the Remix, the React Router one. It's a really good example. I send it to everybody who wants to see, how do I do stuff. Because it's, like, a really solid example that shows a whole bunch of random things and it's SSR, so it's more relevant. A lot of the examples we in here are very, very simple examples, which are all fine. I've got a lot of big companies going, how would I do three levels of hell and, you know, there's not exactly that on GitHub and I'm like, well, I got one for you and I send them this guy and� [Laughter]. And basically, that just� you know, inside of there, it just shows you, here's how you could use a custom Server.js file to kickstart the app. So, you use Server.js and your app would be "Node.Server.js." If you have to go "next build, next start," similar thing in here with the Server MJS server configurations. This is what the user has, which is straightforward. Basic build configuration.

JASON LENGSTORF: This is the plugin you're building, the Plugin React Router. Is that in here somewhere?

ZACK JACKSON: The example, plus the actual� oh, wait, that says� okay, yeah, no, it's open. And, I think I just pushed it yesterday, if I'm right?

JASON LENGSTORF: Here's all the source and everything here for the React Router Plugin.

ZACK JACKSON: Yeahhh. Oh, wait, I see this is not getting updated. Hold on. I think I had to fork the branch because I changed our twofactor auth. Give me one second. I'll send you the right one. I need to merge that PR, or push back to the Rsbuild branch. Okay. Let me just find it in here... React Router. Okay. I think this is the six commits ahead. Okay, so, here we are. Let me just� yeah. Okay. Here we go. Sorry about that. I forgot.
So this is the branch it's on, on my end. I want to see if I can sync those but I probably won't do that on the call right now...

JASON LENGSTORF: What did I just do? This one. This one. This one. Okay. So, here we go and we're going to go into Packages� actually, can I just do the thing? I don't think I have that permission anymore. Oh, I do! Hell, yeah! I still have this thing. So, this is the� yeah, that's fine. Okay. So, we can just open this up, like we would any other project. Here's the React Router, we've got the source. So we've got our plugin utils here. What do you want to look at it?

ZACK JACKSON: The interesting thing, if we go to the React Router sample in the examples, let's start with that one. React Router Sample. Let's start with Server JS. This kind of gives you an idea of, okay, if I wanted to make a custom executer� we have Rsbuild Dev and Serve, which is the builtin server that'll serve it out, but if you wanted to say, add this to something bigger, like a custom express server, this is essentially what some of our other APIs look like to implement. So, essentially all I'm really doing here� I also like how kind of simple it is. Create an express server. Create an Rsbuild instance and my middleware is Load Bundle. That's an example. There it is and, boom.

JASON LENGSTORF: Wow. Okay. This is� this is slick. Okay. Okay. I'm� I'm honestly kind of blown away by this. To anybody who doesn't understand, don't worry, this stuff is complicated and this is just the sort of thing I used to fight about at IBM, so I'm impressed.

ZACK JACKSON: Can you increase your font size a little bit? Maybe we can try to explain a little bit. So, essentially, inside of Rsbuild, you have Load Config, this is what the CLI would do. You can create multiple build instances. There's cool JS APIs. We're saying, let's create an instance of Rsbuild and initialize a dev server and start off with the default one or create a server for it to respond on, so now it's using the� you know, it's essentially just giving us a primitive to work with.
Then really, what we're doing is we add the default middleware we might stick on it from Rsbuild and you add your app, which is, in this case, we're saying dev server environments node because this is a serverside rendered app. All the environments that we'll configure, I can access during the startup of my actual, you know, app itself. So now I can say, hey, give me the Node build and I'm going to add the app entry point.

JASON LENGSTORF: Just to make sure�

ZACK JACKSON: App is going to be� I think it's in the Server Directory. Yeah, it's that app. App TS.

JASON LENGSTORF: We're loading this bundle, which is being exported as app. So this is the request handler and this is how we're able to kind of do things. Right. So this is the� the React Router saying, this is how you� like� handle a route in express format so when we come down here into the server JS, we're saying, here's Express and we've exported inapp, a property or a method called App, which is right here, that then handles expressstyle requests so you can see that it looks like there's a lot going on but really what we've done is we've basically, this call here means the entirety of the Node app has become portable instead of Rsbuild, when we load this bundle, it's like firing up that app anywhere, which is magical. That is so damn cool.

ZACK JACKSON: You're essentially loading your� this is the server entry point. So you could take App and� this code already is� you could just replace that load bundle with required dist JS app and there's production for you. You don't have to vanillarequire anything or go and find it.
Another instance is you'll have something that transforms it from TS into JS on the fly so you can evaluate the pure module, but I really do love the fact that this is actually loading the bundle that comes out of the build, which means you have all the power of the build behind it the whole way.

JASON LENGSTORF: And I think the thing that's really important here is I've gotten myself into absolute hell, in the past, because I wanted to use something in an environment that it wasn't built for so my bundler was taking the thing and putting it into whatever format, but then I'm in the server folder of a Next project and I'm trying to require a file but during their bundling process, they move files so my import is broken down so I'm doing something that doesn't work locally because I'm importing from a path that only exists when it's deployed and the complexity there is just, you have to learn too many internals of too many systems and they're all supercoupled to where you deploy specifically; whereas this is coupled to the bundler. If you know you're exporting an app bundle, you know you can use it and it's not related to the� whether you're deploying on AWS or Netlify or Cloudflare or whatever, you have the app and you can use it. You don't have to figure out pathing. You just get to use it and I think that alone is worth the price of admission. That is a huge feature for complicated apps that are crossing client/server boundary.

ZACK JACKSON: This was the first time I started to use Rsbuild because all the projects I'm working on, I'm working way down the stack of the supply chain of the bundler or working in Federation or a ByteDance project that's a gargantuan. I was like, I'll do it with Webpack and Rspack and, boom, I did it. It took three weeks to do it and it was a nightmare. Let me do it with Rsbuild. The slowest part was having to ask the team, how do I do this weird, obscure thing. This is the first thing I've written for Rsbuild, the APIs are new to me. But I was superimpressed with considering it took weeks to put together the old one and then on this thing, it was mostly just, like, my own ignorance or I needed to go and speak to Jacob from the Remix team about a convention I don't understand. This took a significantly less amount of time. Probably a couple of days to get it up and running.

JASON LENGSTORF: Wow. Absolutely, wow.

ZACK JACKSON: The whole load bundle thing for me. Think of� what is it? Remix even has a good example of this. The Routes TS file. How that works is they use something under the hood, which I'm using, as well, just to save time, called [Indiscernible], which is a lightweight way to execute TypeScript code. The Routes TS file is never used in the bundle. It's evaluated and it returns an object and the object are the entry points so it builds a new file that imports all your page routes. So, it builds a virtual file and so think about the mechanics of this, which is always kind of tricky. If I have that one thing and it's not in Vanilla JS, how do I evaluate it and execute it and use it inside my bundle to inform how I create the build in the first place? So, like, I� so, I could have ended up going with Load Bundle to do it, but I didn't know how to access it at the point I needed to access it at, but it was a really good example� it was a similar paradigm. Imagine you have a similar situation where you have this TS preflight thing and you want to bake that into a build CLI for your job. Part of it is going to do a bunch of complicated things. It's really nice to have something where you could say, oh, well, take this thing, compile it reliably, really quickly, and kind of, like, almost like shipping a binary. Bundle the app into a universal format that will work anywhere, execute on that and then actually start doing the app. Actually start building the app part. Like, selfpackage your infra.
I think prior, it was too slow to do this. But in here, because it's in Rust, 3 milliseconds and you can do whatever weird stuff you want to do, crawl across the app and that could be the preflight check. I really, really like because this is� a big pain point to, like, have the build be informed by the app itself.

JASON LENGSTORF: I've got a couple folks asking questions in the chat here, so let me pull this up. How does Rsbuild compare with Rolldown in the Vite ecosystem and someone gave a "+1" to that. Folks want to wait for Rolldown. So, I guess� are they a onetoone tool or, like, what are the tradeoffs?

ZACK JACKSON: Okay. So, I guess� so to give you the kind of breakdown of the layers, we would have Rsbuild versus Vite. So, what's the difference between Rspack and Rolldown? OXC, [Indiscernible] used to work at ByteDance. We worked with him a little prior and that's where we kind of started on OXC, which is really, really cool. The benchmarks, when he worked here, were really impressive to see what he was working on. OXC has a lot of speed on it, which is awesome. I think it problem with it is it needs more time to mature, just because it's new.
We use SWC. We have a really big pipeline for it, we know it works and for us, the biggest problem for ByteDance is mitigating risk. If it's a little slower, but it's guaranteed to keep the $300 billion machine running, nobody gives two shits about� sorry. Nobody cares about an extra second. In general, OXC looks really awesome. I'm pretty bullish on it. But I'm bullish on SWC. It's a bit slower, but it could definitely be quicker if KDY was given more time to work on it. So, transformers aside, the main differences that I could see between them...I mean, I think probably the big one is going to be� so, they'll most probably both do the job that you want them to do. I think the challenge is going to be, well, one, API shapes are going to be different. A lot of it is going to be depending on what hooks do they expose to you. This is the pitfall of every Rust project, so far, in my opinion, oh, it's super quick and has a terrible API because we had to keep it small to keep it fast.
I don't know, most� look at ES Build, the API has four hooks. You have super creative workarounds of, like, using ES Build three times in a row so it can output back to it. It's too limited.

JASON LENGSTORF: And I think that actually brings up a good point about the tradeoffs. ES Build, itself, is rippingfast, but it's very rare to use it. You usually use Vite which is a super set of ES Build. We needed the configurability by adding something like Vite on top of it. And so, I think that� that is very much been something that keeps me away from a lot of the Rust ports is that when I look at them, I'm like, okay, how do I do this thing I did over here? None of my projects are in the hours to build, they're mostly in the, like, three minutes to build and I can live with that. Getting it from three minutes to two doesn't materially change my life.
If it was a onetoone change, I would consider. Here, all the workarounds to get back to the functionality that you were able to do with the API surface of the other thing�

ZACK JACKSON: This is the other thing that I also think, where speed ultimately� so, I would say maybe the biggest thing� because I don't� so, with Rolldown, I know the team behind it because half of the team was the Rspack team. I think that they're very capable. So, I think that the tool will probably do quite well. But ultimately, I think what it's probably going to come down to� its ecosystem. Whatever Vite does today, it'll probably keep doing, faster. Whatever Webpack is doing, it'll keep doing, but faster. You're essentially in two different ecosystem styles. What size do you like to go with?
Now maybe if we look down� again, we need to see Rolldown show up, so I'm mostly just speculating here on what we've looked at from digging around in the code and our own experiences on this. But I would say, will be interesting to see, how will it handle stuff like, you know, like, they'll need chunking. So, this was another thing that we had seen, um� seen� so, like, I know that they have corrected from going with the unbundled approach and now they're going toward an app mode. They're introducing a chunking system and no Vanilla outputs, like they had done before.
So, the� yeah. So, I would say, like, what I'm interested to see is how are they going to handle optimization because that usually is where the pitfall is, is the chunking� getting your chunks, actually either finegrained so I don't have too many little chunks, like max size on the chunks. Two, actually data code elimination optimization, things like that. I'll be very�

JASON LENGSTORF: Just a higher level, I think maybe the bigger question is. For a lot of us, we� we aren't dealing at that level, you know. We're building�

ZACK JACKSON: Looking at it, yeah.

JASON LENGSTORF: It almost sounds like maybe the first consideration is, what are you porting over? If you're sitting on a big, old Webpack project, you probably don't have the time to fully port it over to Vite. Like, the full rebuild cost. You got to work out the economics for your team and how much time, how many people, what is the risk if it doesn't work? Can you guarantee onetoone parity of what you're doing today. If you can't answer "yes" to all of those questions, then it does kind of sound like the right choice� unless you've got the buyin to write it the way you wanted to� is to put it into Rspack. You get the onetoone feature parity, you just get a speed boost because you're using a more optimized bundle system.

ZACK JACKSON: Yeah. I think also, just preference. What have you historically liked? Some users have challenges with Vite because they're ESMfocused. I think they're going to be solving the support for that, but you know, if there's certain things� it really comes down to preference. If the speed was big deal breaker, imagine speed doesn't matter. We're getting off the "who's faster than who" because at the end of the day, we've entered a lot of diminishing returns. If Rspack takes five seconds and Rolldown takes two seconds, I don't care because before, they took seven minutes. At a magnitude of scale, that five to seven seconds is going to matter. I'm got projects I'm building here and I'm seeing this minute delta, nobody's going to have projects bigger than ByteDance and we're more than happy with the output speed it gives us.

JASON LENGSTORF: Recognizing there's a point you're just going for the high score and it doesn't functionally matter. There's a giant practical difference between an hourlong build and a 10minute build. There's a pretty significant different between a 10 and a twominute build. There is functionally no difference between a two and a oneminute build.

ZACK JACKSON: If you can keep the build under five minutes, 20minute product latency delay added. When it gets to 10 minutes, it jumps to four hours. So we already knew that, okay, we could� it's not going to get much quicker because the build isn't the problem anymore, assuming dev is quick� which dev usually is� maybe takes four or five seconds to start. Boom. If your dev server is fast always, that's probably the biggest hindrance and there's no way you're getting your CI pipeline out faster than two minutes. I'm sorry.
Once we've reached the point where it's acceptably quick, yes, you can make it much faster but the other thing always is, the amount of compute you're dedicated to speed� for me, when I think about a bundler, I don't buy a Ferrari to plow the field. I want a work horse, it might not be as fast as a race horse, but it can pull more weight. If you can make it� we could make it 20% quicker, I would rather you make it 20% more powerful and keep it the speed it is today.

JASON LENGSTORF: Yes, yes. Exactly. 100%. We are out of time. I've thrown out a link to Rsbuild. Let me throw a link on Twitter here. Is there anything else you want to link to before we wrap it up?

ZACK JACKSON: Maybe one more project. Okay. Two more. If you do microfrontends, I would check out zephyrcloud.io. This thing is� a lot of work has been put into this. It works with the Federation system. Works with Vite. All the bundler have been working on it. Think of it as Kubernetes for frontend. If you want to update button, the user will see an updated header in this environment for them. And, yeah, so it's a really, really neat one.
Midscene JS. I think we have an AI� there we are. So, this is our newest project that we had just came out with. This thing is awesome. So, I've just personally been interested in it. I've done a lot of� I've built out a trading algorithm.

JASON LENGSTORF: You are trusting at a level I am not. [Laughter].

ZACK JACKSON: There's a Python algorithm that calculates the rates on the trade and says, hey, go to my portfolio and go and buy it and tell me if the order went through. It's� yeah, it's not fully doing it, but it's the thing that does the instruction layer and it works really, really well. Definitely. I'm planning for my whole� and maybe one last one is Modulefederation.io. Federation is also our other popular� you know, this is a thing I had created back in the day. This is still what I primarily maintain alongside Rspack and all the other stuff.

JASON LENGSTORF: Awesome. All right. Well, let me do one more shoutout to our captioner. We've had Vanessa here, from White Coat Captioning, all day. That is made possible through our sponsor, Tuple.
Zack, this has been incredible. I've had so much fun talking about this. Y'all make sure you mark your calendars. Head over to the schedule and check it out.
With that, we're going to call this one all done. Thank you, all, so much for hanging out and we will see you next time.