Install the Latest Node.js
sudo apt install nodejs npm
sudo npm install n -g
For the latest stable version of Node JS:
sudo n stable
node --version
Create a New React App with Vite
Install Node.js, then in the directory where you want to install (often within project-name/client
):
npm create vite@latest
npm run dev
Clone Existing React App
To clone a React project from Github, you clone it, then use the following command from the project subdirectory (to install it, which I don’t totally understand, but it works):
npm install --f
Move Entire App to a Subdirectory
You’ll want the React app to be contained in a subdirectory /client
and the Express API contained in a subdirectory /api
or /server
. You can move the entire React app by moving all files into a subdirectory with the following commands:
mkdir client
git mv -k * client/
Create the Express API (mostly from ChatGPT)
mkdir api
cd api
npm init -y
Install express. Install mysql2 only if you are going to connect to a database:
npm install express cors dotenv mysql2
npm install --save-dev typescript ts-node nodemon @types/node @types/express @types/cors
UPDATE: ts-node is apparently a higher-performance version of tsx. I found ts-node to be a pain, so next time, use tsx instead.
npx tsc --init
Modify tsconfig.json
for better compatibility:"compilerOptions": {
"target": "ESNext",
"module": "NodeNext",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"moduleResolution": "node"
}
Add the following lines to package.json
, scripts
section to run typescript files directly with ts-node by compiling with tsc
then running the dist/index.js
file:
… ,
"type": "module",
"scripts": {
"dev": "ts-node src/index.ts",
"build": "tsc",
"start": "node dist/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
Make src/
directory:
mkdir src
cd src
Within src/
, make index.ts
and write the express API TS code, then run it with:
npm run dev
Running the Two Servers, API + React App
When they are separate, run the API from the api/ directory with:
npm run dev
and run the React app made with Vite from the client/
directory with:
npx vite
Deploy to a VPS
Fresh install an Ubuntu server and create non-root superuser per these instructions. Then:
sudo apt install -y nodejs npm nginx
sudo npm install -g serve pm2
Build and Run Frontend Manually
Going to frontend directory, then:
npm install
rm -rf dist
(if necessary to clear previous build)
npm run build
package.json
should be: "scripts": { "dev": "vite", "build": "tsc -b && vite build", ... }
serve -s dist --listen 4173
Run the Backend Manually
node index.js
CORS and .env Note
It is worth setting up – from the beginning – permissive CORS that utilizes .env
. You can get pretty far ignoring CORS and .env
in your initial local dev environment, but you do encounter CORS even in the local environment from the start. Facing and understanding the concepts of .env
and CORS up front saves time overall.
Also using .env
up front helps separate the environmental factors so you understand how things are working better.
Set up pm2
From the client/
directory:
pm2 start bash --name tlom-viteserve --cwd /home/nate/code/tlom2/client -- -c "serve -s dist --listen 4173"
From the api/
directory:
pm2 start index.js
Set up pm2 for reboot:
pm2 save
pm2 startup
Then copy-paste the long command it gives you, per instructions.
Nginx as a Reverse Proxy
Then modify
sudo nano /etc/nginx/sites-available/default
with:
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /home/youruser/your-project-folder/frontend/dist;
index index.html;
location / {
try_files $uri /index.html;
}
location /api/ {
proxy_pass http://localhost:5000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Then restart nginx:
sudo nginx -t && sudo systemctl restart nginx