Channel
Interviewed Person
Conferences
Take a deep dive into how Turbopack (the new Rust-based successor to Webpack) came to be, and the new incremental architecture it's built on with Maia Teegarden, Engineering Manager at Vercel. Turbocharge your business: https://vercel.com/home
Vercel
Interviewed: Conferences
Hello, everyone. I'm Maia Teegarden, and today I'm extremely excited to introduce you all to Turbopack. You briefly heard about it in today's keynote, but I'm here to take you on a much deeper dive. First, I'll introduce myself real quick. I originally joined Vercel last year as a core Next.js developer, and one of my main efforts was replacing our file transformer Babel with SWC which is a much faster alternative written in Rust.
And earlier this year, I became the Engineering Manager of a newly formed team focused on web tooling. We maintained SWC, Webpack, and now, Turbopack. Now, I'm sure you're all excited to hear about what Turbopack is and what makes it so special and I will get to that. But first I wanna start with a little bit of history, because I think looking back at the way JavaScript-based apps have evolved, especially over the last 10 to 15 years helps illustrate what it takes to build a bundler
that will stand out today and stay useful into the future. So let's go all the way back to the pre-JavaScript days, back when everything was statically rendered by servers. When you typed a URL into the address bar, a server would return a page of HTML that would stay the same until you either clicked on a link or submitted a form, and these actions would result in the server sending back an entirely new page of HTML that would repaint the entire screen. Then JavaScript came along
and you could update HTML on the page dynamically. This started out really basic, like showing scrolling text or sparkles that trail your mouse cursor. But over time, websites became more and more interactive, and more and more JavaScript was added to the page. Eventually, the lack of a module system became a problem for maintaining large JavaScript code bases. You could split your code into multiple files, but they all had to share a global scope. Bundling JavaScript just meant Concatenating files.
Node.jS really changed the game, even though it was a server-side runtime. It came up with a module system called CommonJS, and it bundled itself with a package manager called npm. Now, you could organize your code into modular files and easily pull in reusable third party dependencies. This inspired what we now know as bundlers, tools that could understand module systems in order to build a dependency graph and create bundles of JavaScript, which combine these files with a runtime so they could run in the browser.
Another monumental change came in 2015 with ES6. Previously, JavaScript, also known as ECMAScript, was very slow to make changes. There had only been one release in 16 years and it was pretty insignificant. But ES6 came out with a bunch of revolutionary changes and the ECMA committee planned to add new features yearly. The problem was it was going to take some time for browsers to support these features, but developers wanted to use them right away. This is where Babel came in which was originally called SixToFive because it would take ES6 code
and transform it into ES5 code. So bundlers took on more responsibility and started to support transformations. This also allowed developers to use languages or supersets that can compile down to JavaScript like CoffeeScript and TypeScript. Bundlers empowered JavaScript-based apps so much that they went from little widgets on server-rendered pages to what are now known as single-page apps or SPAs. The server would send down some minimal initial HTML
with JavaScript that would render the entire application once it loaded. Naturally, this led to bigger JavaScript bundles which can take a long time to load. To help with this, bundlers started supporting something called code splitting. Instead of one big bundle, there would be many chunks that could be lazily loaded as they are needed. For example, if you're loading page A, you don't need the code that renders page B until you navigate to it. The concept is pretty simple, but with large apps, this can get really complicated to create optimized bundles.