📝Project Setup

This guide is to help understand what goes on under the hood of CRA application, and to grasp how the tools like Webpack and Babel work in tandem with React and Typescript.

Motivation

I had fun with create-react-app, with the no-worries setup it provides to dive right into the action of writing React components, but now it's time we get our hands dirty with the configuration that create-react-app does for us under the hood. This is basically to understand the basic concepts of how tools like Webpack and Babel help us developers in writing better code, with the latest ECMAScript standards, while also ensuring that older browsers that do not support these latest standards, also work for the code that we write.

P.S. This is a really long article, stick till then end, it's going to be worth the effort! All the code for this guide is available on Github.

1. Base setup

Let's start by creating a folder and initializing git and yarn, plus we'll also add two folders, src and public, which will house our code.

mkdir boilerplate; cd boilerplate
# initialize package.json
yarn init -y;
#  initialize git version control
git init

React dependencies

Let's add the react and react-dom dependencies:

yarn add react react-dom

Typescript & others

Let's add the Typescript and other dev dependencies: [use the -D flag to save as dev dependency]

With these dependencies added, we need to add a new file to the root directory of the app, called tsconfig.json. This file will contain all the configuration required for Typescript in our app.

Babel & others

With the Typescript configuration in place, let's add babel and it's dev dependencies:

Create a new file in the root directory called .babelrc, which will contain the config options for babel.

Base Code

With this basic setup in place, we can now write Typescript JSX, i.e, TSX in our app! But keep in mind, we can only write it, currently it cannot be compiled and displayed on the browser, for which we will need Webpack!

2. Webpack

We need to inject our <script> into the index.html file. We do this by using webpack, which will transpile and bundle our React app into plain Javascript, and inject it into the HTML page in our app.

Webpack & others

Let's add webpack and it's dev dependencies! Also, I'll be using a really cool webpack dashboard to see the status of my compilation and bundling, it's called webpack-dashboard, and is open sourced by FormidableLabs.

With the above tools installed, we will need to create a new "script" in our package.json file, which points to the webpack configuration of our app. But before we start with the webpack configuration, we need to add another package, called babel-loader, which is required to transpile all the .tsx and .jsx files in out app!

Configuration

Let's configure webpack. For this, we need to create a new file called webpack.config.js at the root level directory of our app.

With the configuration done, we need to add the script to the package.json file:

We can finally test our app on the browser! Simply run yarn start in the terminal to see the app working on localhost:3000.

3. Prod and Dev Webpack Configs

It's usually a good idea to split out webpack configuration into different files. We usually 4 webpack config files:

  • webpack.dev.js : This contains the config for the webpack dev server

  • webpack.prod.js: This contains the config for building our app for production

  • webpack.common.js: This contains the configs that are common to both dev & prod

  • webpack.config.js: This 'merges' both dev OR prod config file AND the common config file

Let us setup this structure for our app! We'll create a webpack/ folder in the root directory of our app, and create 3 files in it, viz., webpack.common.js, webpack.dev.js and webpack.prod.js. We would have to change the content of webpack.config.js (which is in the root directory, and not the webpack folder) as well. But first, we need to install a package that merges two webpack configuration files.

With this package installed, we are ready to configure our webpack configuration files!

4. Adding styles

Since there are many options out there to style a React app, we'll be focusing on really the basic tools for styling an app, i.e, CSS, CSS-modules and SASS. These are the most widely used styling tools used and are relatively easy to set up with webpack! We will add different rules for development and production modes.

Installing dev dependencies

Before we start adding rules to webpack config files for styling, we need to install a few loaders that can handle CSS and SASS:

Webpack Configs for Styling

Add typings.d.ts

With these configurations in place, we need to do one final thing, add a new file in the src/ folder called typings.d.ts , which will have the modules declaration in it. Let's add some basic modules that we will declare in this file, and then move on to add configurations for using images and other stuff in our app with webpack!

5. Images and SVGs

All apps require images and SVGs in their code. To bundle such files in our app with webpack, we do not need to install any extra dependencies! Prior to webpack 5 & 4, we had to install the 'file-loader' dependency with other things to use images and SVGs in our app. Now, we need to just use the type property set to asset/resource or asset/inline to use images or SVGs in our app respectively. Not only images and SVGs, we can also use other file with file-extenstions like .gif, .jpg, .jpeg, .woff, .eot, etc.

We will declate these configs in our common webpack config file:

6. Misc Webpack Dependencies

Here are a few common dependencies that are typically used in every production ready application. They are not absolutely necessary to install, but it's recommended that you do, since they are pretty useful!

React Refresh Webpack Plugin

This is a plugin that adds hot reloading to our app.

Dotenv Webpack Plugin

This plugin helps us use environment variables throughout our app, and utilizes the functionality of webpack.DefinePlugin to declare global constants which can be declared at compile time, and therefore helps us hide important information for the source code and the end-user.

With this setup in place, we can define a .env file in our app's root directory and declare global constants that we can define during runtime.

Update package.json

We need to add the scripts to the package.json file from where we can run the webpack server for production or development. We'll add the rimraf package as well, to delete all previous build folders, so as to start a clean build every time we build our app!

7. ESLint

The ESLint package helps use developers write code that is as accurate as possible by pointing our errors as we write our code. Pretty useful feature to have linting in our code to highlight errors and warnings that indicate problems with our code.

A prerequisite for this dependency is that we need to have the ESLint extension installed in VSCode. This extension can be found here.

Now, we have to define the configurations for ESLint in a new file at the app's root directory, called '.eslintrc.js'.

Let's take it to the next level by adding a script to run eslint on our files:

8. Prettier

This is basically a style guide for our code, and helps maintain a standard for writing code for an application. Again, a prerequisite for this to work is we have the Prettier extensions installed on VSCode. This extension can be found here.

To configure prettier, a '.prettierrc.js' file is required at the app's root directory.

We need to modify the .eslintrc.js file a little bit as well:

Time to take it to the next level, by adding a script to run prettier on all our files:

We can also turn on the 'Format on Save' option in VSCode to true, to format our files when we save them.

9. Husky & lint-staged

With Husky and lint-staged packages, we prevent linting and formatting errors to be committed to a common work repository for our app. This help maintain a code standard, and thus prevents accidental errors in our code or formatting of our code to be committed into the repository.

Define lint-staged configs

Define Husky configs

We define the husky config that tells husky to run the lint-staged configurations just before the code is being committed.

10. Nice-to-have(s)

Below are some other configurations for our React + Typescript app that are not necessarily required, but are good to have.

Babel & Runtime

These plugins let us us the async-await features in our application.

We'll update the .babelrc file to incorporate the plugins.

Copy Webpack Plugin

This plugin helps us copy static assets from a source to a destination, typically used to copy the contents of the source folder into the build folder, when the build command is run.

Bundle Analyzer Plugin

This plugin runs when we build our app for production. It loads a webpage that displays all the bundled files and their sizes. Pretty useful feature to use in an app that is being deployed.

Last updated

Was this helpful?