Over the past year, you’ve likely heard rumblings about a new build tool called Parcel.
For those of you unaware, Parcel describes itself as “a web application bundler, differentiated by its developer experience. It offers blazing fast performance utilizing multicore processing, and requires zero configuration”.
Now build tools have come and gone and ones such as webpack and Browserify are still knocking around, so why do we need a new one and why am I spending my time writing about Parcel?
Straight out of the gate, I have to say that I think webpack has a lot of awesome use cases and certainly has its place in web development. But for all that webpack does to help streamline the web development process, it requires a lot of initial setup.
Most web developers typically only need a set up that handles Sass/SCSS, CSS vendor-prefixing, Babel and a code minifier. We may also want some cache-busting included in the form of putting hashes at the end of each file name. Oh, and if our build tool also knows how to whip up a live server during development, then I’ll throw a few bonus points in!
So even though most development setups will always (and only) use the aforementioned, we always have to set this up when using webpack. This is where Parcel enters to blow webpack out of the virtual water.
To demonstrate this we’re going to take a typical webpack setup that has all of the plugins mentioned earlier, and then swap it out for Parcel.
Ready?
Let’s take a look at our webpack.config.js
file to see exactly what we are going to be converting:
module.exports = { entry: { main: './src/js/main.js' }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].[chunkhash].js' }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: "babel-loader" } }, { test: /\.s[c|a]ss$/, use: ['style-loader', MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader'] } ] }, plugins: [ new CleanWebpackPlugin('dist', {}), new MiniCssExtractPlugin({ filename: 'style.[contenthash].css', }), new HtmlWebpackPlugin({ inject: false, hash: true, template: './src/html/index.html', filename: 'index.html' }), new WebpackMd5Hash() ] };
To get this set up, besides installing webpack
and webpack-cli
, I had to install the following dependencies: autoprefixer
, babel-core
, babel-loader, babel-preset-env
, clean-webpack-plugin
, css-loader
, extract-text-webpack-plugin
, html-webpack-plugin
, mini-css-extract-plugin
, node-sass
, postcss-loader
, sass-loader
, style-loader
and webpack-md5-hash
. I also needed to set up a postcss.config.js
file in order for vendor-prefixing to work.
As you can see, there’s quite a lot of configuration involved in getting what would typically be a fairly normal set up for a developer in 2018.
Just to quickly recap, in order to be in line with what our webpack setup did, we want our Parcel set up to handle the following things:
So how do we achieve the exact same setup with Parcel?
To get started, we have to first install Parcel by running the following command in our terminal: npm install -g parcel-bundler
. You’ll notice that I’ve installed it globally ; this allows us to run the parcel command without the need to include the entire file path.
You can choose to omit the -g
and install this locally inside of the project if you prefer. I found that I ended up having to run the exact file path in the terminal when I tried using a local version, as typing parcel
simply didn’t work. Instead, I had to run node node_modules/parcel-bundler/bin/cli.js
in the terminal.
I then went and created an initial project structure, which looked like this:
/dist
/src/js/script.js
/src/scss/styles.scss
Index.html
I went into the project root and ran npm init -y
in the terminal in order to create a package.json
file.
I put some initial code inside of script.js
and styles.scss
as test code. Nothing too fancy: I created a const in script.js
to see if it would get transpiled down to a var, and wrote some very basic nested SCSS code to see if it would get transpiled down into CSS.
So the fancy thing about Parcel is that it will simply look at whatever script tags you have inside of your index.html
and will transpile the code it finds.
So in our case, I had the following inside of my index.html
:
<html> <body> <h1>Hello, Parcel!</h1> <script src="src/js/script.js"></script> </body> </html>
I then ran parcel index.html
from the terminal, and after a few seconds, Parcel had compiled some files into the /dist
directory and had booted up a local server at port 1234. I opened my browser and went to localhost:1234
, and my code was there! I checked the compiled script file (which also has a hash suffix to handle cache busting) and could see that the const had indeed been turned into a var.
So without me having to configure anything, Parcel had sorted out a local server, used Babel to transpile ES6 code down to ES5, and even took care of file hashing! I also didn’t have to write anything special to tell Parcel where the input and output files were. This is pretty sweet!
I even found out afterward that we can get Parcel to open up your default browser and load the page by simply adding -open
to the end of your command (so we would instead run parcel index.html -open
).
Well, I haven’t referenced it at any point yet, so I guess we need to get that sorted out.
So I had to install node-sass
in order for this to work. I ran npm install node-sass
in the terminal. I then added import '../scss/styles.scss'
at the top of my script.js
file, ran parcel index.html
, and, to my amazement, Parcel sorted everything out.
I had a separate file in my dist folder for HTML, CSS, and JS  —  it also took Parcel 2.28s to compile everything, which is pretty blazing fast! Parcel even added a link tag to the CSS file in the dist version of index.html
, which I hadn’t even bothered to sort in the original src version!
I should also note that, as far as I am aware, the import would have also worked with plain old CSS, so had I not been using SCSS, I could have imported vanilla CSS and skipped the npm install for node-sass
.
I added a ::placeholder
tag in my SCSS to see what would happen but the CSS code that was compiled didn’t include any prefixes. It turns out that this is yet another thing that Parcel has included in its setup! All we have to do is include a .postcssrc
file in the root of our project (alongside our index.html
file) and include the following inside of it:
{ "plugins": { "autoprefixer": true } }
I ran parcel index.html
again, checked the outputted CSS file and it now had a bunch of vendor-prefixed styles for ::placeholder
 —  wow!
At this point, you may be wondering how Parcel used Babel without a .babelrc
file, seeing as we needed a .postcssrc
file to handle vendor-prefixing. Well, it turns out that Parcel is preconfigured for Babel to compile code for browsers that have more than 1 percent market share. So you’ll only need a .babelrc
file if you’re looking to target something a little more niche.
So far, none of my code has been minified, which I guess is expected, given that I am still inside of a development environment. Let’s see what happens if we run parcel build index.html
.
No way! The HTML is minified, the CSS is minified, the JS is minified! Everything is minified!
So, amazingly, Parcel has handled everything that our webpack setup handled, and only required two pieces of configuration:
npm install node-sass
.postcssrc
fileTo me, that is an incredible feat and is something that I can see being supremely useful for new developers looking to use modern tools and for experienced devs who either want a blazingly fast set up or have simply grown tired of webpack’s complexity.
I love what Parcel does. It feels like a super-close-to-zero config setup, which is awesome for speeding up the development process, by letting me concentrate on building stuff rather than configuring a setup.
It does everything I need it to do, without headache.
It’s also a lot faster than webpack at compiling! I should note that I did notice the fans on my 2015 Macbook Air kicking up from time to time, which I can only imagine is down to Parcel using multicore processing —  so it builds faster than webpack, but requires more work from your computer in exchange.
One thing I would like to make clear though is that this idea of “zero-config” in general is a little bit misleading. Most of the whole “zero-config” concept is simply down to how much something has been abstracted away in the setup.
webpack tries to be as extensible as possible by default, whereas Parcel gives you a lot of the most commonly used features by default. This make Parcel an easy win for most of us. It’s amazing that this is even possible, but I just want to shed some light on this as I think it’s super important to have an understanding of what the tools we are using are doing for us.
In closing, you should definitely give Parcel a shot. But don’t rule out webpack just yet, as if you find yourself requiring a set up that goes down a road less traveled, it may just be the route for you.
As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app, mobile app, or website. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.
Modernize how you debug web and mobile apps — start monitoring for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.
Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.