Let's Look At... Parcel Posted on Jan 29th, 2018

What is it?

So Parcel is another module bundler, similar in ways to Webpack or Browserify.
But this one claims to "just work", so let's take a look! 👀

Let's Get Started

I'm pretty much just going to follow the official Getting Started.

Let's create somewhere to work:

$ mkdir project-1
$ cd project-1

And install Parcel:

$ npm init -y
$ npm install -g parcel-bundler

Now let's add some basic files, your typical kinda thang.

.gitignore

# General
*~
.DS_Store
node_modules/

# Parcel Related
.cache/
dist/  

index.html

<html>  
  <head>

  </head>
  <body>
    <header>
      <h1>Parcel Test</h1>
    </header>
    <section class="content">
      <div class="box">

      </div>
    </section>
    <script src="./app.js"></script>
  </body>
</html>

app.js

console.log('hello');  

It should look like this:

.
├── .gitignore
├── app.js
├── index.html
└── package.json

Now let's see what Parcel can do!
$ parcel index.html
...
This actually gave me the following error:

async function bundle(main, command) {  
      ^^^^^^^^
SyntaxError: Unexpected token function  
    at Object.exports.runInThisContext (vm.js:76:16)
    at Module._compile (module.js:542:28)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.runMain (module.js:604:10)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)
    at bootstrap_node.js:509:3

From a quick Google search, it turns out async functions are only supported in Node.js v8 onwards. My (quite outdated) v6.9.4 of node needs to be upgraded!

Node Issues (Can Skip)

I use nvm, so updating my local version of node was as simple as:

nvm ls-remote to list the available versions nvm offers.

...
v8.8.1  
v8.9.0   (LTS: Carbon)  
v8.9.1   (LTS: Carbon)  
v8.9.2   (LTS: Carbon)  
v8.9.3   (Latest LTS: Carbon)  
v9.0.0  
v9.1.0  
v9.2.0  
...

From this output, I decided to install v8.9.3 as it's the 'Latest LTS' (Long Term Support), so probably good for a while:
nvm install v8.9.3

To make sure v8.9.3 is used next time I start a new terminal session:
nvm alias default v8.9.3

Might as well update npm while I'm at it:
npm install -g npm

Let's check everything is good to go:
node -v && npm -v

  v8.9.3
  5.6.0

Success! 🎉

Now let's try Parcel again:
parcel index.html

zsh: command not found: parcel  

So upgrading Node.js wipes out all your globally installed packages 😑

Let's fix that quickly

npm install -g parcel-bundler

Ok back to Parcel...

Where were we?

NOW LET'S TRY PARCEL AGAIN:
parcel index.html 🤞🏻

⏳  Building...
Server running at http://localhost:1234  
✨  Built in 217ms.

Nice! 😎

image

So that should be now running on Parcel's built in dev server, pretty cool.

My project directory now looks like this:

.
├── .cache
│   ├── db8235d6812b5c8a7f0fa52459aa5e24.json
│   └── f67a21878735da127d156ff98c298c6c.json
├── .gitignore
├── app.js
├── dist
│   ├── index.html
│   └── project-1.js
├── index.html
└── package.json

(To print out the directory structure above, I've used the tree command, specifically tree -a -I '.git' which ignores the .git directory to keep things readable. You can install 'tree' via your typical apt-get install tree or brew install tree)

Since running parcel index.html, we now have two additional folders

.
├── .cache
│   ├── db8235d6812b5c8a7f0fa52459aa5e24.json
│   └── f67a21878735da127d156ff98c298c6c.json
├── dist
│   ├── index.html
│   └── project-1.js

/.cache contains magic 🧙🏻‍♂️
/dist is served up to the browser and should look pretty familiar

/dist/index.html has been updated to include the full path to the newly compiled /dist/project-1.js file:

/dist/index.html

<script src="/dist/project-1.js"></script>  

/index.html

<script src="./app.js"></script>  

And /dist/project-1.js contains all kinds of crazy. Most of which you can happily ignore, but things Parcel needs to do it's thing in browser. Things like 'Hot Module Replacement' and 'Friendly Error Logging' etc.

So making changes in my original files:

.
├── app.js
├── index.html

Triggers a re-compilation and browser injection (not full reload, unless needed).
This becomes especially useful if you're working on stateful elements (such as dirty form fields) as the whole page won't reload and loose your browser's current state.

So making the following changes in /index.html

<h1>Parcel Test</h1>  

to

<h1>Parcel Testing</h1>  

and in /app.js

console.log('hello');  

to

console.log('hello1');  

(The creativity... I know!)

img

Causes the browser to simply inject the changes, which you can see because the 'Console' has kept the initial log (a full refresh would wipe the 'Console' history based on my DevTools settings).

So, not ground-breaking stuff... But considering how simple that was (minus my personal problems with node versions) it could be quite a powerful tool for getting quickly set up on simple projects.

I'm not sure how it fares when projects get really big or how easily you can customize the, but thinking back to my first foray into Webpack a few years ago - this was a breeze!