Create a React project from scratch, with TypeScript and Vite
Tags: react, typescript, vite, webdev
Published: 2023-05-12 15:19:45



A step by step guide  on how to create a React project from scratch, with TypeScript and [Vite](https://github.com/vitejs/vite).

You can find the full source code here: https://github.com/alexadam/project-templates/tree/master/projects/react-app-vite

## Setup

Prerequisites:
- node (https://nodejs.org/en/download/)
- yarn (https://yarnpkg.com/getting-started/install)



Create the project's folder:

```sh
mkdir react-app
cd react-app
```


Generate a default **package.json** file with yarn:

```sh
yarn init -y
```

Install React, TypeScript and Vite:

```sh
yarn add react react-dom

yarn add --dev @types/react \
        @types/react-dom \
        sass \
        typescript \
        @vitejs/plugin-react \
        vite
```


Add build, dev & clean scripts in the **package.json** file:

```json
 ....
  },
  "scripts": {
    "clean": "rm -rf dist/*",
    "build": "vite --config vite.config.js build",
    "dev": "vite --config vite.config.js serve",
    "preview": "vite --config vite.config.js preview"
  }
```


Configure TypeScript by creating the file **tsconfig.json** with:

```json
{
  "compilerOptions": {
    "incremental": true,
    "target": "es6",
    "module": "commonjs",
    "lib": ["dom", "dom.iterable", "es6"],
    "allowJs": true,
    "jsx": "react",
    "sourceMap": true,
    "outDir": "./dist/",
    "rootDir": ".",
    "removeComments": true,
    "strict": true,
    "moduleResolution": "node",            
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "experimentalDecorators": true
  },
  "include": [
    "./src"
  ],
  "exclude": [
    "./node_modules",
    "./build",
    "./dist"
  ]
}
```


To configure Vite, make a file **vite.config.js** containing:

```js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react(
    {
      include: '**/*.{ts,js,tsx}',
    }
  )],
  base: '',
  root: 'src',
  build: {
    outDir: '../dist',
  },
  server: {
    port: 8080
  },
  preview: {
    port: 8080
  }
})
```

## Example App

Create a folder named **src** (in the project's folder):

```sh
mkdir src
cd src
```


Make a simple React component, in the file **numbers.tsx**:

```js
import React, {useState} from 'react';

interface INumberProps {
  initValue: number
}

const Numbers = (props: INumberProps) => {
  const [value, setValue] = useState(props.initValue)

  const onIncrement = () => {
    setValue(value + 1)
  }

  const onDecrement = () => {
    setValue(value - 1)
  }

  return (
    <div>
      Number is {value}
        <div>
          <button onClick={onIncrement}>+</button>
          <button onClick={onDecrement}>-</button>
        </div>
    </div>
  )
}
export default Numbers
```


Create the main React component (the entry point), in the file **app.tsx**:

```js
import * as React from 'react';
import ReactDOM from "react-dom/client";
import Numbers from './numbers';
import './app.scss'

const App = () => {

  return (
    <Numbers initValue={42} />
  )
}

const root = ReactDOM.createRoot(document.getElementById("app") as HTMLElement);
root.render(<App />);
```

Next, add the **index.html**:

```html
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>React TypeScript</title>
</head>

<body>
  <div id="app"></div>
  <script type="module" src="./app.tsx"></script>
</body>

</html>
```


Add some style in **app.scss**

```css
html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}

* {
  box-sizing: border-box;
}

#app {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
}
```


Then, run `yarn dev` and open `http://localhost:8080/` in a browser.

## Use this project as a template



You can save the *Setup* steps as a shell script:

```sh
#!/bin/sh

rm -rf node_modules
rm -rf dist
rm -rf build
rm package.json
rm yarn.lock

yarn init --yes

yarn add react react-dom

yarn add --dev @types/react \
        @types/react-dom \
        sass \
        typescript \
        @vitejs/plugin-react \
        vite

# Remove the last line
sed -i.bak '$ d' package.json && rm package.json.bak

# append the scripts commads
cat <<EOT >> package.json
   ,"scripts": {
      "clean": "rm -rf dist/*",
      "build": "vite --config vite.config.js build",
      "dev": "vite --config vite.config.js serve",
      "preview": "vite --config vite.config.js preview"
   }
}
```


Delete the **node-modules** folder and, when you want to start a new project, you can copy the contents of *react-app* to the new location:

```sh
mkdir new-project
cd new-project

# copy the react-app folder content to the new project
rsync -rtv /path/to/../react-app/ .

./init.sh
```