Bundling React applications with minimal configuration and full control

- 6 min read

When you want fast transpiling, straight forward configuration, and total control of your React environment, Parcel is a great fit.

The commands in this post assume you have Node.js installed and available on your system.

Why

For me to adequately explain why you may want to adopt Parcel, I must explain why the go-to alternatives didn’t work for my team. If you already know why you want to use Parcel, jump down to the implementation steps.

Why not use Create React App

Create React App is a fantastic tool for getting started with React. The framework is opinionated and well documented. Unfortunately if you want any of the following it simply won’t work (without ejecting):

  • Server side rendering for SEO/accessibility
  • Running at a path other than a domain root with a like production dev environment
  • Having additional routes for your web application outside of React

If you eject from Create React App (a one-way operation) to support any of these needs, you’re left with the Webpack configuration…

Why not use Webpack

Like Create React App, I am a huge fan of Webpack, I’ve been proudly and happily using it since v1. Unfortunately I repeatedly run into the same type of issues over and over:

  • Around the time of major versions of Webpack being released I have enormous difficulty configuring my applications for the new version. Plugins and presets that are needed are in various states of support for the new version of Webpack and finding documentation is rough.
  • The barrier to entry is enormous! As a long time user I can’t overstate this enough. I’ve interviewed a lot of frontend candidates and not one of them has been able to configure a build configuration in Webpack.

For my team, replacing Webpack with something that requires less work, complexity, and attention is extremely desirable (so I don’t spend all of my days editing Webpack config for the team).

While Parcel uses the same transpilers that you need with Webpack, Parcel works without it’s own set of configuration. So there’s not confusion about whether to use .babelrc or whether to put the configuration in Webpack’s config.

Lastly, from my anecdotal use (at time of writing), Parcel appears to be much faster to start.

Setting up Parcel

Before you proceed please ensure you have a package.json file, if not run npm init and follow the prompts.

Dependencies

If you’ll eventually expand your application to use React on the server in production you’ll need to install react and react-dom as production dependencies. If you don’t plan to use them in production you may choose to install them as dev dependencies instead.

For security, it’s always best to limit the code deployed to production to the code code needed to run the application.

To install react and react-dom run:

npm install --save react react-dom

Dev Dependencies

In your dev environment, you’ll need:

  • parcel-bundler - Parcel itself to bundle your application
  • @babel/core - To support transpiling of JavaScript applications
  • @babel/plugin-proposal-class-properties - An optional plugin that allows use of class properties, this allows you to greatly simplify your React class base components and will be used in code samples in the rest of this guide
  • @babel/preset-env - Handles syntax transforms and some browser polyfills to allow your application to work for less advanced browsers
  • @babel/preset-react - Transforms JSX syntax to JavaScript

To install these dependencies, run:

npm install --save-dev \
    parcel-bundler \
    @babel/core \
    @babel/plugin-proposal-class-properties \
    @babel/preset-env \
    @babel/preset-react

Configure Babel

Tell Babel which presets/plugins to run by creating a .babelrc file in the root of your project (in the same directory as your package.json) with this content:

{
  "presets": ["@babel/preset-env", "@babel/preset-react"],
  "plugins": ["@babel/plugin-proposal-class-properties"]
}

Seriously, that’s it.

Configure browserslist

Next to the .babelrc file you created, create a .browserslistrc file to contain definitions of your supported browsers.

This configuration is what @babel/preset-env will read for transforming your code, see browserslist’s project page for details.

I’ve provided a sample configuration below:

# Browsers that we support

>0.2%
not dead
not ie < 11
not op_mini all

Create the foundation for your React application

Create the entry point

The most straight forward way to build a React application with Parcel is to start with an html file (Parcel will load and transpile resources referenced within HTML files!).

To get started, create a file named src/index.html (you’ll need to create the src dir in your project root):

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Your title</title>
</head>
<body>
<div id="root"></div>
<script src="./index.js"></script>
</html>

Note, change lang="en" to whatever your language is.

If you already have a React application, make sure that ./index.js above points to the JS file that attaches React to your DOM element, then skip the next few steps and move on to running Parcel.

Create the script to attach React

Create a file at src/index.js — Parcel loads this file from your src/index.html’s <script src="./index.js"></script> tag):

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

// Assuming you have CSS for index, you can import it by uncommenting the
// following import:
//
// import "./index.css"

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

Create your first React component

In the prior step, we import “./App” now you’ll need to create it at src/App.js:

import React, { Component } from "react";

// If you have CSS for your App component you can import it by uncommenting the
// following import:
//
// import "./App.css"

class App extends Component {
    render() {
        return <div>This is your App component</div>;
    }
}

export default App;

Run and develop your application

Your application is now ready to run and to start developing by running Parcel using the npx command. The npx command is a helper to run executable files from the ./node_modules/.bin/ directory.

npx parcel src/index.html

If you don’t want to use npx you can run the script directly (npx is a helper so that you don’t have to do this):

./node_modules/.bin/parcel src/index.html

Package your application for production

When you’re ready to package your application for production, run Parcel with the build argument before your entrypoint:

npx parcel build src/index.html

Or without npx:

./node_modules/.bin/parcel build src/index.html

Parcel will output the files created for production like this:

✨  Built in 2.62s.

dist/src.7c2c1974.map    226.57 KB     35ms
dist/src.7c2c1974.js     111.65 KB    2.18s
dist/index.html              147 B    361ms

Where to go from here

If you are just learning React, visit the official getting started guide, it really is a fantastic resource.

If you want more control over your environment:

  • See the Parcel CLI documentation
  • You are also able to invoke Parcel through a Node.js application instead of the command line tool. For documentation on how to do this see the Parcel API.

In a future post I’ll share an example of an application I created using React and Parcel that provides:

  • Server side rendering of React
  • Bundling of the client side application with React.hydrate
  • Bundles the server side React application with whatever custom server routes/middleware desired
  • Listens for file changes to invoke rebundles
  • Runs a dev server with a socket to notify the browser to page refresh
  • Bundles the production application

Author

Cody Craven enjoys sharing tidbits of information that he learns through his life-long journey developing websites and configuring web servers.

When at work, Cody can often be found banging his head against his keyboard for hours days weeks-on-end trying to solve technical issues that would otherwise prevent his teammates from creating Member value at AAA.

All content that Cody contributes to this site are his own ideas and do not necessarily represent AAA's positions or opinions.