Our Initial ReactJS/TypeScript setup¶
Initial project creation¶
The command to create initial frontend project is:
npx create-react-app frontend --template typescript
.
This will create the project in ./frontend
directory.
While create-react-app
initializes the project, you have plenty of time to get fresh cup of
coffee/tea.
Change everything as development dependency¶
You should go and edit ./package.json
so that everything in the dependencies
section is located
at devDependencies
. We will not have any runtime dependencies since the project is compiled as a
single bundle.
Setup IDEA's configuration not to be in git¶
You should append .idea
to .gitignore
, even if you are not using IDEA. If .idea
is already
in git, please remove it completely from git first.
Install core dependencies¶
Open a terminal and execute:
npm i --save-dev \
node-sass@4.14.1 '@types/node-sass' \
lodash '@types/lodash' \
'moment-timezone' '@types/moment-timezone'
Install our core TypeScript library¶
You should also install our core TypeScript library:
mkdir -p src/fi/hg
git submodule add git@github.com:heusalagroup/fi.hg.core.git src/fi/hg/core
git config -f .gitmodules submodule.src/fi/hg/core.branch main
git add .gitmodules
Rename CSS files as SCSS¶
Now, you should rename *.css
as *.scss
.
If you use IDEA, it should automatically replace paths in imports and exports correctly.
Expert note: Configure shortcut (or Apple TouchBar action) to Rename files.
Move App to its own subdirectory¶
Next, you should move App.*
to directory src/components/app
.
Same here, you shouldn't need to manually fix imports/exports.
Expert note: Configure shortcut (or Apple TouchBar action) to Move files.
Remove default exports¶
The project builder will initialize the project with some default exports. Refactor out of these.
We don't use default exports. Default exports are not compatible between different project builders. Using them will make your life miserable for example when trying to bundle your frontend inside a server side rendering NodeJS server.
For example, change code like this:
import ReactDOM from 'react-dom/client';
...to:
import { createRoot } from 'react-dom/client';
Also remove the default export from generated ./App.tsx
.
Create constant file for class names¶
The default template will implement App
component using class name as App
.
It's best practice to create a single file src/constants/classNames.ts
where
you define all of your class names in one place.
Create this file and add the App class there:
export const APP_CLASS_NAME = 'hg-app';
Then use it in your App.tsx
code:
<div className={APP_CLASS_NAME}>...</div>
Keep in mind that the name must match with the component's name. Also the class constant must always go to the top level element in your component. Otherwise you make messy code that's slow to debug and develop later.
Any class name in your component must be unique. For example, never do this:
return (
<div className={APP_CLASS_NAME}>
<h3 className={APP_CLASS_NAME}>Title</h3>
</div>
);
Instead, do this:
return (
<div className={APP_CLASS_NAME}>
<h3 className={`${APP_CLASS_NAME}-title`}>Title</h3>
</div>
);
Setup Dockerfile¶
Create file ./Dockerfile
with contents:
ARG NODE_IMAGE=node:14
FROM $NODE_IMAGE as node-image
FROM node-image
ARG DEFAULT_REQUEST_CLIENT_MODE=WINDOW
ARG DEFAULT_NODE_ENV=production
ARG DEFAULT_GENERATE_SOURCEMAP=false
ARG DEFAULT_PUBLIC_URL=http://localhost:3000
ENV PATH=/app/node_modules/.bin:$PATH
ENV REACT_APP_REQUEST_CLIENT_MODE=$DEFAULT_REQUEST_CLIENT_MODE
ENV REACT_APP_PUBLIC_URL=$DEFAULT_PUBLIC_URL
ENV NODE_ENV=$DEFAULT_NODE_ENV
ENV GENERATE_SOURCEMAP=$DEFAULT_GENERATE_SOURCEMAP
WORKDIR /app
COPY ./package*.json ./
RUN npm ci --silent --also=dev
RUN npm rebuild node-sass --sass-binary-name=linux-x64-83
COPY tsconfig.json ./tsconfig.json
#COPY config ./config
#COPY scripts ./scripts
COPY public ./public
COPY src ./src
#COPY --from=nor-shared-image /app/shared/src ./src/shared
RUN npm run build
If you are going to be using a backend, set up a development proxy now¶
First, install http-proxy-middleware
:
npm i --save-dev http-proxy-middleware
Create a file named src/setupProxy.js
and append this there:
const REACT_APP_BACKEND_TARGET_URL = process?.env?.REACT_APP_BACKEND_TARGET_URL ?? 'http://localhost:3500';
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: REACT_APP_BACKEND_TARGET_URL,
changeOrigin: true,
autoRewrite: true,
//protocolRewrite: 'http',
pathRewrite: {
['^/api'] : ''
}
})
);
};
Now, you can control where /api/...
is forwarded:
REACT_APP_BACKEND_TARGET_URL='http://localhost:8080' npm start
This will redirect http://localhost:3000/api
to http://localhost:8080
.
REACT_APP_BACKEND_TARGET_URL
defaults to http://localhost:3500
.
Test if the system runs¶
You can test if the app starts:
npm start
Sometimes IDEA fails to fix import/exports, so fix them manually now.
Make sure everything is in git¶
Finally, make sure everything is committed to git and push your initial working version now.