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! 😎
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!)
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!