Engineering

How to Create a React Project from Scratch

Even though create-react-app is one of the most used tools for starting React projects, we don’t see most of the configuration that we need to do for it. When we need to modify that config, we are not sure how to do it.

Even though create-react-app is one of the most used tools for starting React projects, we don’t see most of the configuration that we need to do for it. When we need to modify that config, we are not sure how to do it. This tutorial will walk you through the process for a high-level React project (with tests, linter, and best-practices). My hope is that after reading, you’ll have a better understanding of what’s needed to create a react app, and modify your create-react-app configuration or legacy projects. The app that we are going to create will have the following features:

  • Uses Babel for transpiling ES6 code into ES5 javascript.
  • Uses a post-css processor like sass.
  • Handles images and svgs, creating a links for referencing them.
  • Uses a linter for keeping a consistent code style.
  • Has a basic setup for using Jest for tests.
  • Bonus: Uses TypeScript.

Prerequisites

  • Node, you can download and install it from here. Go for the LTS (Long Terms Support) version if you don’t have it installed yet. If you already have a different node version, I advise you to use tools like NVM, so you can manage node versions (and use LTS for this tutorial).
  • npm is the default package manager. You can use it for the tutorial, just change yarn for npm. If you want to install yarn, you can do it by running yarn install in your terminal.

Creating the project and adding dependencies

First, we must create our package.json file. We can do that with npm init, or yarn init. I’ll go for yarn, as I think it’s faster for installing dependencies and uses emojis.

 

yarn init

 

Yarn will ask some questions before creating the file. We can hit enter for using the default values, or type what we want to change. I’m setting this project as private, as I won’t publish it to production. It’s better to change that flag to Yes when we want to publish as we’ll see most of npm’s warnings about unpublished dependencies.

 

question name (react_template):
question version (1.0.0):
question description: React template
question entry point (index.js):
question repository url (https://github.com/timgivois/react_template):
question author: Tim Givois
question license (MIT):
question private: y


First, we’ll add Babel 7 to the project, and the presets that we’ll need for ES6 and JSX.

 

yarn add @babel/core @babel/preset-react @babel/preset-env


After we installed Babel, we may need to add basic configuration for it in .babelrc file (in our root folder)

 

// .babelrc
{

"presets": ["@babel/preset-react", "@babel/preset-env"]

}

 

Now that we have our transpiler for JavaScript ES7 and React, we are able to add webpack. It’s a module bundler that will basically create a dependency graph in the project and spit a packaged javascript file that we’ll attach to our index html.


yarn install webpack webpack-cli babel-loader webpack-dev-server html-webpack-plugin


We installed webpack and some dependencies we’ll need for building our React app. Babel-loader is basically a bridge between webpack and Babel and webpack dev server is a helpful plugin for creating dev bundles quickly.

Configuring webpack

As we made with Babel, we need to create a configuration file. In most of the mature projects I’ve seen, more than one webpack configuration is needed (for dev and for production). This is because production bundles are normally optimized bundles that are hard to read and dev bundles can be read by developers. The following code snipper was created in the root folder with the name webpack.config.js

Basic webpack config with jsx and css loaders


I added the following files to the project (as you may deduct from the webpack configuration).



In root folder, add a index.html file.
This file is saved in a src/ folder.

This file is saved in a src/ too.

This is our entry file, it’s located in the root folder.


And now, we need to update our package.json scripts:


"scripts": {
   "start": "webpack-dev-server --hot --open",
   "build": "webpack --config webpack.config.js --mode production"
 }


If you run npm, run build, or yarn build, you’ll see that there’s a production bundle made in dist folder. If you run npm, run start, or yarn start, a server will be created for serving our files. The ‘hot’ flag indicates that the bundle will be autogenerated after we change something in our app. ‘Open’ flag will automatically open a browser tab in localhost:8080 which is the default webpack dev host and port.

And, VOILÁ! we got a React app with minimal configuration. From now on, we’ll be adding features (post-css, lint rules, image loading, jest setup and finally typescript).

Adding a postcss loader to webpack

We are going to add sass loader to our configuration. To do so, we just need to add the deps.


yarn add --dev sass-loader node-sass

 

Modify the css loader we already have

Add a sass file in your src folder.

App.scss file located in src.

Modify the import you had, changing App.css to App.scss in your App.jsx.


You should see the image below when running yarn start.


What about file images? We can add a webpack configuration for that too. First, we need to install ‘file-loader’ running:


yarn add --dev file-loader

 


Add TypeScript to the project

The first thing you have to do is install typescript and its webpack loader.


yarn add --dev typescript ts-loader source-map-loader

 

Add the following configuration for your TypeScript project:

Add tsconfig.json to your root folder

Now, you should just need to add the loader and rename App.jsx to App.tsx.

Add these lines before the Babel loader we have

Don’t forget to add react types to the project:

 

yarn add --dev @types/react @types/react-dom


Now, we can rewrite our HelloWorld app. This is a good start, for developing our application. But we need to first add linters, jest and dotenv imports.


Using assets and images may lead to some Cannot find module errors, you can fix them by adding the following file:

 

Save this index.d.ts file in your root folder

Add a linter for the project

Another nice-to-have in projects are the linters. While more people work in it, there are different styles of writing code. Some may prefer to use single quotes for strings and some others love to use the semicolon. Linters are the tool for keeping a consisting style in your code. We’ll see how we can setup StandardJS with TS.


yarn add --dev @typescript-eslint/parser @typescript-eslint/eslint-plugin


Modify your package.json adding standard script and its basic config:


"scripts": {
   "start": "webpack-dev-server --hot --open",
   "build": "webpack --config webpack.config.js --mode production",
   "lint": "standard src/**/*.tsx src/**/*.ts src/**/*.jsx src/**/*.js"
 },
 "standard": {
   "parser": "@typescript-eslint/parser",
   "plugins": [
     "@typescript-eslint/eslint-plugin"
   ]
 }

 

One of the awesome things is that we can automatically fix the style differences with StandardJS:


yarn lint --fix

 

Adding Jest to the project

Now that we have fixed our lint problems, we’ll add configuration for jest so we can have tests. Let’s start by installing jest and enzyme:

 

yarn add --dev jest enzyme enzyme-adapter-react-16 @types/jest ts-jest @types/enzyme babel-jest identity-obj-proxy


Add the following jest config file:

jest.config.json file which is in your root folder

Now, as you may suspect. We need to create the setup adapter for enzyme. Add the following ES5 file in your root folder:

setupEnzyme.js which is in your root folder

To see if it’s working, we may add our very first test.

Add this file in src/ folder. Remember to save it with .test.tsx extension

Congrats, you made it. Now, we can start to actually create our React app. We now control and understand all the configs that are in the project.

 

Tim Givois, Software Engineer at Wizeline
Tim Givois, Software Engineer at Wizeline

Nellie Luna

Posted by Nellie Luna on August 6, 2019