Building a basic website with Parcel
Tags: html, css, javascript, opensource
Published: 2020-10-15 22:38:42

---
title: Building a basic website with Parcel
published: true
description: Let's build a small website that can import libraries with Parcel.
tags: ['html, css, javascript, opensource']
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/rsvehfkjtqx1usrzqbex.jpg
---

You want to build a tiny website with just HTML, CSS, and JavaScript. You don't want to import a ton of libraries or use a framework that performs ultra enhanced low latency rendering under the hood.
You want a website that has some styling, maybe makes a request to an API, and that you can build, manage, and deploy simply.
So let's build that.

Here's a video version of this post if you'd rather watch us build the website:
{% youtube U_1O9YY75FA %}

## A basic website

First, let's set the foundation with technically the only 3 files you need to make up a website.

Let's pull up our command line and navigate to where we'd like to create our new project.

Then we'll create the directory:

```plain-text
mkdir awesome-site
cd awesome-site
```

Now we can create three files:

```plain-text
touch index.html
touch main.css
touch main.js
```

And let's fill in our files like so:

### index.html

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Example</title>
    <link rel="stylesheet" type="text/css" href="main.css" />
  </head>
  <body>
    <h1>Hello from HTML!</h1>

    <script src="main.js"></script>
  </body>
</html>
```

### main.css

```css
h1 {
  color: magenta;
}
```

### main.js

```jsx
console.log('Hello from JavaScript!');
```

Now if we open `index.html` we will see `Hello from HTML!` in magenta and that's it, we have a website.

At this point, we have the bare minimum, but we want to continue to add features to our website. To help with that we want to use other developer's libraries.

So, how can we import a library that we can use in our website?

## Importing a library

There are plenty of ways you can import a library. You can directly download a JavaScript file and add it the same way we are using `main.js`, you can include the JavaScript file from a CDN in your HTML, and you can setup a package manager.

We're going to look at setting up a package manager called NPM (Node Package Manager) because this will automatically download the necessary files as well as help manage dependencies going forward.

Let's setup NPM in our repo

```plain-text
npm init -y
```

Running this command we are creating a `package.json` file with default values.

Now we will install a package called moment.js a library that helps with date formatting.

```plain-text
npm install moment
```

If we look at our `package.json` file now we will see that moment has been added to our dependencies

```json
{
  "name": "awesome-site",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "moment": "^2.29.0"
  }
}
```

To use moment first we'll need to include the `moment.min.js` file using a script tag in our `index.html`

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Example</title>
    <link rel="stylesheet" type="text/css" href="main.css" />
  </head>
  <body>
    <h1>Hello from HTML!</h1>

    <script src="node_modules/moment/min/moment.min.js"></script>
    <script src="main.js"></script>
  </body>
</html>
```

Notice that we are adding `moment.min.js` above where we include `main.js`. This way we will load moment before we use the library in `main.js`.

Lets start using moment by changing `main.js`

```jsx
const now = moment().format('MMMM Do YYYY, h:mm:ss a');

console.log(now); // September 30th 2020, 8:20:12 pm <- The time I am actually writing this
```

When you open `index.html` moment will be loaded and the current time will be logged in the format defined above.

But wait, is there more we can do?

## Using a bundler

JavaScript does not provide a way to import code from one file to another. Right now when we want to import and use a library we have to include the JavaScript file from `node_modules` with an exact path to the entry point file for the library inside our HTML. When we include the library in our HTML the JavaScript file is loaded into our HTML and will be defined as a global variable for files loaded after to use.

Not only is this inefficient but we'll also have a bug if we don't add our script tag in our HTML or if we have our tags in the incorrect order.

So what's the alternative?

We're using NPM right now which is the package manager for node.js. Node.js implements CommonJS modules which allow JavaScript to import and export code across files.

This is what our previous example looks like using node.js modules, Instead of including the moment library in our HTML with an HTML script tag we can load the library in our `main.js` file:

```jsx
const moment = require('moment');

const now = moment().format('MMMM Do YYYY, h:mm:ss a');

console.log(now);
```

This looks great but if we try to use this right now we will get this error:

`Uncaught ReferenceError: require is not defined`

The browser does not have access to the file system which means loading files is tricky.

To fix this error and be able to access the file system we need a _module bundler._ A JavaScript module bundler is a tool that will create an output of your files that is browser compatible. A module bundler will find all the `require` statements and replace them with the context of each required file.

It's awesome but can be complicated. So let's use a tool that takes every complication out of the equation.

Enter _Parcel._

## Parcel

Parcel is a web application bundler that is going to handle a bunch of things for us that previously we would have to set up ourselves.

Parcel will bundle all our JS, CSS, HTML, file assets, etc into a smaller set of files we can use to run our code. During the bundling Parcel will also transform our files so we can use the `require` or even the `import` syntax.

[Parcel has other features you should check out too](https://parceljs.org/)

Let's install Parcel in our project

```plain-text
npm install parcel-bundler --save-dev
```

This will add the `parcel-builder` module as a _dev dependency_ which is a module that is only required during development.

Now we'll add two scripts to our `package.json`

```json
{
  "name": "awesome-site",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "dev": "parcel index.html",
    "build": "parcel build index.html --public-url ./"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "moment": "^2.29.0"
  },
  "devDependencies": {
    "parcel-bundler": "^1.12.4"
  }
}
```

The `dev` script we added uses the `parcel` command and an entry file. This will be used during development and starts a server for us to use with hot-reloading.

The `build` script uses `parcel build` which will build the website to a `/dist` folder which is where our site will be served from when we deploy it.

## Bringing it all together

Now that we have Parcel set up we can use the `require` statement in our `main.js` file.

Our `main.js` file will look like this now:

```jsx
const moment = require('moment');

// The newer import statement will also work
// import moment from 'moment'

const now = moment().format('MMMM Do YYYY, h:mm:ss a');

console.log(now);
```

And we can exclude the moment script tag from our HTML:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Example</title>
    <link rel="stylesheet" type="text/css" href="main.css" />
  </head>
  <body>
    <h1>Hello from HTML!</h1>
    <script src="main.js"></script>
  </body>
</html>
```

We can now run our dev script `npm run dev` and open [http://localhost:1234](http://localhost:1234/) we will see our website and if we have the console open we will see the current time logged as well!

(Also try updating any of the HTML, CSS, or JS and you'll see that the website will reload automatically)

## Wrapping up

Our small website is all set up and ready for us to host the code on our service of choice (GitHub, GitLab, Bitbucket, Etc) and to deploy the site to the world.

Take this starting point and use it as a testing ground for your next project. Some other interesting extensions to this project would be to add PostCSS, use Sass, as well as add various ways to deploy.

## Resources

[Parcel](https://parceljs.org/)

[NPM](https://www.npmjs.com/)

[Moment.js](https://momentjs.com/)

[More robust example code](https://github.com/themisterholliday/what-time-is-it)