A step-by-step guide on how to create a React project from scratch with TypeScript and Vite.
You can find the full source code here: https://github.com/alexadam/project-templates/tree/master/projects/react-app-vite
Prerequisites:
Create the project's folder:
mkdir react-app
cd react-app
Generate a default package.json file with yarn:
yarn init -y
Install React, TypeScript, and Vite:
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:
....
},
"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:
{
"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:
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
}
})
Create a folder named src (in the project's folder):
mkdir src
cd src
Make a simple React component in the file numbers.tsx:
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:
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:
<!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
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.
You can save the Setup steps as a shell script:
#!/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:
mkdir new-project
cd new-project
# copy the react-app folder content to the new project
rsync -rtv /path/to/../react-app/ .
./init.sh