Set up React with TS, Babel & Webpack 5 in just 25 Steps πŸš€

Set up React with TS, Babel & Webpack 5 in just 25 Steps πŸš€

Learn how to set up your first React project with TypeScript, Babel and Webpack 5 from scratch in just 25 easy steps!

Indrajeet Nikam's photo
Indrajeet Nikam

Published on Sep 12, 2021

6 min read

Subscribe to my newsletter and never miss my upcoming articles

Namaste everyone πŸ™πŸΌ

Have you ever wanted to work with TypeScript in React but were afraid of changing huge Webpack, Babel config files. Well, I was on the same boat till pretty recent. I had always worked with Create-react-app(CRA) in the past so I never bothered getting into intricate details of configuring Webpack, Babel or TypeScript to have a custom configuration for the application.

I almost always relied upon CRA templates for the initial scaffolding.

But recently I felt the need to start understanding how Webpack works. The reason is, having knowledge about module bundlers will help me throughout my career as a Frontend(JS/TS) developer.

So I took my sweet time understanding it in the past few weeks. Now I want to share it with you all.

How you can set up React app with TypeScript, Babel & Webpack in 25 steps!

Steps

  1. Create a new application using the command, This should create a package.json file

     npm init -y
    

    Initialize node project

  2. Now let's install react dependencies

     npm i react react-dom
    
  3. Add git to project and add .gitignore file. Your project should look like this,

    Initialize git

  4. Now we will install babel related dev-dependencies

     npm i -D @babel/core @babel/preset-env @babel/preset-react babel-loader css-loader style-loader
    
  5. install webpack related dev-dependencies

     npm i -D webpack webpack-cli webpack-dev-server html-webpack-plugin
    
  6. install typescript related dependencies

     npm i typescript
     npm i -D @types/react @types/react-dom @babel/preset-typescript
    
  7. Add SASS dependencies for a better styling experience.

     npm i -D sass sass-loader
    
  8. Add .babelrc file at the root level with the following config,

     {
       "presets": [
         "@babel/preset-env",
         [
           "@babel/preset-react",
           {
             "runtime": "automatic" // This removes need to import react in each file
           }
         ],
         "@babel/preset-typescript"
       ]
     }
    
  9. Add webpack.config.js file at root level with following config,

     const path = require("path");
     const HtmlWebpackPlugin = require("html-webpack-plugin");
    
     module.exports = {
       entry: path.resolve(
         __dirname,
         "./src/index.tsx"
       ) /* entry-point(s) to start app bundling process */,
       resolve: {
         extensions: [".tsx", ".ts", ".jsx", ".js"],
       } /* configure how modules are resolved */,
       module: {
         rules: [
           {
             test: /\.(ts|js)x?$/,
             exclude: /node_modules/,
             use: ["babel-loader"],
           } /* rules to process .ts, .tsx, .js, .jsx files */,
           {
             test: /\.s[ac]ss$/i,
             use: ["style-loader", "css-loader", "sass-loader"],
           } /* rules to process .scss, .sass files */,
         ],
       } /* determines how different module types will be treated */,
       output: {
         path: path.resolve(__dirname, "./build"),
         filename: "bundle.js",
       } /* where to output your bundle */,
       mode: "development" /* for built-in optimizations -> 'none' | 'development' | 
     'production' */,
       devtool: "cheap-module-source-map" /* how source maps are generated */,
       devServer: {
         open: true, // opens the app when you run "npm start"
       } /* options for webpack-dev-server */,
       plugins: [
         new HtmlWebpackPlugin({
           template: path.resolve(__dirname, "./src/index.html"),
         }) /* simplifies the creation of HTML files to serve your webpack bundles */,
       ],
     };
    
  10. Add tsconfig.json file at the root level with the following config.

    {
      "compilerOptions": {
        "target": "ES5" /* Specify ECMAScript target version */,
        "module": "ESNext" /* Specify module code generation */,
        "moduleResolution": "node" /* Specify module resolution strategy */,
        "lib": [
          "DOM",
          "ESNext"
        ] /* Specify library files to be included in the compilation. */,
        "jsx": "react-jsx" /* Specify JSX code generation */,
        "noEmit": true /* Do not emit outputs. */,
        "isolatedModules": true /* Transpile each file as a separate module */,
        "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
        "strict": true /* Enable all strict type-checking options. */,
        "skipLibCheck": true /* Skip type checking of declaration files. */,
        "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
        "resolveJsonModule": true /* Allows importing modules with a β€˜.json’ extension */
        // "allowJs": true /* Allow javascript files to be compiled. Useful when migrating from JS to TS */,
        // "checkJs": true /* Report errors in .js files. Works with allowJs. */,
      },
      "include": ["src/**/*"]
    }
    
  11. Create src folder and create index.tsx, App.tsx and index.html inside of it.

  12. index.html file content,

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>React Webpack Setup</title>
      </head>
      <body>
        <div id="root"></div>
      </body>
    </html>
    
  13. App.tsx file content,

    export const App = () => {
      return <h1>Hey there!</h1>;
    };
    
  14. index.tsx file content,

    import ReactDOM from "react-dom";
    import { App } from "./App";
    
    ReactDOM.render(<App />, document.getElementById("root"));
    
  15. Let's add the following script to package.json to start our application

    "start": "webpack serve --config webpack.config.js"
    
  16. at this point, our package.json file should look like this,

    {
      "name": "react-webpack-setup",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "start": "webpack serve --config webpack.config.js"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "dependencies": {
        "react": "^17.0.2",
        "react-dom": "^17.0.2"
      },
      "devDependencies": {
        "@babel/core": "^7.15.5",
        "@babel/preset-env": "^7.15.6",
        "@babel/preset-react": "^7.14.5",
        "@babel/preset-typescript": "^7.15.0",
        "@types/react": "^17.0.20",
        "@types/react-dom": "^17.0.9",
        "babel-loader": "^8.2.2",
        "css-loader": "^6.2.0",
        "html-webpack-plugin": "^5.3.2",
        "sass": "^1.39.2",
        "sass-loader": "^12.1.0",
        "style-loader": "^3.2.1",
        "typescript": "^4.4.3",
        "webpack": "^5.52.1",
        "webpack-cli": "^4.8.0",
        "webpack-dev-server": "^4.2.0"
      }
    }
    
  17. now let's run the newly added script using command 🀞🏼,

    npm start
    
  18. Voila! we are good to go 🍻!

    First successful render

  19. Let's try to add styles using scss now. add App.module.scss file with following content inside src folder.

    .heading {
        color: orange;
        font-family: 'Courier New', Courier, monospace;
        font-size: 40px;
        font-weight: 500;
    }
    
  20. use these styles in App.tsx file like this,

    import styles from "./App.module.scss";
    
    export const App = () => {
      return <h1 className={styles.heading}>Hey there!</h1>;
    };
    
  21. let's rerun the application. but wait! what is this?

    Error with declarations

  22. Yep, I forgot to tell you this one. If you are trying to import non js/ts(i.e. .scss, .png, .jpeg files etc.) files as a module in your code, typescript gives above error in the editor.

    Cannot find module './App.module.scss' or its corresponding type declarations.ts(2307)

  23. To fix this, we just have to declare a declarations.d.ts file within the src folder with the following content.

    declare module "*.module.scss";
    
  24. And, ta-da! the error is gone,

    Error in the editor is gone

  25. Our application is running as expected πŸ”₯

    Application final render


And we are done. I told you these were easy steps.

Now you can go crazy πŸš€ and can keep expanding your application as you see fit. Just keep the following checklist in your mind,

  1. Always add loaders for new file types in Webpack. know more.
  2. You can always optimise the bundling process through various plugins, know more.
  3. Declare module for new file types in declarations.d.ts

To get the above codebase, check out this git repo.


Hope this was helpful to you.

If you have any problem following the above steps, please mention those in the comments, I'll help asap.

For more such content, follow me on my blog, LinkedIn or Twitter.

See you soon, Take care 😊

Did you find this article valuable?

Support Indrajeet Nikam by becoming a sponsor. Any amount is appreciated!

Learn more about Hashnode Sponsors
Β 
Share this