Easy step-by-step method to create your own React project with typescript and webpack
Tags: react, typescript, webpack, boilerplate
Published: 2023-10-17 05:23:26

I've been looking for a way to create a new typescript react project from the scratch. I came across a few relevant articles and open source github projects that I thought I could use to get started but couldn't get them to work properly because they were outdated. I started on this journey to setup a new webpack project with typescript and react and wanted to share my journey with others.

Here's a link to the boiler plate code created using steps enlisted below:
{% embed https://github.com/swchak/react-ts-webpack-template %}

---

### Create new project root directory
```
% mkdir react-ts-webpack-template; cd react-ts-webpack-template
```

---

### Install webpack-cli packages
```
% npm install -D webpack-cli
% npm install -D @webpack-cli/generators
```

---

### Generate [new webpack project](https://webpack.js.org/configuration/#set-up-a-new-webpack-project) 

* Run webpack init command.

```
% npx webpack init
```

* Go through the webpack setup process.

You should see a list of options to be selected go ahead make the same selections.
![webpack-init-select-options](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qdlr0m4xj054iewdpjud.png)

* Folder structure created should look like this -
![webpack-folder-structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9tvhupo5ji1yk5gul9lg.png)

_Note: typescript and ts-loader packages are automatically installed as part as part of the webpack init command._

* Check webpack project can be run and served without issues

```
% npm run build
% npm run serve
```

Web dev server should be launched as seen below

![webpack-project-build-serve](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gud146y7o06t0oxtkirr.png)

---

### Install react packages
- [react](https://www.npmjs.com/package/react)
- [react-dom](https://www.npmjs.com/package/react-dom)
- [@types/react](https://www.npmjs.com/package/@types/react) 
- [@types/react-dom](https://www.npmjs.com/package/@types/react-dom)

```
% npm install react react-dom
% npm install --save-dev @types/react @types/react-dom
```

---

### Setup [Babel](https://babeljs.io/docs/)
* install babel packages using npm
 - [@babel/core](https://www.npmjs.com/package/@babel/core)
 - [@babel/preset-env](https://www.npmjs.com/package/@babel/preset-env)
 - [@babel/preset-env](https://www.npmjs.com/package/@babel/preset-env)
 - [@babel/preset-typescript](https://www.npmjs.com/package/@babel/preset-typescript)
 - [@babel/cli](https://www.npmjs.com/package/@babel/cli)
 - [@babel/preset-react](https://www.npmjs.com/package/@babel/preset-react)
```
npm install --save-dev @babel/core @babel/preset-env @babel/preset-typescript @babel/cli @babel/preset-react
```

* add a .babelrc file
```
{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-typescript",
    "@babel/preset-react"
  ]
}
```

* add script below in package.json to enable command line invocation of babel.
```
 "babel": "babel src --out-file dist/main.js --extensions .ts,.js,.tsx,.jsx,.cjs,.mjs  --presets=@babel/preset-typescript,@babel/preset-env,@babel/preset-react"
```

* check babel setup works as expected
```
npm run babel
```
check for creation of dist/ directory with main.js which is the code that babel transpiled and webpack bundled it under main.js

---

### Update tsconfig.json
```
{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "noImplicitAny": true,
    "module": "es6",
    "target": "es5",
    "allowJs": true,
    "jsx": "react-jsx", //tells ts compiler to compile react jsx 
    "moduleResolution": "node"
  },
  "include": ["src/**/*"],
  "exclude": ["**/*.spec.ts"]
}
```

- **compilerOptions.jsx** property when set to "react-jsx" lets typescript compiler know that it needs to handle react jsx code.

- **include** and **exclude** tell the typescript compiler which files to include and exclude from compilation.

### Update webpack config

Make the following changes to web pack

* update the entry point to be "./src/index.tsx" instead of "./src/index.ts"

* add rules for babel-loader and file-loaders 

```
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: ["babel-loader"],
      },
      {
        test: /\.(jpg|jpeg|png|gif|mp3|svg)$/,
        use: ["file-loader"],
      },
```

### Create sample ts react component and related files required to be rendered into the index.html page

* create new files index.tsx, App.tsx and App.css in src/ dir

```
% touch src/index.tsx src/App.tsx src/App.css 
```

* add the sample code below into App.tsx to create a new functional react component 

```
import { FC } from "react";

interface MessageProps {
  greeting: string;
  user: string;
  projectTitle: string;
}

const App: FC<MessageProps> = (props: MessageProps) => {
  return (
    <div className="app-id">
      <h1 className="greeting-id">{props.greeting}</h1>
      <h1 className="user-id">{props.user} </h1>
      <h2 className="title-id">{props.projectTitle}</h2>
    </div>
  );
};

export default App;
```

* update index.html to add _<div id="root"></div>_ inside the body tag. this refers to the node where we will be injecting and rendering the new react component App.

```
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Welcome to React TypeScript Project Boilerplate</title>
  </head>
  <body>
    <!-- This is the DOM node -->
    <div id="root"></div>
  </body>
</html>


```

* make following updates to index.tsx. 

 - import the sample react component defined in App.jsx
 - get a reference to the browser DOM node(div tag with root id) from index.html
 - call [createRoot](https://react.dev/reference/react-dom/client/createRoot) pass in reference to browser DOM node that will serve as the root for rendering react components.
 - invoke render method of root object created passing in JSX markup where we use the imported sample App component.

```
import { createRoot } from "react-dom/client";
import "./App.css";
import App from "./App";
import React from "react";

const root = createRoot(document.getElementById("root"));

root.render(
  <App
    greeting={"Hello"}
    user={"Swetha"}
    projectTitle={
      "Welcome to the journey of setting up your own typescript react project from scratch"
    }
  />
);
```

* update App.css with simple rules

```
h1.user-id,
h1.greeting-id {
  color: red;
  display: inline-block;
  margin-right: 15px;
}

h2.title-id {
  background-color: aqua;
}
```

* Run npm build and serve 

```
% npm run build
% npm run serve
```
![create-succeeded_console](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/du5yny5pctxa18wyi7li.png)


![create-succeeded-browser](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/759d8ai8f1md7fb78xaf.png)