Volver

How to set up a React + Parcel boilerplate project

Diario del capitán, fecha estelar d72.y38/AB

Development React Parcel
How to set up a React + Parcel boilerplate project

Hey, I'm Dani, the JavaScript connoisseur who's written the blog posts about building Node.js APIs (Part One, Part Two) a few weeks ago!

In this post, I want to share how to create the boilerplate to build React applications with parcel.

Since this is a blog post and it might become outdated, I suggest you follow the project on Github. I've created a Gist to Set up a React + Parcel Boilerplate Project for you to keep up with it!

Alright! Let's get into it. This setup includes:

1. Project setup

Let's start from the very beginning:

mkdir my-react-app
cd my-react-app
mkdir src/
git init
echo '# My Awesome React App' > README.md

Then, we will create the project's npm package:

yarn init -y
echo 'node_modules/' > .gitignore

It's likely that we want to set the module as private so as to prevent accidental publishing. Also, we're going to store all the files inside a src folder, so inside package.json write the following:

{
  ...
  "private": true,
  "main": "src/index.js"
}

2. Transpilation with babel

We'll need to transpile the code for two reasons: first, to convert JSX to JavaScript, and second, to convert JavaScript features not supported by our target browsers into more standard JS. These two processes are covered by these two babel-preset packages:

yarn add --dev babel-preset-env babel-preset-react

The babel-preset-env plugin can be configured to for the target browsers we want to support, so it will transpile the code according to the JavaScript features available on those browsers. However, the defaults are ok, for now.

To match the create-react-app babel configuration we need to add a couple of plugins that provides a some transformations not included yet in the env preset:

yarn add --dev babel-plugin-transform-object-rest-spread babel-plugin-transform-class-properties

Finally, we write the babel configuration inside a .babelrc.json file:

{
  "presets": ["env", "react"],
  "plugins": ["transform-class-properties", "transform-object-rest-spread"]
}

3. Linting with eslint

A linter is a program that analyses source code in order to detect possible errors and maintains coherence in the codebase. The babel-eslint package will allow our linter to parse JSX code, and the eslint-plugin-react includes the react related rules:

yarn add --dev eslint babel-eslint eslint-plugin-react

The configuration goes inside .eslintrc.json:

{
  "parser": "babel-eslint",
  "extends": ["eslint:recommended", "plugin:react/recommended"],
  "env": {
    "browser": true,
    "jest": true,
    "es6": true
  }
}

I always like to have a script to detect lint errors (in package.json):

{
  "scripts": {
    ...
    "test:eslint": "eslint src/ --ext .js --ext .jsx"
  }
}

One handy feature of npm scripts is the ability to launch a script before another just by prepending "pre" to the name of the target script. You can run the linter before the "test" with this "pretest" script:

{
  "scripts": {
    ...
    "pretest": "yarn run test:eslint"
  }
}

4. Format code with prettier

We want to make sure, before every commit, that our source files have the same format. This can be done with a combination of prettier, husky and lint-staged:

yarn add --dev lint-staged husky prettier

And then, in package.json:

{
  ...
  "scripts": {
    "precommit": "lint-staged"
  },
  "lint-staged": {
      "*.{js,jsx,json,scss,css,md}": ["prettier --write", "git add"]
  }
}

5. Build and development server with parcel

We're ready to add parcel bundler to the mix:

yarn add --dev parcel-bundler

We need a script to start a development server and another to build our app:

{
  ...
  "scripts": {
    "start": "NODE_ENV=development parcel src/index.html --open",
    "build": "NODE_ENV=production parcel build src/index.html --public-url ./",
    ...
  }
}

Note: this doesn't work on Windows (because of the environment variables). If you need Windows support take a look at cross-env.

If you are planning to deploy the compiled bundle you need to change the public-url parameter to point to the root URL of your app.

Finally, we don't want our compiled app to be on the Git repository:

cat 'build/' >> .gitignore

6. Styles with Sass and CSS autoprefixer

Parcel comes with PostCSS support out-of-the-box. PostCSS can be extended with other languages and preprocessors. Sass is our CSS language of choice, implemented via node-sass. autoprefixer is a popular PostCSS plugin that adds vendor CSS prefixes when required:

yarn add --dev node-sass autoprefixer

Configure it inside package.json:

{
  ...
  "postcss": {
    "modules": false,
    "plugins": {
      "autoprefixer": {
        "browsers": [">1%", "last 4 versions", "Firefox ESR", "not ie < 9"],
        "flexbox": "no-2009"
      }
    }
  },
  ...
}

7. Hot code reloading

Hot code reloading means that the browser will reload automatically the app when the code changes. It's a handy development feature (specially if you have two or more screens):

yarn add --dev react-hot-loader

The react-hot-loader is implemented as a babel plugin, so we need to change .babelrc.json configuration:

{
  "presets": ["env", "react"],
  "plugins": [
    "transform-class-properties",
    "transform-object-rest-spread",
    "react-hot-loader/babel"
  ]
}

Then, we need to change a little bit our source code. Let's suppose our index.js file is like this one:

import React from "react";
import { render } from "react-dom";
import App from "./App";

const root = document.getElementById("root");
render(<App />, el);

To enable hot code reloading we should change the above code for this one:

/* global module */
import React from "react";
import { render } from "react-dom";

const root = document.getElementById("root");

function renderApp() {
  const App = require("./App").default;
  render(<App />, root);
}

renderApp();

if (module.hot) {
  module.hot.accept(renderApp);
}

The first comment tells eslint to treat module as a global object instead of an undefined variable. With the module.hot.accept function we tell react-hot-loader to invoke the renderApp function each time the code changes.

8. Deployment with gh-pages

There are many ways to deploy a serverless app. The quick-and-dirty solution is to use Github Pages (not recommended for production):

yarn add --dev gh-pages

And a couple of scripts:

{
  ...
  "scripts": {
    ...
    "predeploy": "yarn run build",
    "deploy": "gh-pages -d dist",
  }
}

Remember to change the URL of the build script to match the root URL of the app. For example:

{
  ...
  "scripts": {
    ...
    "build": "NODE_ENV=production parcel build src/index.html --public-url https://marsbased.github.io/my-awesome-app/",
  }
}

9. Create your awesome app

Now the hardest thing is missing: coding your own app.

I'd love to know how it goes! Let me know in the comments section below if you need any help and if anything I posted can be explained better or improved. I am always eager to learn from everyone!

Compartir este post

Artículos relacionados

How to build a Node.js API (part one)

How to build a Node.js API (part one)

We want to share with you how we built a Node.js API for a client, describing some patterns and javascript conventions we used.

Leer el artículo
How to build a Node.js API (part two)

How to build a Node.js API (part two)

We want to share with you how we built a Node.js API for a client, describing some patterns and javascript conventions we used.

Leer el artículo
JSBits #0: an introduction to JavaScript modules

JSBits #0: an introduction to JavaScript modules

We have been accumulating a lot of knowledge in JavaScript over the years that we want to share with you in frequent bits, so we'll call this JavaScript Bits!

Leer el artículo