Bootstrapping a React library with Parcel Bundler
Tags: parcel, react, github, webpack
Published: 2018-09-20 17:48:28

---
cover_image: https://i.imgur.com/sg1NSrl.jpg?1
title: Bootstrapping a React library with Parcel Bundler
published: true
description: A guide from my experience ditching webpack
tags: parcel, react, github, webpack
---

##### *Photo by Jøn on Unsplash*

Often while working on a project I get to create some neat components that I would like to re-use in the future and keep it in a presentable repo for anyone interested. Most of these side-projects end up in a repo graveyard or not even get split from their original project. Configuring webpack and babel to transpile and expose a UMD module and a demo page can be a daunting task. Although Webpack 4 has introduced config-less operation, today I want to share my experience with [Parcel-bundler](https://parceljs.org/).

Parcel runs config-less by default, and it is a very fast and flexible bundler that works seamlessly with Babel 7. I want to show you how easy it is to achieve that painless library setup.

## Folder Structure

First, we need to create our root folder with the name of our project and initialize it with yarn (or NPM if that's what you're into).

``` 
mkdir my-awesome-component 
cd my-awesome-component
yarn init
```

Once the folder has been initialized we need to add a couple of things 

```bash

mkdir lib
mkdir example/src
```


These folders will hold both our source code and the example we're going to write.
These are not the only folders we are going to work with but for now, this is all we need.

## Dependencies

I'm only going to talk about the general dependencies you would need to accomplish an environment that provides most of the functionality you get from [CRA](https://github.com/facebook/create-react-app) with a minimal setup using babel 7 and Parcel. 

_NOTE: At the time writing this Parcel 1.10 is in beta, so I'll be using the beta since the current stable build does not support babel 7._

On the most basic level, we need babel to: transpile to ES5, polyfill generators, and support the [object-spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax). We are also going to add parcel as our bundler.

```bash
 yarn add --dev @babel/cli @babel/core @babel/plugin-proposal-object-rest-spread @babel/plugin-transform-regenerator @babel/plugin-transform-runtime parcel-bundler@^1.10
```

If you use [lodash.js](https://lodash.com) or [moment.js](https://momentjs.com) you may want to add the babel plugins to shave off those extra KBs from your bundle as well.


Since we are talking about React in here, I'm going to add the obligatory dependencies. Note that _react-dom_ is added to be used in our demo and not necessarily on our library.

```bash
yarn add react react-dom prop-types
```

## Configuring Babel 7

Parcel provides a default babel config and it will do most of the things for you. However, you can define your own _.babelrc_ and Parcel will pick it up and add it to their config. Parcel will automatically add some presets like *env* and *react* so we don't need to set that up if you check the babel dependencies we didn't even need to include a preset, so we are here just to set up our plugins. I'm using atom, feel free to use your favorite editor!

```bash
 atom .babelrc
```

then add

```javascript
{
  "plugins": [
    "@babel/transform-runtime",
    "@babel/transform-regenerator",
    "@babel/proposal-object-rest-spread"
  ]
}
```

and that was it for Babel!

## The Scripts

Now the fun part begins. We need to set up the scripts that are going to bring our project to life! open your *package.json* and head to the *scripts* section.

```bash
 atom package.json
```

We need a *start* script that watches our source for changes and compiles it live to */dist* (or however you want to call it I'm going for the default).

We need a *build* script that compiles and minifies our bundle and makes it ready for shipping.

we need a *start-demo* script which watches the source of our example in *examples/src*

We need a *build-demo* so our demo can also be bundled and get ready to be served on [github pages](https://pages.github.com/)

We also need a *publish-demo* script so we can push the bundle to GitHub.


```javascript
{
  "start": "parcel watch lib/index.js",
  "build": "parcel build lib/index.js --global my-awesome-component",
  "start-demo": "parcel example/src/index.html --out-dir examples/dist --open",
  "build-demo": "parcel build example/src/index.html --out-dir examples/dist --public-url ./",
  "publish-demo": "gh-pages -d examples/dist",
}
```

_NOTE: the **--global** option denotes the UMD package name, so you need to provide the name your NPM package is going to have. Also, make sure your examples' **index.html** has a script tag referencing your **index.jsx** and parcel will take care of the rest_

## Extra

Source maps are generated by default using Parcel, and they can be a powerful tool to analyze and optimize your bundle size. Let's take advantage of them.


[Source-map-explorer](https://github.com/danvk/source-map-explorer) is a CLI that generates a report based on your existing source maps, we are going to use this tool to generate a visual representation of our bundle.

```bash
 yarn add --dev source-map-explorer
```

now let´s add a script to generate the HTML representation of our source map.

```javascript
"view-source-map": "source-map-explorer --html dist/index.js dist/index.map > source.html && open source.html" 
```

now you can open *source.html* on your browser and figure out where you can shave off those extra KBs.

_NOTE: If you are running windows you need to remove **open** to launch the generated html to your default browser_

## Conclusion

With the configuration we've discussed here, you can throw in something you cooked up in CRA with minimal changes and publish it as its own library with a nice demo hosted on GitHub pages. I hope this can encourage other devs to start using parcel and get their ideas published faster. Thanks for reading if you got this far, please leave a comment to share your thoughts!