A Crash Course in Modern JavaScript Tooling
Demystifying npm, webpack, babel, and rest of the JavaScript tooling ecosystem so we can get down to building modern web applications.

This is Part 2 of Modern JavaScript for Django Developers.

Welcome to Part 2!

In this part, we're going to cover the basics of the modern JavaScript toolchain that we'll need to build the hybrid application that we covered in Part 1. The goal is not to get to a deep understanding of the entire ecosystem, but rather to gain enough knowledge to be able to put it to good use in our projects.

Those readers who are already deeply familiar with the 2021 JavaScript ecosystem—things like bundling, webpack, module systems, etc.—may want to skim this part as a quick review and skip ahead to Part 3: Integrating a Modern JavaScript Pipeline into a Django Application.

The problem: modern JavaScript is hard and fragmented

JavaScript is just a programming language, right? Sure, one not without its quirks but like any other language, once you learn it you're kind of good to go, right? Right?!?

'' == false  // true
[] == false  // true
null == false  // false
undefined == false  // false
[] == []  // false
[] == ![]  // true
Sure we know JavaScript has it's problems, but once you overcome them (in this case, by using ===) then it's all good, right?
Source: JavaScript: The Good Parts

Well, unfortunately, not really. JavaScript is a unique beast and one that—as of 2021—continues to change at a disconcertingly rapid pace. The reasons date all the way back to the language's origins.

JavaScript was created quickly—in 10 days in 1995 if you can believe it. And while this was a remarkable achievement by a brilliant person, not surprisingly, the language had some flaws.

However, despite its flaws, JavaScript soon shipped with Netscape—the most popular web browser at the time—and, a year later, with the first version of Internet Explorer. This cemented the language's place as the default "programming language for the web"—a title it still holds 25 years later.

It also kicked off the most important factor leading to the complexity of the modern JavaScript ecosystem today—the need to run on different platforms.

Anyway, as JavaScript experienced this meteoric rise of popularity—in lock-step with the rise of the web—people started trying to make it better; hoping to overcome some of the flaws and limitations introduced by the language's rapid creation.

And they've succeeded. Kind of.

There are now loads of ways to work around many of JavaScript's early quirks—the initial lack of a native module system, the lack of typing of any kind, and, most importantly, the need to support all sorts of different—often out of date—devices and browsers. In fact, often there isn't just one workaround to each quirk, but many!

JS Meme

One of the main challenges with JavaScript in 2021 is the overwhelming number of tooling and framework options available.

The main problem with modern JavaScript is that the right way to do these things is rarely agreed on and the popular opinion is constantly changing.

Ok, so why does this matter?

Well, for many back-end devs, what it means is that they have to choose between two sub-optimal options. Either they ignore modern JavaScript and don't get to take advantage of advances made in the last decade, or they try to get up to speed on modern JavaScript and get completely overwhelmed by complexity of the tooling landscape.

Note: The next section makes heavy reference to the React documentation, however it's just used to illustrate the complexity and fragmentation of modern JavaScript. Vue and other frameworks have similar ecosystems, and the underlying primitives needed to make sense of them are the same.

Let's—as an example—take a seemingly simple use case. You—a Django developer—want to add a React front end to your app. So you go to the React docs for creating a new React app. There in the "Recommended Toolchains" section you see this:

React Recommended Toolchains

Well that's a lot of options! Ok, well whatever, you're integrating with an existing codebase so let's see what the "More Flexible Toolchains" link has to say.

React 'More Flexible' Toolchains

At this point you might be thinking something like this:

"Hmm. Do I want the power of webpack with the simplicity of presets? What's webpack again? I've heard of that... Anyway, that sounds complicated so maybe not Neutrino. I'm not building a monorepo, so maybe let's nix Nx. Fast and zero configuration sounds good. Maybe Parcel then? Although Razzle also is apparently zero-configuration and more flexible than Next.js... Wait, what's Next.js, again?"
—You, a confused Django developer

If you read through those options and feel dumb you are not alone! The JavaScript ecosystem is fragmented and complicated and—unlike most other frameworks and languages—there isn't a single way to do things. Also, like many communities with deep, insider knowledge, modern-JS-people often make assumptions about what their audience already knows—which can make it very difficult for new people to make sense of things.

Repeat after me: it's not your fault.

It's not your Fault

If getting into modern JavaScript makes you want to cry, just remember the great words of Robin Williams: it's not your fault.

At this point many people will have a reaction like "ugh, stupid JavaScript. I don't have time to figure all this stuff out" and then just drop another inline <script> into their app and call it a day.

But it doesn't have to be this way.

All you really need is a functional pipeline to get from modern JavaScript to a browser. And despite there being innumerable options, the primitives are actually relatively easy to reason with. So let's start there.

The modern JavaScript tool chain

Ironically, the React docs on "creating a toolchain from scratch"—the option that sounds the most complex—are actually the best place to start if you want to understand JavasScript toolchains from first principles:

React Toolchain from Scratch

It's just three things!

Let's get into those in a little more depth.

The package manager

The first part of the toolchain is the package manager. This is the thing that allows you to import and use packages that other people have built—basically pip but for JavaScript. It's the modern-day equivalent of adding <script src="some-library.js"> to your pages.

There are two popular packages managers out there, Yarn, and npm. JavaScript people can have strong opinions about which one is best, but honestly they're both fine. Npm is more popular. Yarn is newer and does a few things NPM can't do.

Yarn vs NPM

Don't worry, there are only 12 million sites on the internet debating npm and Yarn...

Either way, they are mostly compatible with each other. You can just pick one and move on. It doesn't matter.

If you aren't sure which to use, just go with npm. It's more popular and will do everything you need. The rest of this guide will assume you're using npm throughout.

The bundler

The bundler's job is to take your code—the libraries you're using from the package manager plus any code that you've written—and, well bundle it up. Bundlers take code spread across a bunch of places and mash them together so you only have to drop small number of files on your site—making it more performant.

Bundlers are most commonly used to bundle JavaScript, though you can add support for arbitrary input types. One common use case we'll cover later is to also add a SaSS to CSS build step using a bundler.

Again, JavaScript people can be quite opinionated about bundlers and there are about a gagillion of them to choose from. However, this guide recommends using webpack. It's the most popular bundler, which means it's well-tested, can do everything you need, and has a huge community for support. If you want to be on the bleeding edge feel free to try something else, but webpack isn't going anywhere anytime soon.

Webpack Vs

Here are just a few things in the JavaScript ecosystem that may or may not do the same thing as webpack...

The compiler

The final component of the pipeline is the compiler—also sometimes called a transpiler.

Remember earlier when we talked about the fancy new improvements that have been added to JavaScript? The compiler's job is take those and make them backwards compatible, so they work with the pesky devices—mostly browsers—that don't understand them yet.

If you took a Computer Science class in university you might remember learning about how compilers turned human-readable code into machine-readable code. Well, in the JavaScript world they are doing the same thing except that the machine-readable code is (usually) also JavaScript. And the machine doing the reading is your browser.

This guide recommends using babel as a compiler. It's the most popular JavaScript compiler, and will do everything you need. Done and done!

Putting it all together

Ok—that was a lot of information really quickly so let's summarize.

  1. We'll manage our library imports using npm.
  2. Webpack will bundle our code into a small number of JavaScript files we can add to our pages.
  3. Babel—managed by webpack—will compile our code, so we can take advantage of newer features and syntaxes and make them usable by older browsers.

That's it!

JS Pipeline

Our final JavaScript build pipeline.

Now that we know what we want, we can finally take steps to get this set up in our Django project.

That's the subject of Part 3: Integrating a Modern JavaScript Pipeline into a Django Application.

Subscribe for Updates

Sign up to get notified when I publish new articles about building SaaS applications with Django.

I don't spam and you can unsubscribe anytime.