How to Setup a React App with TypeScript + Webpack from Scratch
Tags: blog, react, typescript, webpack
Published: 2022-06-07 01:37:08

Have you ever created a React application using [Create React App](https://create-react-app.dev/) but was then curious about how it was configured under the hood? Do you want to use React with TypeScript, but have had a hard time finding all the setup instructions in one place? Do you prefer to avoid [Babel](https://babeljs.io/) for bundling or transpiling or want a more modern option like [Webpack](webpack.js.org/)? This guide walks you through how to setup a React application with TypeScript-written components and bundled with Webpack. Bonus: It also teaches you how to configure Jest for testing.

## 🙋🏽 Why?
While [Create React App](https://create-react-app.dev/) is a great way to jump start a simple project, it unfortunately abstracts away most of the configuration in order to streamline the setup process. Should you ever want to customize a particular project configuration or be more aware of installed dependencies, you'll have to manually wade through all of the pre-build configuration files and inspect each setting to learn what is required and what is optional. [Create React App](https://create-react-app.dev/) even hints at this on their homepage.

> If you ever want an advanced configuration, you can ”eject” from Create React App and edit their config files directly.

While this is taunted as a "feature", it makes it more likely that developers will keep using the de facto [Create React App](https://create-react-app.dev/) tech stack and not make conscious decisions on what frameworks and libraries work best for the project requirements.
 
Understanding how a React application is built from the ground up provides the developer the expertise to know when to use a cookie cutter template and when to forge their own path.

## 🧱 How?

> **NOTE**: The final React project template is available on [GitHub](https://github.com/cloud-city-crafted/react-typescript-webpack-template).

This guide assumes that you have [`git`](https://git-scm.com/), a Node package manager (e.g. [`npm`](https://www.npmjs.com/), [`yarn`](https://yarnpkg.com/)), your favorite IDE (e.g. [VSCode](https://code.visualstudio.com/), [WebStorm](https://www.jetbrains.com/webstorm/)), and the ability to run commands in a *nix-like terminal.

Each step shows an example file to use as a starting point. `<PLACEHOLDERS>` are used in the examples to highlight values that needs to be updated with information specific to the project.

### 1. Initialize Project

Let's start off by creating the initial project files. This will get the project ready for version control (e.g. GitHub) and dependency management (e.g. `npm`). 

> The [Initialize Project Template PR](https://github.com/cloud-city-crafted/react-typescript-webpack-template/pull/1/files) shows the suggested state after completing these steps.

1. Create a new directory for your React application (e.g. `my-react-app`)
1. Initialize a `git` repository to start the `git` history.
    ```shell
    git init
    ```
1. Add a `.gitignore` file to the project root to keep common Node project files from being included in the repository.

    {% embed https://gist.github.com/TheLandolorien/cb17e14012ed691a802345b4f9b26afc %}

1. Add a `README.md` file to the project root.

    {% embed https://gist.github.com/TheLandolorien/3a697d8ef32e623ddcd34f398a070ee3 %}

1. Use https://choosealicense.com to select the appropriate license and add its contents to a `LICENSE` file in the project root. 
1. Add a `package.json` file to the project root to initial the npm project.

    {% embed https://gist.github.com/TheLandolorien/3e2cdf5bb79f83f9ed9b406c19c47461 %}
    - `<PROJECT_NAME>`: A string that typically matches the name of the GitHub repository. See limitations for that value in [package.json docs > name](https://docs.npmjs.com/cli/v8/configuring-npm/package-json#name)
    - `<PROJECT_DESCRIPTION>`: A string that concisely describes what your project is or does.
    - `<GITHUB_USERNAME>`: The GitHub username or organization that will own the project's repository.
    - `<*_KEYWORD>`: Strings to make your project more discoverable. They can be the same as the GitHub topics you apply to the repository.
    - `<DEVELOPER_NAME>`: The person or organization writing the code
    - `<LICENSE_TYPE>`: The type of license to apply to this project.

1. (Optional) Add any versioning files (e.g. `.nvmrc`) or linting configuration files (e.g. `.prettierrc`) for easier development on other machines.

Be sure to check out [Take Your Github Repository To The Next Level](https://dev.to/eludadev/take-your-github-repository-to-the-next-level-17ge). The sections on discoverability, naming, writing descriptions and choosing the right license should help you choose appropriate values for these placeholders for this and future projects.

### 2. Setup TypeScript

> The [Setup TypeScript PR](https://github.com/cloud-city-crafted/react-typescript-webpack-template/pull/2/files) shows the suggested state after completing these steps.

1. Install the TypeScript dependencies required for coding in TypeScript.
    ```shell
    npm install --save-dev typescript ts-node @types/node
    ```
1. Add a `tsconfig.json` file to add type checking and support for compiling TypeScript React components and utilities.

    {% embed https://gist.github.com/TheLandolorien/6820292db505ef116f29ae5e8a0784be %}

With TypeScript configured, we are ready to add our first React components.

### 3. Setup React

> The [Setup React PR](https://github.com/cloud-city-crafted/react-typescript-webpack-template/pull/3/files) shows the suggested state after completing these steps.

1. Install the React dependencies required for building React components with TypeScript.
    ```shell
    npm install react react-dom
    npm install --save-dev @types/react @types/react-dom
    ```
1. Create the `src` directory in the project root to store the source code.
1. Download all the `src` files from the [Setup React PR](https://github.com/cloud-city-crafted/react-typescript-webpack-template/pull/3/files) to get the source code for a basic React app.

We now have a sample React app, ready for unit testing.

### 4. Setup Jest

> The [Setup Jest PR](https://github.com/cloud-city-crafted/react-typescript-webpack-template/pull/4/files) shows the suggested state after completing these steps.

1. Install the Jest dependencies required to test TypeScript React components.
    ```shell
    npm install --save-dev jest ts-jest jest-environment-jsdom @types/jest @testing-library/jest-dom @testing-library/react
    ```
1. Add the `jest.config.js` file to let Jest know where to locate test files and what the coverage requirements are.

    {% embed https://gist.github.com/TheLandolorien/0c2fb8d7b4fc055af450bdff0c56bed5 %}

1. Add the `src/__mocks__/fileMock.ts` file to load file imports during tests.

    {% embed https://gist.github.com/TheLandolorien/08c883604d65d365fb5e83cd2d4bac7d %}

1. Add the `src/__mocks__/styleMock.ts` file to load style imports during tests.

    {% embed https://gist.github.com/TheLandolorien/59fcc9509b3e0d2cb90ef4e20b77cacf %}

1. Add the `src/setupTests.ts` file to support DOM simulation during tests.

    {% embed https://gist.github.com/TheLandolorien/828fa4ed5e6c4fdc9d1df9aa1e8a60b8 %}

1. Add a `scripts` attribute to `package.json` to run `jest` commands in your local terminal.
    ```json
    "scripts": {
      "test": "jest",
      "test:watch": "jest --watch",
      "test:coverage": "jest --coverage"
    },
    ```
1. Download all `src/__tests__` files from the [Setup Jest PR](https://github.com/cloud-city-crafted/react-typescript-webpack-template/pull/4/files).
1. Run the test commands to ensure all tests are passing and all code has test coverage.
    ```shell
    npm run test # Run the full test suite once
    npm run test:watch # Watch files for changes and rerun tests related to changed files
    npm run test:coverage # Generate and display a test coverage report
    ```

Even though we cannot view the components in a browser yet, we can simulate a DOM during tests and verify content rendering. We'll need a bundler to transpile our app into something a browser can display.

### 5. Setup Webpack

> The [Setup Webpack PR](https://github.com/cloud-city-crafted/react-typescript-webpack-template/pull/5/files) shows the suggested state after completing these steps.

1. Install the Webpack dependencies required to serve files locally and bundle for production deployment.
    ```shell
    npm install --save-dev webpack webpack-cli webpack-dev-server style-loader css-loader ts-loader html-webpack-plugin copy-webpack-plugin webpack-merge
    ```
1. Add additional commands to the `scripts` attribute to `package.json` to run `webpack` commands in your local terminal.
    ```json
    "scripts": {
      "build": "webpack --config webpack.production.js",
      "start": "webpack serve --config webpack.development.js",
      "test": "jest", # <-- Already in file from last step
    },
    ```
1. Add a `webpack.common.js` file to detail the shared configuration process in all environments.

    {% embed https://gist.github.com/TheLandolorien/cdca2c21184f6d73997bb002fdd7453b %}

1. Add a `webpack.development.js` file to detail the configuration process a development environment.

    {% embed https://gist.github.com/TheLandolorien/60f2c0fe2cd497f9bda4f689e7f85beb %}

1. Add a `webpack.production.js` file to detail the configuration process for a production environment.

    {% embed https://gist.github.com/TheLandolorien/d50be0da98aa85f0b072806c1fcfb769 %}

1. Run the development commands to ensure the project can be served locally and bundled for production.
    ```shell
    npm run start # Start a local development web server at http://localhost:8080 using webpack-dev-server
    npm run build # Bundle application for Production using webpack
    ```

Now you can make changes to the components' source code and view content locally in a browser. And once bundled, the app is ready for deployment to a remote server.

### 6. (Optional) Setup Tailwind CSS

> The [(Optional) Setup Tailwind CSS PR](https://github.com/cloud-city-crafted/react-typescript-webpack-template/pull/6/files) shows the suggested state after completing these steps.

1. Install the Tailwind CSS dependencies required to import its utility styles and integrate with Webpack.
    ```shell
    npm install --save-dev tailwindcss @types/tailwindcss postcss postcss-loader autoprefixer
    ```
1.  Add a `postcss.config.js` file to specify which PostCSS plugins to use.

    {% embed https://gist.github.com/TheLandolorien/0555c3cfa18c7f0fd4912903c947eb79 %}

1. Add a `tailwind.config.js` file to specify the project files.

    {% embed https://gist.github.com/TheLandolorien/55c8028cf242367eac0561cad8b8ca21 %}

1. Add the `postcss` loader to the list of CSS rules in `webpack.common.js`, after the existing `style` and `css` loaders.

    ```javascript
    {
      test: /\.css$/i,
      use: ['style-loader', 'css-loader', 'postcss-loader'],
    },
    ```

1. Add the Tailwind directives to `index.css` to inject Tailwind styles.
    ```css
    @tailwind base;
    @tailwind components;
    @tailwind utilities;
    ```

From here you can either create new components using Tailwind classes or migrate existing styles into the Tailwind framework. See the [CSS file changes](https://github.com/cloud-city-crafted/react-typescript-webpack-template/pull/6/files#diff-e269447b167c1d69748b9d5ccde405e2fb2d74af0d1832d5c05e63362816722d) in the (Optional) Setup Tailwind CSS PR for an example of a style migration.

## Summary

With TypeScript, Jest, and Webpack configured and React installed the project should be in a state equivalent to running [`npx create-react-app`](https://create-react-app.dev/).

More specifically, you should be able to:

  - Develop React Components using TypeScript (using .tsx files)
  - Test React Components using Jest
  - Bundle a React Web Application for Production
  - Serve a React Web Application locally with automatic reloads on save
  - (Optional) Build custom design systems using Tailwind CSS utility classes

Be sure to check out the [detailed tooling list](https://github.com/cloud-city-crafted/react-typescript-webpack-template#-tooling) for more information about the tech stack and dependencies used for this project template.