⚠️ WARNING: This repo is now archived. It should only be used as a reference if you want to set up a custom webpack configuration. The practices in this repo may be outdated and you should be cautious when used as a reference. Hipo uses this new CRA template when starting out new projects.
This template includes all the configurations for kick-starting a project with React and TypeScript.
For now, you need to manually copy-paste all the files from the template into your directory. Eventually, there will be a command-line tool that does this for you. After you copied all the files in this template, you will need to take the following steps:
- This project requires Node >= 12.x and npm >= 6.x for proper development environment.
-
Update necessary fields inside
package.json
for your projects. -
Go over all the files inside
config
folder and update them with your project's necessities. Here you will find the following configuration files:
apiConfig:
Configurations for the API requests in different environments.assetConfig:
Paths for the assets in different environmentss3Config:
S3 configurations for different environments.sentryConfig:
Sentry configurations for different environments.
-
Update
changelog-context-variables.json
to include your project'scodebaseProjectName
. -
Run
npm install
to install dependencies. -
Check commented out code for Sentry integration. You will find them inside
index.tsx
andNetworkManager.ts
. Make sure to checksentryHandler.ts
for correcting integration.
npm start
This will build out the frontend for development environment. It is an alias for npm run build:dev:live
. This will use the webpack.dev.config.js
file and start out the webpack dev server with local
being the target environment. If you want to build in another environment then do npm run build:dev:live -- --env.target=TARGET_ENV
where TARGET_ENV may be one of the following: production, staging or local (or preproduction, if you add it). You can simply run npm run build:dev
if you don't want to listen for changes.
It is recommended to split your terminal and run npm start
in one and npm run type-check:watch
in another. npm run type-check
offers cleaner output when you have errors from the tsc
.
npm run build:release -- --env.target=RELEASE_TARGET --env.awsAccessKeyId=AWS_ACCESS_KEY_ID_FOR_YOUR_TARGET_ENV --env.awsSecretAccessKey=AWS_SECRET_ACCESS_KEY_FOR_YOUR_TARGET_ENV
This will generate /build
folder with static files to serve. RELEASE_TARGET
may be one of the following: production, staging or local (or preproduction, if you add it). During server deployment (executed by the CI jobs), RELEASE_TARGET is derived by the branch name (currently can be staging, or production).
There is a pre-commit
git hook which runs npm run lint; npm run type-check;
script when you want to commit your changes. If any of them fails, it won't allow you to commit. You can still force commit by telling git to skip pre-commit, but you shouldn't.
Also, a pre-push
git hook which runs npm run test
script when you want to push your changes. If any of them fails, it won't allow you to push.
npm run changelog
This will generate a changelog from your commits. Refer to its repo for details.
The template already have protected
and public
route system. Dig into src/core/route/
to see how it works. There you will find an example of one public route that passes a prop to its component and a lazy loaded protected route.
The template is generated with the token authentication in mind. webStorage
and authenticationManager
utilities are generated for this purposes. authenticationManager
allows you to store or retrieve the token with the help of webStorage
. authenticationState
is added to the root Redux Store. This state has to have an authenticateProfile
key which is used for the functionality behind protectedRoutes
. When you authenticate your user in your application, you need to save the user data as the value of authenticateProfile
.
The template has a network manager and an api handler utility which needs to be used when making requests with axios
. An example for a GET request:
function listBuyerPO(
{projectId, params}: {projectId: string; params?: TBuyerPOListRequestParams},
cancelToken?: CancelToken
) {
return apiHandler<IListResponse<IBuyerPO[]>>(
manufacturitApiManager,
"get",
`/projects/${projectId}/buyer-purchase-orders/`,
{
settings: {
params,
cancelToken
}
}
);
}
These functions would usually be inside a file named as, e.g., buyerPOApiHandlers.ts
. As you can see apiHandler
allows you to type the returned promise. These types would usually be defined inside a file named as, e.g., buyerPOApiModels.ts
.
Redux and redux-saga integration is already available with the template. For the asynchronous actions, you can use asyncReduxAutomator
tool to speed up the generation of necessary action creators, saga watchers, etc. For example, for the buyer PO list request above you can create a redux
namespace object with:
const initialBuyerPOListState = getMinimalAsyncStoreState<IBuyerPO>([]);
const buyerPOListReduxNamespace = {
initialState: initialBuyerPOListState,
...asyncReduxAutomator("listBuyerPO", listBuyerPO, initialBuyerPOListState, "list")
};
buyerPOListReduxNamespace
will now have initialState
, actionTypes
, actionCreators
, saga
, watcher
, reducer
keys which you can use to integrate into your Redux store.
Note: promisifyAsyncActionsMiddleware
is added to Redux to promisify REQUEST_TRIGGER
actions.
Note: For the async processes, avoid using Redux and Redux-saga, if possible. Instead, try using useAsync
hook. Example usage:
const requestState = useAsync(
{
handlerCreator: accountApi.updateAccount,
argumentGenerator() {
return {
accountId: accountDetail!.id,
payload: generateUpdateAccountPayload(state)
};
}
},
[shouldUpdate, state, accountDetail],
{
shouldMakeRequest() {
return Boolean(shouldUpdate && accountDetail?.id);
},
onSuccess(account) {
setSuccessModalVisibility(true);
},
onFailure(error) {
dispatchFloatingMessage({
type: "DISPLAY",
payload: {
type: "error",
message: generateErrorMessageFromCaughtError(error)
}
});
}
}
);
This template utilizes react-modal library for implementing modals. There is a component called Modal
that uses react-modal
in the background that lets you generate modals easily. An example modal named as ReportModal
is generated.
These files should be gathered inside /src/core/declarations/
.
npm run test
Tests can be run by executing the command above. Tests files should be placed right below the original implementation file, see numberUtils
for example inside /src/utils/number/
.
Group by main modules or routes for the project:
├── config
└── src
└── components <- Where common components of the project are placed
└── button
└── dropdown
└── form
├── core <- Core functionality, routes and root app is here
├── dashboard <- Homepage related stuff
└── home <- Homepage related stuff
├── api
└──homeApiHandlers.ts <- Api handler functions are defined here
└──homeApiModels.ts <- Api models are defined here
├── invester
└── _invester-homepage.scss
└── InvesterHomepage.tsx
└── InvesterHomepage.test.ts
├── advisor
└── _advisor-homepage.scss
└── AdvisorHomepage.tsx
└── AdvisorHomepage.test.ts
├── redux
└── advisor
└── advisorHomeReduxState.ts
└── advisorStatsReduxState.ts
└── investor
└── investorHomeReduxState.ts
└── investorStatsReduxState.ts
└── homeReduxState.ts <- Main `homeState`, its reducer and saga factory are defined here
└── utils
└── homeReduxUtils.ts
└── homeReduxUtils.test.ts
└── utils
└── homeUtils.ts
└── homeUtils.test.ts
NOTE: Avoid a deeply nested structure and don't overthink it.