Today we’re gonna talk about application bundlers — tools that simplify our lives as developers. At their core, bundlers pick your code from multiple files and put everything all together in one or more files in a logical order that are compiled and ready for use in a browser. Moreover, through different plugins and loaders, you can uglify the code, bundle up other kinds of assets (like CSS and images), use preprocessors, code-splitting, etc. They manage the development workflow.
There are lots of bundlers out there, like Browserify and webpack. While those are great options, I personally find them difficult to set up. Where do you start? This is especially true for beginners, where a “configuration file” might be a little scary.
That’s why I tend to reach for Parcel. I stumbled upon it accidentally while watching a tutorial on YouTube. The speaker was talking about tips for faster development and he heavily relied on Parcel as part of his workflow. I decided to give it a try myself.
What makes Parcel special
The thing I love the most about this bundler: it doesn’t need any configuration. Literally, none at all! Compare that to webpack where configuration can be strewn across several files all containing tons of code… that you may have picked up from other people’s configurations or inherited from other projects. Sure, configuration is only as complex as you make it, but even a modest workflow requires a set of plugins and options.
We all use different tools to simplify our job. There are things like preprocessors, post-processors, compilers, transpilers, etc. It takes time to set these up, and often a pretty decent amount of it. Wouldn’t you rather spend that time developing?
That’s why Parcel seems a good solution. Want to write your styles in SCSS or LESS? Do it! Want to use the latest JavaScript syntax? Included. Need a server for development? You got it. That’s barely scratching the surface of the large list of other features it supports.
Parcel allows you to simply start developing. That’s the biggest advantage of using it as a bundler — alongside its blazing fast compiling that utilizes multicore processing where other bundlers, including webpack, work off of complex and heavy transforms.
Where using Parcel makes sense
Parcel, like any tool, is not a golden pill that’s designed as a one-size-fits-all solution for everything. It has use cases where it shines most.
I’ve already mentioned how fast it is to get a project up and running. That makes it ideal when working with tight deadlines and prototypes, where time is precious and the goal is to get in the browser as quickly as possible.
That’s not to say it isn’t up to the task of handling complex applications or projects where lots of developers might be touching code. It’s very capable of that. However, I realize that those projects may very well benefit from a hand-rolled workflow.
It’s sort of like the difference between driving a car with an automatic transmission versus a stick shift. Sometimes you need the additional control and sometimes you don’t.
I’ve been working on a commercial multi-page website with a bunch of JavaScript under the hood, and Parcel is working out very well for me. It’s providing my server, it compiles my Sass to CSS, it adds vendor prefixes when needed, and it allows me to use import and export in my JavaScript files out of the box without any configuration. All of this allowed me to get my project up and running with ease.
Let’s create a simple site together using Parcel
Let’s take Parcel for a test drive to see how relatively simple it is to make something with it.
We’re going to build a simple page that uses Sass and a bit of JavaScript. We’ll fetch the current day of the week and a random image from Unsplash Source.
The basic structure
There’s no scaffolding we’re required to use or framework needed to initialize our project. Instead, we’re going to make three files that ought to look super familiar: index.html
, style.scss
and index.js
. You can set that up manually or in Terminal:
mkdir simple-site
cd simple-site
touch index.html && touch style.scss && touch index.js
Let’s sprinkle some boilerplate markup and the basic outline into our HTML file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="https://fonts.googleapis.com/css?family=Lato&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.scss">
<title>Parcel Tutorial</title>
</head>
<body>
<div class="container">
<h1>Today is:</h1>
<span class="today"></span>
<h2>and the image of the day:</h2>
<img src="https://source.unsplash.com/random/600x400" alt="unsplash random image">
</div>
<script src="index.js"></script>
</body>
</html>
You may have noticed that I’m pulling in a web font (Lato) from Google, which is totally optional. Otherwise, all we’re doing is linking up the CSS and JavaScript files and dropping in the basic HTML that will display the day of the week and a link from Unsplash that will serve a random image. This is all we really need for our baseline.
Marvel at Parcel’s quick set up!
Let’s run the application using with Parcel as the bundler before we get into styling and scripts. Installing Parcel is like any thing:
npm install -g parcel-bundler
# or
yarn global add parcel-bundler
Let’s also create a package.json
file should we need any development dependencies. This is also where Parcel will include anything it needs to work out of the box.
npm init -y
# or
yarn init -y
That’s it! No more configuration! We only need to tell Parcel which file is the entry point for the project so it knows where to point its server. That’s going to be our HTML file:
parcel index.html
If we open the console we’ll see something like this indicating that the server is already running:
Server running at http://localhost:1234
Parcel’s server supports hot reloading and rebuilds the app as change are saved.
Now, heading back to our project folder, we’ll see additional stuff,that Parcel created for us:
What’s important for us here is the dist
folder, which contains all our compiled code, including source maps for CSS and JavaScript.
Now all we do is build!
Let’s go to style.scss
and see how Parcel handles Sass. I’ve created variables to store some colors and a width for the container that holds our content:
$container-size: 768px;
$bg: #000;
$text: #fff;
$primary-yellow: #f9f929;
Now for a little styling, including some nested rulesets. You can do your own thing, of course, but here’s what I cooked up for demo purposes:
*, *::after, *::before {
box-sizing: border-box;
}
body {
background: $bg;
color: $text;
font-family: 'Lato', sans-serif;
margin: 0;
padding: 0;
}
.container {
margin: 0 auto;
max-width: $container-size;
text-align: center;
h1 {
display: inline-block;
font-size: 36px;
}
span {
color: $primary-yellow;
font-size: 36px;
margin-left: 10px;
}
}
Once we save, Parcel’s magic is triggered and everything compiles and reloads in the browser for us. No command needed because it’s already watching the files for changes.
This is what we’ve got so far:
The only thing left is to show the current day of the week. We’re going to use imports and exports so we get to see how Parcel allows us to use modern JavaScript.
Let’s create a file called today.js
and include a function that reports the current day of the week from an array of days:
export function getDay() {
const today = new Date();
const daysArr = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
return daysArr[today.getDay()];
}
💡 It’s worth a note to remember that the getDay
function returns Sunday as the first day of the week.
Notice we’re exporting the getDay
function. Let’s go into our index.js
file and import it there so it gets included when compiling happens:
import { getDay } from './today';
We can import/export files, because Parcel
supports ES6 module syntax right out of the box — again, no configuration needed!
The only thing left is to select the <span>
element and pass the value of the getDay
function to it:
const day = document.querySelector('.today');
day.innerHTML = getDay();
Let’s see the final result:
Last thing is to build for production
We’ve created the app, but we want to serve it somewhere — whether it’s your personal server or some zero-configuration deployment like Surge or Now — and we want to serve compiled and minified code.
Here’s the one and only command we need:
parcel build index.js
This gives us all of the production-ready assets for the app. You can read more about Parcel’s product mode for some tips and tricks to get the most from your environment.
I’ve said it several times and I’ll say it again: Parcel is a great tool. It bundles, it compiles, it serves, it pre- and post-processes, it minifies and uglifies, and more. We may have looked at a pretty simple example, but hopefully you now have a decent feel for what Parcel offers and how you might start to use it in your own projects.
I’m interested if you’re already using Parcel and, if so, how you’ve been using it. Have you found it works better for some things more than others? Did you discover some neat trick that makes it even more powerful? Let me know in the comments!
In the beginning, instead of chaining multiple touch commands, you can just do touch index.html style.scss index.js.
Cool article
Does anyone know what’s Parcel’s support for async chunks and does it keep the hashes of files that did not change between builds?
The parcel build command does not remove source maps, so here is some simple npm script to get you started
I use Parcel for quick prototyping, it is really good for this, but misses critical functionality like copying assets, proxy ( ex. hot reloading wordpress site etc ). Still, great bundler for small projects.
I tried it on CodePen, but got error Uncaught ReferenceError: ReactDOM is not defined, I guess it’s about react.production.min.js added. Pen is fine if added react.development.js. Is there any help?
The whole point is it doesn’t need any configuration, Webpack 4(+) including every features that Parcel provides, with a bit of twist. Meanwhile, parcel doesn’t provide advanced feature.
What are the missing advanced feature that come to mind ?
It would be nice if webpack docs give a generic solution for some things. I had to switch to parcel on a project because I could not reference my images in webpack (dynamic images in js, but it works in css and html). I have debugged and searched in SO for hours, and a deadline is close.
It for reasons like this I hope parcel gets better. Not bashing webpack at all, even from a beginner perspective, it is awesome. But these subtle issues can scare anyone off.
A personal favourite I like about parcel, is if you need to include an npm / yarn module that you haven’t already installed, when you add the import ‘module’, and click save, parcel automatically installs that package for you.
That’s amazing
I feel like this is exactly how build tools should be—very simple to get going with, but powerful enough to be used with large projects. I can well imagine someone new to web development being immediately put off by the ridiculous complexity of just getting started with something like Vue or React, and needing to install and configure a bunch of tools before even setting up their first app (or relying on some ‘magic’ to do it for them).
Hi,
Personally I use Fuse Box, for all types of big and small project. It is simple and very fast…
Good article,
Thx
Do you have examples of cases where parcel would appear to be limited ?
#1. Multiple dynamic entry points.
#2. I do not have and DO NOT WANT a index.html, there are too many dynamic parts for one to exist.
#3. Fine control over configuration. The webpack configuration for generating a script thats meant to be included on other sites is very different from the configuration for webpack when building frontends. Sometimes you need to have multiple of these in the same project.
#4. Visibility and clarity into what the hell it’s even doing (what is the cunks its’ generating, how big are they, what is it using for source map generation, etc).
#5. Does it have all the fancy flags to support safari10 enabled since if it doesn’t and you can’t set it in the uglifyjs or terser (whichever it’s using) somehow, you are doomed. Things like setting it in some global file that tells it your browser support is useless! yes thats right useless, you can only support those damn browsers by sending most of the compression tools into a mode specifically for those browsers (and said mode won’t activate unless explicitly enabled). This is in part due to how broken the scope model is in things like safari10.
etc etc
Basically, when you need to do something that’s “big” this “no configuration” is a giant pain.
Finally, so it’s “easy to configure” for your single css, 10 js files project. Great. Real world has more js, css, and other files then I can count. Just the entry points alone can reach absurd number. How good is it dealing with that? When you don’t have control to dynamically tweak things like that the dev experience becomes living hell; no matter how “fast” it is, it won’t be fast enough.
Woah, that was easy! Many thanks.
Did you consider FuseBox?
It’s strange to call parcel index.html on one side, and parcel build index.js on another side.
How do you integrate this with wordpress
Comment from reader Patrik Pindeš, after the buzzer:
… is not true. And I am not talking about any advanced stuff but pretty much things that 90% of developers come across with.
Here is why:
Want to copy static assets (such as robots.txt, favicon.ico)?
You mush install a plugin “parcel-plugin-static-files-copy” and configure it.
Want to keep ids in inline svg?
You must create a “.htmlnanorc” file and configure it
Want to share your style.css file between pages?
you must create linker js files, otherwise, it will not work, https://github.com/parcel-bundler/parcel/issues/2340
Want to use inline style for whatever reason?
you can’t, the bundler with not work correctly.
Some of the bugs have been reported ages ago and are still not fixed. So I would be very careful using this bundler in production yet.