Skip to main content

Command Palette

Search for a command to run...

Goodbye Webpack! Hello Parcel ๐Ÿ‘‹๐Ÿผ

Published
โ€ข0 min read
Goodbye Webpack!  Hello Parcel ๐Ÿ‘‹๐Ÿผ

If you have written any Javascript framework like either React, Vue etc. chances are that you have come across one form of bundler or the other.

Well here is another one called PARCEL.

Introduction

Parcel is a blazingly fast web application bundler that boasts of its zero-configuration setup ๐Ÿ˜ฑ. Yeah! you heard me right zero-configuration.

image

Hard to believe, then lets set up a simple React application with Parcel and Babel.

Setup the Project

So first things first, we need to set up our project. Run the following command below in your terminal

NB - Am assuming you have Node installed if not, you can download it here

With that out of the way, run the following in your terminal

$ mkdir parcel-project
$ cd parcel-project 
$ npm init -y

Now that we have our directory setup, we can install the packages that are required.

$ npm i babel-preset-env babel-preset-react parcel-bundler --save-dev
$ npm i react react-dom --save

Generating the files

Now that we have the project setup, we can go ahead and set up our React application. Let's start by creating a .babelrc file, then add the following lines to your the .babelrc file we just created

// .babelrc

{
  "presets": [
     "env",
     "react"
  ]
}

Now let's create the entry point for our React application. Create a file called index.js and another file called index.html. In the index.js file, we add the following lines of code.


// index.js

import React, { Component } from 'react';
import ReactDOM from 'react-dom';

class App extends Component {
  render() {
    return <h1>Hello World! with Parcel </h1>
  }
}

ReactDOM.render(<App />, document.getElementById('root'));

In case this is your first time with React, all this code is doing is just import our react library and creating a DOM object that renders the text Hello World! with Parcel. For more on React, take a look at this

Now let's create the root element in our index.html file. Open the file and add the following lines of code to it


<!-- index.html -->

<!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">
  <title>Parcel Tutorial</title>
</head>
<body>
  <div id="root"></div>
  <script src="./index.js"></script>
</body>
</html>

Execute the Parcel Script

Now for the moment we have all been waiting for, in your package.json file, add a start script that runs parcel index.html. So you should have something like this

// package.json
{
...

"script": {
  "start":  "parcel index.html"
}

and we can then run npm start in our terminal. If you followed every step correctly, you should see your react application spin-up. Head over to the URL provided http://localhost:1234 and you should have a web page like the image below

Screenshot 2019-09-29 at 5.00.45 PM.png

there we have it, a simple React app setup with zero-configuration using the parcel-bundler

Conclusion

Now I don't want to bash webpack in any it still is a very useful bundler but whenever I think of going from this ๐Ÿ‘‡

{
  "name": "react_web",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.config.js",
  "scripts": {
    "start": "webpack-dev-server --open --hot --mode development",
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.4.0",
    "@babel/preset-env": "^7.4.2",
    "@babel/preset-react": "^7.0.0",
    "babel-loader": "^8.0.5",
    "css-loader": "^2.1.1",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "react": "^16.8.5",
    "react-dom": "^16.8.5",
    "style-loader": "^0.23.1",
    "webpack": "^4.29.6",
    "webpack-cli": "^3.3.0",
    "webpack-dev-server": "^3.2.1"
  }
}

which has a whole lot of webpack dependencies to this ๐Ÿ‘‡

{
  "name": "parcel_demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "parcel index.html"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-preset-env": "^1.7.0",
    "babel-preset-react": "^6.24.1",
    "parcel-bundler": "^1.12.3"
  },
  "dependencies": {
    "react": "^16.10.1",
    "react-dom": "^16.10.1"
  }
}

the decision just becomes really clear.

Have a contrary opinion, let me know in the comments below and with that, we will call it a demo ๐Ÿ˜. Have a nice day folks!

M
Muescha6y ago

you should include into the article that:

A) audit error

this error would not be fixed: issues serialize-to-js

$ npm audit

                       === npm audit security report ===                        

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                                Manual Review                                 โ”‚
โ”‚            Some vulnerabilities require your attention to resolve            โ”‚
โ”‚                                                                              โ”‚
โ”‚         Visit https://go.npm.me/audit-guide for additional guidance          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ High          โ”‚ Denial of Service                                            โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Package       โ”‚ serialize-to-js                                              โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Patched in    โ”‚ >=2.0.0                                                      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Dependency of โ”‚ parcel-bundler [dev]                                         โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Path          โ”‚ parcel-bundler > serialize-to-js                             โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ More info     โ”‚ https://npmjs.com/advisories/790                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
found 1 high severity vulnerability in 10336 scanned packages
  1 vulnerability requires manual review. See the full report for details.

B) can not find 'json5'

i fixed it with an additional npm install

  /Users/muescha/Work/react/parcel-project/index.js: Cannot find module 'json5'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:582:15)
    at Function.Module._load (internal/modules/cjs/loader.js:508:25)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (/Users/muescha/Work/react/parcel-project/node_modules/v8-compile-cache/v8-compile-cache.js:161:20)
    at Object.<anonymous> (/Users/muescha/Work/react/parcel-project/node_modules/babel-core/lib/transformation/file/options/build-config-chain.js:19:13)
    at Module._compile (/Users/muescha/Work/react/parcel-project/node_modules/v8-compile-cache/v8-compile-cache.js:194:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
    at Module.load (internal/modules/cjs/loader.js:600:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
    at Function.Module._load (internal/modules/cjs/loader.js:531:3)
P

Thanks for the article, gave it a bash and it worked as expected. The immediate benefits are not that clear though. The parcel index.html/js example on their site results in a fair bit of pa.js boilerplate.

I wonder will parcel also fork into more than one useful dependency to have? Happens often enough with these tools.

parcel-bundler requires

{
        "@babel/code-frame": "^7.0.0 <7.4.0",
        "@babel/core": "^7.0.0 <7.4.0",
        "@babel/generator": "^7.0.0 <7.4.0",
        "@babel/parser": "^7.0.0 <7.4.0",
        "@babel/plugin-transform-flow-strip-types": "^7.0.0 <7.4.0",
        "@babel/plugin-transform-modules-commonjs": "^7.0.0 <7.4.0",
        "@babel/plugin-transform-react-jsx": "^7.0.0 <7.4.0",
        "@babel/preset-env": "^7.0.0 <7.4.0",
        "@babel/runtime": "^7.0.0 <7.4.0",
        "@babel/template": "^7.0.0 <7.4.0",
        "@babel/traverse": "^7.0.0 <7.4.0",
        "@babel/types": "^7.0.0 <7.4.0",
        "@iarna/toml": "^2.2.0",
        "@parcel/fs": "^1.11.0",
        "@parcel/logger": "^1.11.0",
        "@parcel/utils": "^1.11.0",
        "@parcel/watcher": "^1.12.0",
        "@parcel/workers": "^1.11.0",
        "ansi-to-html": "^0.6.4",
        "babylon-walk": "^1.0.2",
        "browserslist": "^4.1.0",
        "chalk": "^2.1.0",
        "clone": "^2.1.1",
        "command-exists": "^1.2.6",
        "commander": "^2.11.0",
        "cross-spawn": "^6.0.4",
        "css-modules-loader-core": "^1.1.0",
        "cssnano": "^4.0.0",
        "deasync": "^0.1.14",
        "dotenv": "^5.0.0",
        "dotenv-expand": "^4.2.0",
        "fast-glob": "^2.2.2",
        "filesize": "^3.6.0",
        "get-port": "^3.2.0",
        "htmlnano": "^0.2.2",
        "is-glob": "^4.0.0",
        "is-url": "^1.2.2",
        "js-yaml": "^3.10.0",
        "json5": "^1.0.1",
        "micromatch": "^3.0.4",
        "mkdirp": "^0.5.1",
        "node-forge": "^0.7.1",
        "node-libs-browser": "^2.0.0",
        "opn": "^5.1.0",
        "postcss": "^7.0.11",
        "postcss-value-parser": "^3.3.1",
        "posthtml": "^0.11.2",
        "posthtml-parser": "^0.4.0",
        "posthtml-render": "^1.1.3",
        "resolve": "^1.4.0",
        "semver": "^5.4.1",
        "serialize-to-js": "^1.1.1",
        "serve-static": "^1.12.4",
        "source-map": "0.6.1",
        "terser": "^3.7.3",
        "v8-compile-cache": "^2.0.0",
        "ws": "^5.1.1"
      }