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!
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-dom
Add git to project and add
.gitignore
file. Your project should look like this,Now we will install
babel
related dev-dependenciesnpm i -D @babel/core @babel/preset-env @babel/preset-react babel-loader css-loader style-loader
install
webpack
related dev-dependenciesnpm i -D webpack webpack-cli webpack-dev-server html-webpack-plugin
install
typescript
related dependenciesnpm i typescript npm i -D @types/react @types/react-dom @babel/preset-typescript
Add SASS dependencies for a better styling experience.
npm i -D sass sass-loader
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" ] }
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 */, ], };
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/**/*"] }
Create
src
folder and createindex.tsx
,App.tsx
andindex.html
inside of it.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>
App.tsx
file content,export const App = () => { return <h1>Hey there!</h1>; };
index.tsx
file content,import ReactDOM from "react-dom"; import { App } from "./App"; ReactDOM.render(<App />, document.getElementById("root"));
Let's add the following script to
package.json
to start our application"start": "webpack serve --config webpack.config.js"
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" } }
now let's run the newly added script using command π€πΌ,
npm start
Voila! we are good to go π»!
Let's try to add styles using
scss
now. addApp.module.scss
file 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.tsx
file 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.ts
file 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 types
in Webpack. know more. - You can always optimise the bundling process through various
plugins
, know more. 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 π