DEV Community

Cover image for How to Setup a React App with TypeScript + Webpack from Scratch
Lando Toothman
Lando Toothman

Posted on • Updated on

How to Setup a React App with TypeScript + Webpack from Scratch

Have you ever created a React application using Create React App 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 for bundling or transpiling or want a more modern option like Webpack? 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 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 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 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.

This guide assumes that you have git, a Node package manager (e.g. npm, yarn), your favorite IDE (e.g. VSCode, 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 shows the suggested state after completing these steps.

  1. Create a new directory for your React application (e.g. my-react-app)
  2. Initialize a git repository to start the git history.

    git init
    
  3. Add a .gitignore file to the project root to keep common Node project files from being included in the repository.

  4. Add a README.md file to the project root.

  5. Use https://choosealicense.com to select the appropriate license and add its contents to a LICENSE file in the project root.

  6. Add a package.json file to the project root to initial the npm project.

    • <PROJECT_NAME>: A string that typically matches the name of the GitHub repository. See limitations for that value in package.json docs > 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.
  7. (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. 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 shows the suggested state after completing these steps.

  1. Install the TypeScript dependencies required for coding in TypeScript.

    npm install --save-dev typescript ts-node @types/node
    
  2. Add a tsconfig.json file to add type checking and support for compiling TypeScript React components and utilities.

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

3. Setup React

The Setup React PR shows the suggested state after completing these steps.

  1. Install the React dependencies required for building React components with TypeScript.

    npm install react react-dom
    npm install --save-dev @types/react @types/react-dom
    
  2. Create the src directory in the project root to store the source code.

  3. Download all the src files from the Setup React PR 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 shows the suggested state after completing these steps.

  1. Install the Jest dependencies required to test TypeScript React components.

    npm install --save-dev jest ts-jest jest-environment-jsdom @types/jest @testing-library/jest-dom @testing-library/react
    
  2. Add the jest.config.js file to let Jest know where to locate test files and what the coverage requirements are.

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

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

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

  6. Add a scripts attribute to package.json to run jest commands in your local terminal.

    "scripts": {
      "test": "jest",
      "test:watch": "jest --watch",
      "test:coverage": "jest --coverage"
    },
    
  7. Download all src/__tests__ files from the Setup Jest PR.

  8. Run the test commands to ensure all tests are passing and all code has test coverage.

    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 shows the suggested state after completing these steps.

  1. Install the Webpack dependencies required to serve files locally and bundle for production deployment.

    npm install --save-dev webpack webpack-cli webpack-dev-server style-loader css-loader ts-loader html-webpack-plugin copy-webpack-plugin webpack-merge
    
  2. Add additional commands to the scripts attribute to package.json to run webpack commands in your local terminal.

    "scripts": {
      "build": "webpack --config webpack.production.js",
      "start": "webpack serve --config webpack.development.js",
      "test": "jest", # <-- Already in file from last step
    },
    
  3. Add a webpack.common.js file to detail the shared configuration process in all environments.

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

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

  6. Run the development commands to ensure the project can be served locally and bundled for production.

    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 shows the suggested state after completing these steps.

  1. Install the Tailwind CSS dependencies required to import its utility styles and integrate with Webpack.

    npm install --save-dev tailwindcss @types/tailwindcss postcss postcss-loader autoprefixer
    
  2. Add a postcss.config.js file to specify which PostCSS plugins to use.

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

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

    {
      test: /\.css$/i,
      use: ['style-loader', 'css-loader', 'postcss-loader'],
    },
    
  5. Add the Tailwind directives to index.css to inject Tailwind styles.

    @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 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.

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 for more information about the tech stack and dependencies used for this project template.

Top comments (0)