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!

I am a passionate Full-Stack Developer with in-depth experience primarily in React, Angular (2+) & .Net Core. I also love writing blogs to share know how about things I find fascinating and useful.
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
Create a new application using the command, This should create a package.json file
npm init -y
Now let's install react dependencies
npm i react react-domAdd git to project and add
.gitignorefile. Your project should look like this,
Now we will install
babelrelated dev-dependenciesnpm i -D @babel/core @babel/preset-env @babel/preset-react babel-loader css-loader style-loaderinstall
webpackrelated dev-dependenciesnpm i -D webpack webpack-cli webpack-dev-server html-webpack-plugininstall
typescriptrelated dependenciesnpm i typescript npm i -D @types/react @types/react-dom @babel/preset-typescriptAdd SASS dependencies for a better styling experience.
npm i -D sass sass-loaderAdd
.babelrcfile 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" ] }Add
webpack.config.jsfile 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 */, ], };Add
tsconfig.jsonfile 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/**/*"] }Create
srcfolder and createindex.tsx,App.tsxandindex.htmlinside of it.index.htmlfile 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>App.tsxfile content,export const App = () => { return <h1>Hey there!</h1>; };index.tsxfile content,import ReactDOM from "react-dom"; import { App } from "./App"; ReactDOM.render(<App />, document.getElementById("root"));Let's add the following script to
package.jsonto start our application"start": "webpack serve --config webpack.config.js"at this point, our
package.jsonfile 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" } }now let's run the newly added script using command π€πΌ,
npm startVoila! we are good to go π»!

Let's try to add styles using
scssnow. addApp.module.scssfile with following content inside src folder..heading { color: orange; font-family: 'Courier New', Courier, monospace; font-size: 40px; font-weight: 500; }use these styles in
App.tsxfile like this,import styles from "./App.module.scss"; export const App = () => { return <h1 className={styles.heading}>Hey there!</h1>; };let's rerun the application. but wait! what is this?

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)
To fix this, we just have to declare a
declarations.d.tsfile within the src folder with the following content.declare module "*.module.scss";And, ta-da! the error is gone,

Our application is running as expected π₯

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,
- Always add
loaders for new file typesin Webpack. know more. - You can always optimise the bundling process through various
plugins, know more. Declare module for new filetypes 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 π




