Skip to content

Development frontend

Tiffany edited this page Jul 22, 2022 · 8 revisions

Architecture

The front end is built in React, and uses the following major libraries:

  • CMS Design System for standard page components and styling. This helps our app be visually compatible with other CMS web apps.
  • jsonpatch for applying changes to redux state. When a state change arrives at the main APD data reducer, it computes a JSON Patch object and uses this handy library to apply it to the state. Saves us a bunch of trouble!
  • react-router for page routing. We use react-router beacuse it's pretty standard, well-documented, and well-supported.
  • redux for internal state management. It's not always perfect, but it's kind of the go-to standard for flux-like data flows. In the future, it might be useful to spend some time investigating something like redux-sagas to manage more complex action flows instead of managing a lot of complex logic in the actions themselves.
  • okta-auth-js for authenticating with Okta.
  • reselect for memoizing state selectors. Memoization is helpful to avoid repeating costly calculations if the inputs haven't changed.
  • Webpack for bundling the app into a deliverable. Because it's kinda the standard thing at the moment. We've got to turn all that JSX and Sass into browser-friendly code somehow!

We use Sass to build our styles. We also lean heavily on the CMS Design System.

For testing, we use Jest as the test runner and Enzyme and React-Testing-Library as a React renderers. We try to use Jest's stubs and mocks for testing now, but some of our older tests still use Sinon.js. We use Jest because it's a pretty good all-in-one framework, and its ability to capture snapshots makes it really nice for catching UI changes.

architecture-diagram

Building

Our front end is built using Webpack. We use the babel-loader along with the env plugin and the react and stage-2 Babel presets to build the Javascript parts of the app. We use the sass-loader, postcss-loader, css-loader, and mini-css-extract-plugin for our styles.

Webpack injects some environment variables into the front end code. For example, in the code, references to process.env.API_URL are replaced at build time with the actual value of that environment variable. Here's the full list of environment variables that gets replaced:

variable name purpose
API_URL The base URL to the API. default: null
IDLE_LOGOUT_TIME_MINUTES How long to allow the user's browser to sit idle before automatically logging them out. default:: 15

Production

In production, our configuration chunks vendored Javascript files, compiles our Sass, and copies a variety of files from static sources.

file/path where it comes from
index.html Entry page, copied directly from src/index.html, unchanged
app.[hash].js The React app and all necessary libraries (entrypoint is src/app.js)
app.css Our primary styles, built from Sass (entrypoint is src/styles/index.scss)
vendors~app.[hash].js Vendored code chunk, loaded at page load
vendors~zxcvbn.[hash].js zxcvbn chunk, loaded on-demand
static Images and other static resources, copied directly from src/static, unchanged

The Javascript file hashes are content hashes, so as long as our 3rd-party libraries don't change, the vendor files should stay the same and can be cached by users' browsers. Additionally, our Javascript is run through the webpack uglify plugin to minify it.

Development

In development, our configuration uses hot reloading to update the contents of the browser without having to reload the page. Our Sass is build into CSS, is injected into the app Javascript and is loaded via <script> tags, courtesy of the webpack style-loader

Clone this wiki locally