Clean history, git LFS
This commit is contained in:
@@ -0,0 +1,239 @@
|
||||
+++
|
||||
categories = ["software"]
|
||||
tags = ["react","typescript","javascript"]
|
||||
date = 2025-04-12T00:00:00-06:00
|
||||
description = ""
|
||||
draft = false
|
||||
slug = "react-app-resurrection"
|
||||
title = "⚛️ React App Resurrection"
|
||||
author = "nicholas"
|
||||
+++
|
||||
|
||||
[Project git repo](https://git.uuard.com/nicholas/storage-manager)
|
||||
|
||||
A few years ago the company I work for explored the idea of rewriting older **ASP.NET** and **Backbone.js** features in a more modern web framework. Between the two contenders, **React** and **Vue**, the development team was leaning toward Vue. Each developer went off and built a small feature or two using Vue to get a sense for it before we eventually committed to rewriting with it. I raised no objections to the decision because it did not matter to me, and I like Vue just fine.
|
||||
|
||||
Eventually, though, I wanted to try building something with React, so I contrived the simplest possible project that would force me to understand at the very least the fundamentals of React. This is why I created this in the first place.
|
||||
|
||||
The app is a simple CRUD app that manages *boxes*, which can contain *items*. I rewrite the app with TypeScript and clean it up a little bit.
|
||||
|
||||
## Technology Stack
|
||||
I am using the **MERN** tech stack:
|
||||
|
||||
- **M**ongoDB (Database)
|
||||
- **E**xpress.js (Backend framework)
|
||||
- **R**eact (Frontend framework)
|
||||
- **N**ode.js (Backend runtime)
|
||||
|
||||
There are a couple main goals I want to accomplish:
|
||||
1. Get the app working
|
||||
2. Upgrade to **Vite** from **Create React App**
|
||||
3. Update Packages
|
||||
4. Typescript rewrite, refactor using *better* practices
|
||||
|
||||
## 1. Get the App Working
|
||||
The first thing I will do is get the **database** working. This is straightforward minus a small hiccup: my server runs on an *Intel Pentium Gold G5400*, and **MongoDB versions 5+ cannot run without the AVX instruction set extension**, which is regrettably absent in the spec sheet.
|
||||
|
||||
{{< image
|
||||
src="images/pentium-gold-g5400-instruction-set-extensions.jpg"
|
||||
caption="Pentium Gold G5400 Instruction Set Extensions - AVX missing" >}}
|
||||
|
||||
So I will use a very old version of mongodb (`mongo:4.4.6`) to get the app working.
|
||||
|
||||
Here is my `compose.yml` file. The container also includes Mongo Express which will allow me to manage my databases with a web interface rather than manage it through the command line. The environment variables are stored in `.env` file.
|
||||
|
||||
**compose.yml**
|
||||
```yaml
|
||||
services:
|
||||
mongo:
|
||||
container_name: mongo-db
|
||||
image: mongo:4.4.6
|
||||
networks:
|
||||
- mongo-network
|
||||
restart: always
|
||||
environment:
|
||||
MONGO_INITDB_ROOT_USERNAME: ${MONGO_INITDB_ROOT_USERNAME}
|
||||
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_INITDB_ROOT_PASSWORD}
|
||||
ports:
|
||||
- 27017:27017
|
||||
|
||||
mongo-express:
|
||||
container_name: mongo-express
|
||||
image: mongo-express
|
||||
networks:
|
||||
- mongo-network
|
||||
restart: always
|
||||
ports:
|
||||
- 8999:8081
|
||||
environment:
|
||||
ME_CONFIG_MONGODB_ADMINUSERNAME: ${ME_CONFIG_MONGODB_ADMINUSERNAME}
|
||||
ME_CONFIG_MONGODB_ADMINPASSWORD: ${ME_CONFIG_MONGODB_ADMINPASSWORD}
|
||||
ME_CONFIG_MONGODB_URL: mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongo:27017/
|
||||
ME_CONFIG_BASICAUTH: false
|
||||
|
||||
networks:
|
||||
mongo-network:
|
||||
name: mongo-network
|
||||
```
|
||||
|
||||
**.env**
|
||||
```env
|
||||
MONGO_INITDB_ROOT_USERNAME=root
|
||||
MONGO_INITDB_ROOT_PASSWORD=<password>
|
||||
ME_CONFIG_MONGODB_ADMINUSERNAME=admin
|
||||
ME_CONFIG_MONGODB_ADMINPASSWORD=<password>
|
||||
```
|
||||
`docker compose up -d`
|
||||
|
||||
This will start the Mongo DB and Mongo Express.
|
||||
|
||||
---
|
||||
|
||||
Next I need to edit the `server.js` connection string to match the credentials, port, and host:
|
||||
|
||||
```javascript
|
||||
require('dotenv').config();
|
||||
|
||||
const DB_HOST = 'server';
|
||||
const DB_PORT = 27017;
|
||||
const DB_USERNAME =process.env.DB_USERNAME;
|
||||
const DB_PASSWORD = process.env.DB_PASSWORD;
|
||||
|
||||
const connectionString = `mongodb://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}?authMechanism=DEFAULT`;
|
||||
```
|
||||
Once again, I am using a `.env` file to keep the username and password secret.
|
||||
|
||||
Now I start the **server** and the **client** with `npm run start`.
|
||||
|
||||
{{< image
|
||||
src="images/server-db-connection-success.jpg"
|
||||
caption="server connected to database" >}}
|
||||
---
|
||||
|
||||
It could use some refinement, but it is working as expected.
|
||||
|
||||
{{< video
|
||||
src="videos/testing-react-app-2x-speed.mp4"
|
||||
width="100%" >}}
|
||||
|
||||
## 2. Upgrade React-Scripts → Vite
|
||||
I will upgrade the app font end to use **Vite** build tools. The app was originally built with **Create React App**, but this was deprecated in favor of other tools such as Vite, Parcel, and RSBuildVite.
|
||||
|
||||
{{< image
|
||||
src="images/create-react-app-deprecation.jpg"
|
||||
caption="Create React App Deprecation blog post" >}}
|
||||
|
||||
First I scaffold a new Vite project: `npm create vite@latest` and select the following options:
|
||||
- project Name: **client**
|
||||
- framework: **React**
|
||||
- variant: **Typescript**
|
||||
|
||||
{{< image
|
||||
src="images/vite-scaffold-project.jpg"
|
||||
caption="Scaffold Vite project" >}}
|
||||
|
||||
I do some work to hook everything up, then run the dev build.
|
||||
|
||||
`npm run dev`
|
||||
|
||||
{{< image
|
||||
src="images/vite-run-dev.jpg"
|
||||
caption="Vite run dev" >}}
|
||||
|
||||
It built the site in `121 ms`. Very nice.
|
||||
|
||||
|
||||
## 3. Package Updates
|
||||
There are a few outdated packages that I should update. I run `npm install <package>@latest`;
|
||||
|
||||
I verify that I do not have any remaining deprecated, old, bad packages:
|
||||
- `npm audit`
|
||||
- `npm outdated`
|
||||
- `npm ls deprecated`
|
||||
|
||||
**server packages check**
|
||||
{{< image
|
||||
src="images/client-package-upgrades.jpg"
|
||||
caption="Client packages check" >}}
|
||||
**client packages check**
|
||||
{{< image
|
||||
src="images/server-package-upgrades.jpg"
|
||||
caption="Server packages check" >}}
|
||||
|
||||
## 4. Javascript → Typescript Rewrite
|
||||
The project was sort of a mess anyway, so I will rewrite it in Typescript as I clean it up. The logic and UI handling made the `app.js` component very fat indeed. I was handling all of the state there, prop-drilling all the way down. It worked, but it did not accord with best practices. Undoubtedly it still does not accord entirely with best practices, if this is even a meaningful concept, but surely I have improved it somewhat anyway. The point was to revive an old project, touch something with React again, and to write some TypeScript, for it is new to me. I liked it.
|
||||
|
||||
Anyway, there is nothing very interesting about the process of rewriting to TypeScript. The results are positive. Javascript with types, among other additional features. I extracted some components, restructured the directory, and ended up with a **front-end** directory like so:
|
||||
|
||||
### Client / Front-end
|
||||
|
||||
```
|
||||
└── 📁src
|
||||
└── 📁api
|
||||
└── api.ts
|
||||
└── apiResponse.types.ts
|
||||
└── index.ts
|
||||
└── 📁components
|
||||
└── ColorSelector.jsx
|
||||
└── GenericMenu.tsx
|
||||
└── Modal.tsx
|
||||
└── 📁features
|
||||
└── 📁box
|
||||
└── box.types.ts
|
||||
└── 📁components
|
||||
└── BoxCard.tsx
|
||||
└── BoxFormModal.tsx
|
||||
└── index.ts
|
||||
└── 📁services
|
||||
└── BoxService.tsx
|
||||
└── 📁item
|
||||
└── 📁components
|
||||
└── ItemCard.tsx
|
||||
└── ItemFormModal.tsx
|
||||
└── index.ts
|
||||
└── item.types.ts
|
||||
└── 📁services
|
||||
└── ItemService.tsx
|
||||
└── 📁icons
|
||||
└── Ellipsis.tsx
|
||||
└── Garbage.tsx
|
||||
└── Icon.tsx
|
||||
└── index.ts
|
||||
└── Move.tsx
|
||||
└── Pencil.tsx
|
||||
└── Plus.tsx
|
||||
└── Search.tsx
|
||||
└── .env
|
||||
└── app.tsx
|
||||
└── index.css
|
||||
└── index.tsx
|
||||
└── tsconfig.json
|
||||
└── vite-env.d.ts
|
||||
```
|
||||
|
||||
### Server / Back-end
|
||||
This is a very simple flat directory containing the web API server.
|
||||
```
|
||||
└── 📁server
|
||||
└── .env
|
||||
└── .gitignore
|
||||
└── package-lock.json
|
||||
└── package.json
|
||||
└── server.js
|
||||
```
|
||||
|
||||
### Database
|
||||
As I mention above, the MongoDB database is hosted in a Docker container.
|
||||
```
|
||||
└── 📁database
|
||||
└── .env
|
||||
└── .gitignore
|
||||
└── compose.yml
|
||||
```
|
||||
|
||||
## Results
|
||||
It works. The app source is hosted on my [git repository](https://git.uuard.com/nicholas/storage-manager)
|
||||
|
||||
{{< video
|
||||
src="videos/demo-react-app.mp4"
|
||||
width="100%" >}}
|
||||
Reference in New Issue
Block a user