JavaScript Build Tools
June 18, 2019 Alex Anderson Devops
This is a post in a series about code projects, open source, build tools, and deployment.
JavaScript really has grown up in the past decade. It used to be slow and localized to only a web browser context. With the advent of Node.js, not only is JavaScript used on the web, but it can now be used for servers, command-line tools, and desktop applications.
JavaScript has also become more complicated, with package managers, bundlers, ES6 transformations, and a whole lot of other stuff. It's not like you can't write JavaScript in it's own "script.js" file, or even include it directly in a <script>
tag. But a lot of powerful developer features and improvements are available by using a build tool.
What is a build tool?
A build tool is code that does something to other code. There are a bunch of things you might want to do with build tools:
- Package Management. npm is the de-facto JavaScript package repository (but that might change soon). They provide a CLI tool which you can use to download and manage JavaScript packages which other developers have made available. Other CLIs for the npm registry, like yarn, are also available.
- Task Running. You need to have some way to execute your build tools. There are some older task runners that performed configurable actions for you, like grunt and gulp. These have plugins and modules that do specific things to your code, like minify, run compilers, or process CSS. These task runners aren't as popular lately, not because they aren't effective or don't work, but because bundling provides more flexibility and power when it comes to generating the output of your build tasks.
- Analysis. Unlike compiled languages, JavaScript doesn't throw any errors until you actually execute it. This can be a pain and slow down the development feedback loop. Fortunately, linting tools like ESLint can analyze your code and warn you about problems that might exist. You can go even further and add static type checking using a tool like TypeScript or Flow.
- Test. Automated tests can give you confidence that your code is working properly as you make changes to it. This can be considered part of your build process, making it so the build doesn't complete successfully unless all of the tests pass.
- Compiling. Like those that turn C++ code into a binary application, compilers transform your code in some way, such as using babel which lets you use newer JavaScript features which your target web browser might not support. SASS, LESS, PostCSS, and many more CSS build tools perform the same function as Babel, but for CSS.
- Bundling. With the advent of frontend packages being available through package managers, an easy solution for accessing those arbitrary packages was necessary. Some solutions manage this by keeping the modules separate. Webpack took a different approach. Instead of just transforming JavaScript modules in place, why not combine them all into a single bundle? Or better yet, separate different modules based on their usage (such as route) and not by arbitrary module boundaries. And why not include other files too, like CSS, HTML, images, and more? Webpack has inspired a number of other bundlers, such as Parcel, which is good for zero-config bundling, and RollUp, which is great for library packages.
Zero-Config Options
Build tools can be a bit of a pain, and while knowing them well can give you a leg-up, in a lot of cases it isn't necessary for the average app developer. Tool and framework developers often create their own abstractions on top of these build tools that make it easier (and probably better) for developers.
One prolific example is Create React App. This handy package contains all of the necessary dependencies, task running scripts, code analysis, test framework, compiling tools, and bundlers which you could need to create... uhm... your own React app. It's all configured for what is considered 'best practices', and gives you a couple of ways that you can customize it yourself. One of the best features is the ability to "eject", or remove the abstraction and expose all of the underlying tools.
If you were to eject Create React App, you would find Webpack, Babel (and babel-plugin-macros), Jest, ESLint, SASS, PostCSS, and TypeScript are all baked into this little package. It also includes things to make your life and your users' lives better too, like accessibility checking. It's a really handy tool, and a perfect example of a low-to-no config build tool.
Another tool that can help with this is CodeSandbox, and online programming environment that lets you get up and running on a whole bunch of frameworks inside your web browser! It's really cool, and very powerful.
Know it, but Don't Sweat It
There's a lot of stuff that I've shared here, and I think it's good to know about it all. However, it can be really easy to get overwhelmed by all of the things you might think you have to learn. But guess what: In a lot of cases, you don't have to learn all of these things. It's good to know what's under the hood, but even if you don't, the engine will keep running.
Sometimes that might be necessary to change or tweak the settings in these build tools so it works for what you want to do, and that is a great time to dig into the documentation and understand how that specific tool works. But you don't have to understand everything all at once.
Abstractions like Create React App and CodeSandbox make it easy to ignore these tools, and that's a good thing. It lets you focus on building great things instead of continually messing around with the build process.
So go and build something!