You Don’t Need Webpack — 3 Better Alternatives for Building Your JavaScript

Bundles of Yarn
Photo by Karen Penroz / Unsplash

A new generation of JavaScript bundlers offers greatly improved developer experiences

If you’re building any kind of frontend app with multiple source files and dependencies, you’re going to need a build tool to help you solve the problem ofbundling — putting all of the source files and dependencies together into a form the browser can understand.

Most people are familiar with Webpack, the most popular tool for solving this problem, but it comes with some big downsides. A new generation of JavaScript build tools can greatly improve the experience for developers. In this post, we’ll review a couple of the options.

React: Up & Running: Building Web Applications on Amazon

What Do JavaScript Build Tools Do?

Before we jump into the different tools, let’s talk briefly about what JavaScript build tools typically do. Put simply, these build tools take your JavaScript and dependencies and prepare them for use in the browser. Here are some of the steps involved:

  • resolution — find where various source components live on disk.
  • transformation — translate different forms of JavaScript/TypeScript (and typically also other assets like HTML, CSS and images) into standard, packaged forms that browsers can use.
  • bundling — compile the many source components together into a small number of JavaScript bundles that can be easily loaded by the browser. Some newer build tools are able to avoid this step in some cases to improve performance.
  • minification — shrink the JavaScript bundle sizes by removing unnecessary code, renaming variables and a number of other optimization techniques.
  • serving — serve the content to browsers in development mode, including features like “hot” reloading

Note that not all tools do all of these steps or do them in exactly the same way, but these are some of the core problems that most build tools solve in one way or another.

What’s Wrong With Webpack

For many years, Webpack was pretty much the only game in town. On the plus side, Webpack is extremely powerful & extremely flexible: it can really do just about anything you want to your JavaScript bundle through an extensible configuration file.

But the core bundling strategy and incredible flexibility of Webpack also leads to its most serious downside: speed. As a JavaScript project grows, the amount of time it takes Webpack to rebuild your codebase grows, and it eventually becomes a real problem for both the development and release cycle. When developers need to wait 5 or 10 or more seconds to see results after making code changes, the entire development process slows down significantly. Though there are various strategies for improving speed through caching, optimization and other configuration, it can be a non-trivial issue to address and requires significant effort.

A secondary, but related issue is the complexity of the configuration. Because Webpack is so open-ended and powerful, the configuration can be quite complicated. Developers are sometimes left to piece together their own complicated JavaScript pipelines including external tools and loaders, even to do simple things. In practice, these external tools and loaders sometimes conflict with one another or have version or configuration incompatibilities.

The Alternatives

So let’s dive into the choices for JavaScript bundlers, and see what advantages they bring over Webpack.

Vite

Vite is a new kind of build tool that greatly accelerates the development loop by taking a very different approach. We started off this post by saying that JavaScript build tools help solve the problem of bundling. It turns out, however, the bundling step itself is not always needed. In particular, when used for development purposes in modern browsers, we can actually skip the bundling step with the help of ES6 modules.

Instead of pre-processing and bundling up all of a project’s modules into a single JS file, Vite lets the browser request the imports itself. All Vite has to do is resolve the imports, and if necessary, translate them to ES6 modules. This massively accelerates the speed to reload our code after we make changes in development.

The Vite logo
Vite Logo (image from vitejs.dev)

When it comes time to deploy to production, we still do need to bundle our code, so Vite does provide this functionality, though it makes use of other tools under the hood, including Esbuild, which we’ll cover below.

I got Vite up and running very easily on a new project, though I did run into some troubles when trying to port over an existing Webpack project, due to more complicated configuration and dependencies.

When to use it:

✅ You want to prioritize lightning fast reloads in development

✅ On a new project, or an existing project without complicated configuration

Parcel

Parcel is a bundler that stands out for its zero configuration approach. It’s a breeze to setup and use on a new project with little to no configuration required. Simply start with your project entry point, typically an HTML file, and any assets that are included are bundled up and served appropriately. It supports a large number of languages and configurations right out of the box.

The Parcel logo
Parcel Logo (image from parceljs.org)

In spite of its simplicity, it is also quite powerful and flexible, supporting a number of advanced bundling options with little to no configuration, but also featuring an extensible plugin system. It is also much faster than Webpack, though not as fast as Esbuild, which we discuss below.

When to use it:

✅ You want a faster and much simpler bundler than Webpack

✅ You want to take advantage of some advanced features without heavy configuration

esbuild

Esbuild also takes a traditional bundling approach, but is simply lightning fast. Written in go instead of JavaScript and making healthy use of parallelization, Esbuild is estimated to be 50–100x the speed of other bundlers including Parcel and Webpack.

The ESBuild logo
esbuild (image from esbuild.github.io)

Though Esbuild is incredibly fast, there are a couple of features missing from other buildlers that may make it challenging to use in production for some projects. For example, Esbuild does not have as extensive built-in language and framework support as some of the other build tools (though in many cases 3rd party developers have built solutions).

Additionally, unlike some of the other solutions, it’s a build-only tool that does not have a development server built-in. Setting up a separate development server is easy enough, but it is an extra step with Esbuild and may not offer the same level of integration.

I’ve been using Esbuild since it became the default bundler in the Phoenix Framework a couple of releases ago and am very happy with it. This configuration works especially well since Phoenix takes care of the server aspect, and the setup is mostly the same between development and production

When to choose Esbuild:

✅ You want a traditional bundling approach, but want it to be lightning fast

✅ You are okay setting up your own dev server (or are using one already, as is the case with a framework like Phoenix).

✅ You’re sure your particular languages/frameworks are supported — you’re okay with some of the “missing” features of Esbuild

Recap — Three Great Choices for JavaScript Bundling

We’ve looked at three powerful alternatives for your JavaScript workflow: Vite, Parcel and Esbuild. All of these tools can provide big improvements over Webpack to your JavaScript development flow. If you haven’t updated your JavaScript tooling for a while, now is a great time to do so!