Skip to content

Frontend: Tooling

npm has a built in scripting tool that allows to map npm run commands to specific shell calls. For example,

npm run hello

can be mapped to

echo "Hello"

This is useful as it makes it easier to remember the commands. This is done by adding to the "scripts" mapping in frontend/package.json (as shown below).

Formatting

Prettier logo

Typescript does not have an official format/formatter, however prettier is the de-facto formatter. We should add it to the project, as a development depenedency,

Run this command in frontend/

npm install --save-dev prettier

to match the Python style I configure prettier by adding to frontend/.prettierrc.json,

{
  "trailingComma": "all"
}

This allows two commands reformat to autoformat the code and format to check the formatting of the code to be added in the frontend/package.json file,

"scripts": {
   "format": "prettier --parser typescript --list-different \"src/**/*.{ts,tsx}\"",
   "reformat": "prettier --parser typescript --write \"src/**/*.{ts,tsx}\"",
   ...
}

and used

Run these commands in frontend/

npm run reformat
npm run format

Linting

Linting the Typescript code

ESLint logo

ESLint is the de facto Typescript (Javascript) linter, however the default configuration has possible incompatibilities with prettier, so eslint-config-prettier is required. As with the backend I also like to order imports, for which eslint-plugin-import can be used. Finally we'll add langauge translations to the frontend, which are easily missed without eslint-plugin-i18next,

Run this command in frontend/

npm install --save-dev eslint eslint-config-prettier eslint-plugin-i18next eslint-plugin-import

as most of the configuration is already correct I change the "eslintConfig" section of the frontend/package.json to, (with the import rules matching the backend configuration),

"eslintConfig": {
  "extends": [
    "react-app",
    "react-app/jest",
    "plugin:import/errors",
    "plugin:import/warnings",
    "plugin:import/typescript",
    "prettier"
  ],
  "plugins": [
    "i18next"
  ],
  "rules": {
    "i18next/no-literal-string": [
      "warn",
      {
        "markupOnly": true,
        "onlyAttribute": [
          "label"
        ]
      }
    ],
    "import/newline-after-import": "error",
    "import/no-unresolved": "off",
    "import/order": [
      "error",
      {
        "alphabetize": {
          "order": "asc",
          "caseInsensitive": true
        },
        "groups": [
          "builtin",
          "external",
          "internal"
        ],
        "pathGroups": [
          {
            "pattern": "src/**",
            "group": "external",
            "position": "after"
          }
        ],
        "pathGroupsExcludedImportTypes": [
          "builtin"
        ],
        "newlines-between": "always"
      }
    ],
    "no-console": "warn",
    "react-hooks/exhaustive-deps": "error"
  }
}

eslint can also automatically fix issues it finds, as this saves effort it is good to add this to the reformat command, by changing it in frontend/package.json to,

"scripts": {
  "reformat": "eslint --fix \"src/**/*.{ts,tsx}\"; prettier --parser typescript --write \"src/**/*.{ts,tsx}\""
}

Linting the CSS

Stylelint logo

ESLint only lints the Typescript code, leaving any css unchecked. This is potentially problematic as it will allow errors to creep in to the css. stylelint and stylelint-order solve this problem,

Run this command in frontend/

npm install --save-dev stylelint stylelint-order stylelint-config-standard

These are configured by a stylelint section in the frontend/package.json file,

"stylelint": {
  "extends": [
    "stylelint-config-standard"
  ],
  "plugins": [
    "stylelint-order"
  ],
  "rules": {
    "order/properties-alphabetical-order": true,
    "declaration-block-trailing-semicolon": null,
    "declaration-colon-newline-after": null,
    "declaration-empty-line-before": null
  }
}

Linting command

Finnally this allows a lint (in frontend/package.json) command to be defined,

"scripts": {
  "lint": "eslint \"src/**/*.{ts,tsx}\"; stylelint \"src/**/*.{ts,tsx}\"",
}

and used,

Run this command in frontend/

npm run lint

Testing

The Create React App command used to setup the frontend also set up a testing command using jest,

Run this command in frontend/

npm run test

We'll alter the test command (in frontend/package.json) to add the --passWithNoTests option, in order for the tests to pass whilst there aren't any,

"scripts": {
  "test": "react-scripts test --passWithNoTests",
}

Bundle analysis

The frontend code will be delivered as bundles (in chunks) to the user. These bundles, especially the main bundle should be small so that the user isn't waiting too long for the code to be downloaded. To check the bundle size, and analyse what is included in each bundle I use source-map-explorer,

Run this command in frontend/

npm install --save-dev source-map-explorer

Which allows an analyse command to analyse the bundle sizes, via adding the following to the frontend/package.json file,

"scripts": {
   "analyse": "npm run build && source-map-explorer \"build/static/js/*.js\"",
   ...
}

and used

Run this command in frontend/

npm run analyse