Bundle your Web application with ParcelJS

Some developers enjoy writing vanilla JS but some are forced to used a framework like Vue, Angular, React e.t.c because it comes with a bundler like Webpack, some don't actually know how to implement bundler natively. With this article, you will be able to actually bundle your javascript project without relying on any framework.

What is ParcelJS?

ParcelJS is a web application bundler, differentiated by its developer experience. It offers blazing-fast performance utilizing multicore processing and requires zero configuration. With parcel, you don't have to set up any configuration or any loader for either CSS, JS, assets e.t.c.

Why you should use Parcel

  • Zero configuration:

  • Performance

  • Hot Module Replacement

  • Code Splitting

  • Support many asset types

Get Started with ParcelJS

Initialize npm in order to generate package.json file

npm init -y

Install ParcelJS Bundler as a global package using npm

npm install -g parcel-bundler

using yarn:

yarn global add parcel-bundler

How to serve your project

ParcelJS can use any kind of file as an entry point to serve but it's advisable to serve your HTML/jS file e.g index.html/index.js, about.html/about.js. you can serve your files with the following command:

parcel filename.extension

parcel index.html

After you have run your parcel command it will generate an address localhost:1234 where you can view your website. ParcelJS also support watch mode, which basically watches every change in your project and update it directly to your browser.

parcel watch index.html

you can as well watch multiple entry files with parcel watch file1, file2.. file N

parcel index.html about.html service.html contact.html

Importing asset into your project

You can import different types of assets such as (CSS, SCSS, LESS, STYLUS, Images e.t.c) into any javascript.

CSS

import './style.css

SCSS

import './style.scss`

NB: to compile SCSS you need to install npm package called sass

npm install -D sass

JAVASCRIPT

//ES6 Import 
import './script.js

or

//commonJS module

const script = require('./js/script');

Bundling your project for production

To bundle your project for production, you don't have to do any configuration or stress yourself, Parcel will automatically figure out all your files in your project(js,css, scss, jpg, png, svg e.t.c) and bundle everything for you, which you can push to production. use the following command to run your build process.

parcel build index.html

Demo

Let create a simple project that fetches user from Randomusers and displays it on the screen.

first let install parcel-bundle as a dev dependency, because we only need the package in our development stage, it won't go with our production build. But if you have installed it as a global package you don't have to install it again. if you haven't then you can either install as a dev dependency or global dependency.

npm install -D parcel-bundler

then create an index.html and index.js file in the root directory, index.html will be our starting point because the browser can only paint element/assets in HTML file on the screen.. index.js file will be the root where will be connecting all our pages/components to the DOM.

then let create a folder called pages, this is where all our pages files will reside.

NB: you can structure the project as you want, what matters most is when you are importing your files, make sure your path name is correct.

in the index.html file let include our index.js file, the markup should look like below.

<!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>
    <script src="index.js"></script>
  </body>
</html>

then modify your package.json file, in the scripts section add dev and build command. your script section should look like the scripts section below.

"scripts": {
    "dev": "parcel index.html",
    "build": "parcel build index.html"
  }

NB: the dev script command we will be using during the development stage after we are done developing, that's when we will then use build script command to bundle our files to production.

Adding our Javascript into our Pages folder

let create a file called users.js, it going to export a function that will consume the API from Random Users and return the list of users. which we can later import and reuse anywhere in our application.

export const users = () => fetch("https://randomuser.me/api/?results=10").then(res => res.json())

Adding CSS to your project.

Personally, I always create a separate CSS file for every component/page. e.g home.css, about.css e.t.c. and each component/page in a different folder. But for the sake of this tutorial not to make it look more complex. I'm just using a single component/page. You can follow the pattern and approach that works for you, what matters is when you're importing your file make sure your path is always correct.

let create another file called home.js, which will be component /page that will list our users. copy below snippet to the file.

.title {
  color: #fff;
  margin-bottom: 2rem;
  text-align: center;
}
.userAvatar {
  border-radius: 50%;
}
.user {
  list-style: none;
  display: flex;
  padding-left: -2rem;
  /* padding: 0; */
  margin-left: -2.5rem;
  padding: 10px;

  &:not(:last-child) {
    border-bottom: solid 1px #ccc;
  }
  &-details {
    margin-left: 10px;
    margin-top: 4px;
  }

  &-name {
    font-weight: bolder;
    font-size: 18px;
  }
  &-email {
    font-style: italic;
  }
}
body {
  background-color: rgb(131, 4, 153);
  font-size: 16px;
}

.users {
  width: 40vw;
  margin: auto;
  border: 1px solid #ccc;
  border-radius: 10px;
  background: #fff;
}

.loader {
  color: #fff;
  font-size: 30px;
  font-weight: bolder;
  position: absolute;
  top: 50%;
  left: 50%;
  translate: (-50, -50);
  z-index: 1000;
}

After you have created our stylesheet and users.js file that has a list of users from randomuser.me. let import our stylesheet and users into our main.js file.

full source code for main.js below.

import "./home.scss";
import { users } from "./users";

export const home = () => {
  const wrapper = document.createElement("section"); //Create an element that will wrap other elements i.e parent.
  wrapper.classList = "home"; //assign class home from our stylesheet
  const title = document.createElement("h1");
  title.innerHTML = "Welcome to Parcel Bundler Demo";
  title.classList = "title";
  const ul = document.createElement("ul");
  ul.classList = "users";
  //Create a loader element
  const loader = document.createElement("div");
  loader.innerHTML = "Loading...";
  loader.classList = "loader";
  wrapper.appendChild(loader); // add the loader to home wrapper element

  users().then(({ results }) => {
    loader.style.display = "none"; // hide loader when users are available from the API.
    results.forEach(user => {
      const li = document.createElement("li");
      li.classList = "user";
      //create User Avatar element
      const userAvatar = document.createElement("img");
      userAvatar.setAttribute("src", user.picture.thumbnail);
      userAvatar.classList = "userAvatar";
      li.appendChild(userAvatar); // append user avatar to the list
      //Create user details element
      const userDetails = document.createElement("div");
      userDetails.classList = "user-details";
      //user's name element
      const userName = document.createElement("div");
      userName.classList = "user-name";
      userName.innerHTML = `${capitalize(user.name.title)} ${capitalize(
        user.name.first
      )} ${capitalize(user.name.last)}`; //assign name to user's name element
      userDetails.appendChild(userName); // append it to userdetail element
      //Create user's email address element
      const userEmail = document.createElement("div");
      userEmail.classList = "user-email";
      userEmail.innerHTML = `${user.email}`; //assign email address to user's email address element
      userDetails.appendChild(userEmail); //append it to userdetail element
      li.appendChild(userDetails); //append userdetail element to the list
      ul.appendChild(li); // append the list to parent element ul
    });
  });

  wrapper.appendChild(title);
  wrapper.appendChild(ul);

  return wrapper;
};

//Accept a string and return the string in capitalize format
const capitalize = string => {
  return string.charAt(0).toUpperCase() + string.slice(1);
};

after we have created our home.js and pasted the source code above inside the file, take a look where we declare the home function, we export the function i.e we are to use it somewhere else (reuseable).

go to index.js file that we create earlier which is going to be the starting point of our project. if you remember we include the index.js into our index.html. it is the index.js file that the index.html file will load and index.js file will actually make use of every page will create.

import { home } from "./pages/home";

const app = document.createElement("div");
app.setAttribute("id", "app");
app.appendChild(home());
document.body.appendChild(app);

NB: Basically, what index.js file does is to collect the view created in the home.js page and append it into the document body. i.e (browser screen).

Running your Application To run your application, we will execute the npm script command we created earlier

npm run dev

NB: if you are having an error in your project that was due to ES7 syntax used in the project. you can try to install the following npm package @babel/core and @babel/plugin-transform-runtime

npm install -D @babel/core @babel/plugin-transform-runtime

then create a .babelrc file in the project root folder telling your project to use one of the babel transform runtime plugins that will transpile the ES7 to what your browser can understand. use below snippet.

{
  "plugins": ["@babel/plugin-transform-runtime"]
}

Demo result below demo.PNG

Bundling your application for production.

After the development of your project, you will want to deploy your application to production, that's one of the main purposes of using Parcel is minified and reduce your project files size. you can run your build command you set in your script section

npm run build

Conclusion.

The main purpose of this article is to introduce you to ParcelJs and get you started with ParcelJs, with this article you will be able to develop and deploy any javascript project to production. parcel js helps to bundle your app into small size You can find the demo for this project on Codesandbox and the source on Github.

NB:, if you have any questions or any part is not clear. you can drop it in the comment box. I'm always at your service.

No Comments Yet