Based on the features in the legacy application and the current requirements we selected Next.js and MUI-5 (https://mui.com/getting-started/usage/) frameworks for:
- Easy integration with generic SSO oAuth services like ORCID, SURFconext, Microsoft etc.
- SEO support for custom meta tags and dynamic build sitemap.xml file
- Rapid development of user interface, in particular, the input/admin pages of the legacy application require improvements
- install dependencies
npm install
- create
.env.local
file. Use.env.example
from the project root as template. - run all app modules
docker compose up
- open another terminal and run
npm run dev
to start frontend in development mode
Use this if you are using a custom theme and mount files from the /deployment
directory
First, add the folders that contain the custom configuration to the docker-compose.dev.yml
:
services:
frontend:
# .....
volumes:
- ./frontend:/app
# Replace the following directory with the custom deployment directory
- ./deployment/rsd:/app/public
You can start the frontend in dev mode inside Docker using the Makefile
. The command will make sure that the created Docker container uses a user with the same user id and group id as your local account. This ensures that you will be the owner of all files that are written via mounted volumes to your drive (mainly everything in the frontend/.next
and frontend/node_modules
folders).
make frontend-dev
Alternatively you can run
# Export your user and group ids to the variables so Docker will correctly build the frontend-dev container. This is required only if you build the container
export DUID=$(id -u)
export DGID=$(id -g)
docker compose -f docker-compose.yml -f docker-compose.dev.yml build frontend
docker compose -f docker-compose.yml -f docker-compose.dev.yml up
For oAuth implementation we need env variables. From the project root directory, copy .env.example
file to frontend/.env.local
and provide the values See next documentation page for more info.
.env.local
contains secrets when running frontend in local development (npm run dev
). This file is not in the repo. You will need to create it and add secrets to it. There is one difference from basic .env file.
# postgREST api
# cosumed by services: authentication,frontend,auth-tests
# .env.local: http://localhost/api/v1, .env.production.local: http://backend:3500
POSTGREST_URL=http://localhost/api/v1
It can be useful to intercept HTTP requests made by the Next.js server in order to identify potential bottlenecks and to see if the requests made are correct. In order to do so, add the following snippet to the end of frontend/pages/_app.tsx
:
function replaceFetch(originalFetch: any) {
const newFetch = async function (url: any, conf: any) {
const tik = Date.now();
const resp = await originalFetch(url, conf);
const tok = Date.now();
console.log(`${tok - tik} ms for URL: ${url}`);
return resp;
};
global.fetch = newFetch;
}
// @ts-ignore
if (!global.originalFetch) {
const originalFetch = global.fetch;
// @ts-ignore
global.originalFetch = originalFetch;
replaceFetch(originalFetch);
}
// because Next.js overwrites global.fetch again...
setInterval(() => {
// @ts-ignore
const originalFetch = global.originalFetch;
replaceFetch(originalFetch);
}, 10);
It will print each HTTP request and the time it took to complete.
__tests__
: unit test for pages only. Unit tests for the components are in the same directory as components.assets
: images and icons. These are imported into the components. In case of SVG images, the content is used to create an icon component.components
: all custom components created in this project are stored in this folder.config
: place for configuration objects. For example, menu items are stored here.pages
: next specific, pages and api endpoints. For more information see official documentationpublic
: folder for public assets of the website. For example favicon.ico file and robots.txt are stored here. The root of the public folder is equivalent to the root on the webserver. Note that react file atpage/index.tsx
represents the template for the root webpage.styles
: folder for css files and MUI theme objects. Read specific readme file about theming.types
: folder for typescript type objects. Note! specific, not-shared types are sometimes stored within component fileutils
: folder for utility functions, hooks, composables etc.
The integration between Next.js and MUI-5 is based on official example. More explanation concerning the official example can be found in this video
Most important point concerning Next is integration in template files: _app.tsx, _document.tsx
Customization in MUI5 is done using theme object. The theme is provided at the root React component using Theme context provider. In short, add theme provider to _app.tsx file
In addition to MUI-5, the team prefers to use Tailwind CSS for global application layout.
# install dev dependencies
npm install --save-dev tailwindcss@latest postcss@latest autoprefixer@latest
Steps performed:
- extracted MUI-5 theme into separate object
- created tailwind.config.js and defined to use shared theme definitions
- created postcss.config.js and added tailwind to it
- added @tailwind mixins to styles/global.css
- created styles/tailwind.css for tailwind specific utilities (e.g. @apply)
The integration is based on this article.
For authentication, we use a custom module which integrates with our auth service. The frontend code is in frontend/auth
folder and the auth service is in authentication
folder.
For unit testing we use jest and react testing library. There are several practices that the React Testing Library promotes:
- Avoid testing internal component state
- Testing how a component renders
The setup is performed according to official Next documentation. We use rust compiler instead of babel setup.
npm run test:watch
: to run test in watch mode. The tests will run on each change in the test/component file(s)npm run test:coverage
: to run tests and show the test coverage report. This script is used in GH action.npm run test:memlimit
: for minimal memory consumption. When basic test scripts npm run test and npm run test:coverage causing the memory overflow on your machine use this script to limit the number of concurrent workers and memory usage.npm run test:memory
: for examining memory usage during the tests. In node version 18 (and 16) some changes are made in V8 engine memory management that cause the memory leaks when running tests with Jest. See issue
# install dependencies
npm install --save-dev jest jest-environment-jsdom @testing-library/react @testing-library/jest-dom
# install whatwg-fetch to address next-auth fetch requests on node js (node-fetch)
npm install --save-dev whatwg-fetch
- create jest.config.js file and paste content from next instructions
- crate jest.setup.ts file and paste this content.
// isomorphic fetch suport for Node
// required to support fetch with Jest
import "whatwg-fetch";
// specific
import "@testing-library/jest-dom/extend-expect";
This is a Next.js project bootstrapped with create-next-app
.
To learn more about Next.js, take a look at the following resources:
- Next.js Documentation - learn about Next.js features and API.
- Learn Next.js - an interactive Next.js tutorial.
You can check out the Next.js GitHub repository - your feedback and contributions are welcome!
Upgrading minor version changes can be usually done using npm outdated
and npm update
. Major updates are more demanding and might require changes in the source code.
Since RSD went live in August 2022 we started using exact versions in the package.json to avoid unexpected upgrades. This means that we manually check for outdated packages and perform "controlled" upgrades. At the same time we run security audits using npm audit
.
# upgrade next, react and typescript
npm install next@latest react@latest react-dom@latest eslint-config-next@latest typescript
# upgrade types
npm install --save-dev @types/node @types/react @types/react-dom
# upgrade material ui
npm install @mui/material @mui/icons-material @emotion/react @emotion/server @emotion/styled
# react testing lib
npm install --save-dev @testing-library/react@latest @testing-library/jest-dom@latest jest@latest jest-environment-jsdom@latest @types/jest@latest
# cookie for tokens
npm install cookie
# type
npm install --save-dev @types/cookie
For the maintenance we use knip. It will show a list of unused files, dependencies, exported functions and types. Exclude definitions, specific to this project, are in knip.jsonc
. Knip is able to identify next and use pages folder as entry points.
# execute in the frontend folder
npm run knip:files
Based on report validate that file are unused/not needed. To validate always run npm run test
and npm run build
to confirm that test are working and application can be build.
- Example report
> [email protected] knip:files
> knip --include files
types/Invitation.ts
utils/getUnusedInvitations.ts
components/layout/MasonryGrid.tsx
components/layout/StatCounter.tsx
components/home/rsd/HomeSectionTitle.tsx
components/projects/edit/mentions/citations/NoCitationItems.tsx
Show unused exported functions. Note! This functions could be used in the file itself.
npm run knip:exports
Based on report validate that types are unused/not needed. To validate always run npm run test
and npm run build
to confirm that test are working and application can be build.
- Example report
> [email protected] knip:exports
> knip --include exports
getExpInMs function auth/index.tsx:136:17
getWaitInMs function auth/index.tsx:150:17
initSession unknown auth/index.tsx:48:14
isMaintainerOfCommunity function auth/permissions/isMaintainerOfCommunity.ts:40:23
getCommunitiesOfMaintainer function auth/permissions/isMaintainerOfCommunity.ts:65:23
default unknown auth/permissions/isMaintainerOfCommunity.ts:91:8
getMaintainerOrganisations function auth/permissions/isMaintainerOfOrganisation.ts:69:23
Show unused exported types.
npm run knip:types
Based on report validate that types are unused/not needed. To validate always run npm run test
and npm run build
to confirm that test are working and application can be build.
- Example report
> [email protected] knip:types
> knip --include types
OrganisationCount type components/admin/organisations/apiOrganisation.tsx:21:13
SoftwareKeywordsProps type components/communities/settings/general/AutosaveCommunityKeywords.tsx:23:13
ReleaseCountByYear type components/organisation/releases/useSoftwareReleases.tsx:12:13
NewKeyword type components/projects/edit/information/searchForKeyword.ts:14:13
Name type components/software/edit/contributors/FindContributor.tsx:21:13
ContributorInformationConfig type components/software/edit/editSoftwareConfig.tsx:167:13
TestimonialInformationConfig type components/software/edit/editSoftwareConfig.tsx:241:13
SoftwareInformationConfig type components/software/edit/editSoftwareConfig.tsx:85:13
Knip can report more irregularities in the project. Run npm run knip
to get complete report. However, to validate always run npm run test
and npm run build
to confirm that test are working and application can be build.