Trinity Frontend — 2018
Frontend for the 2018 rewrite. Powered by React and good style.
Table of Contents
- Installation & Setup
- Stack Overview
- Project Structure
- Available Scripts
- Git Strategy
- Creating Issues
- Docs Todos
- Node v8.11.3
npm install && npm start
Assuming you have Node 8.11.3 installed on your machine,
cd into the directory you want to clone the project, and copy, paste, and run the following:
git clone <REDACTED> && cd <REDACTED> && npm install && npm start
Installing Node & Nodenv
This project uses Node 8.11.3.
We recommend you install via the "Basic Github Checkout" option instead of Homebrew. Windows Subsystem for Linux note: Modify your
~/.profile instead of
~/.profile seems to be the default shell profile in WSL (or at least, this was our experience while installing Nodenv on Tyler's computer).
Installing the Project
Once you've installed 8.11.3,
cd into the directory in which you want to clone this repo and run:
If you're using nodenv, it will utilize the
.node-version file in the repo to know what Node version (8.11.3) to use for all Node/NPM commands you run — no manual version switching required.
Lastly, install all the project dependencies with
You can ensure everything is working properly by running
npm start — you should see the app build in your shell and then your web browser should open automatically. If it doesn't, refer to the Troubleshooting section below.
Use: UI Layer
React is one of the best modern JS libraries for creating user interfaces. Its "learn once, write anywhere" approach is really powerful, especially here at Trinity where we have multiple interfaces, including multiple web applications and multiple mobile applications.
- React Docs - The docs are really good.
- React for Beginners - Course by Wes Bos. Everything you need to know to understand how React works and reason about React components.
- Awesome React - A collection of awesome things in the React ecosystem.
- ES6 for Everyone - Course by Wes Bos. Also includes ES7 and ES8.
- You Don't Know JS - Book Series by Kyle Simpson.
Use: State Management
Redux was chosen for state management for three main reasons:
It's predictable. We're able to determine what the state of our app will be at any given point with a high degree of certainty. This gives us confidence in our UI and also makes things really easy to test (since everything dealing with state is a pure function).
The developer experience is amazing. Because we have an immutable state tree, we are able to have nice things. Like a Time Traveling Debugger.
It's very well documented. Redux has been around for 3 years now, which is forever in the world of frontend. It's battle-tested, and there's a ton of articles, videos, and helpful chatrooms if we are ever stuck on something or have a specific use case we want to learn more about. This is really important since there are currently only two people who have experience with this stack and they're both juniors.
Why not just use React's Context API?
This was considered, but ultimately the immutability, dev tools, and documentation made Redux the winner. Plus, sticking to React's internal state management would still make us reach for a helper library when dealing with async operations. Redux Thunk makes this very easy.
- Redux Docs - These are really good, too. Dan Abramov knows how to make good documentation.
- Redux & React For Everyone - Perhaps the single best course I've found for quickly learning Redux. Pair it with his React 16 For Everyone course before doing the Redux one for power levels over 9000.
- Learn Redux - Great course from Wes Bos. A little out of date in terms of the API, but still great for grasping the concepts.
Parcel is a zero-configuration bundler. Out of the box, it has code splitting, hot module replacement, automatic transforms, friendly error logging, and it bundles pretty much any type of asset you throw at it. It's also really fast.
Parcel was chosen over Webpack simply because of time constraints. Webpack may very well be used in the future, but Parcel allowed us to get up and running much faster.
- Parcel Website - The docs are pretty good.
- Parcel on GitHub
- Exploring the Parcel Application Bundler - Video by Traversy Media
There was a lot of things to consider in terms of CSS. An overwhelming amount, actually:
Ultimately, here's what we went with and why:
Material UI — Material seemed to be a great choice based on the bandwidth our [one] designer, Ryan, has. We may hit the big leagues one day and have our own design system, but for now Material provides a ton of great designs and microinteractions that would require a lot of time to design and build out from scratch. To date, we are using base material elements.
Styled Components - Styled Components is a CSS-in-JS library that makes writing CSS in React a pure joy. Material UI integrates really well with it as well.
Flexbox and CSS Grid - There's good support for these, except not fully in IE11 (but they are nearly fully supported in IE11). Just be sure to test in IE and reference their known bugs (see Flexbox and CSS Grid on Can I Use).
Things to still consider in the future:
- To BEM, or not to BEM?
- ITCSS? (a fantastic way to keep specificity low, even with a YUGE codebase - may not be necessary since Styled Components inherently solves scoping collisions)
- Material UI
- Styled Components
- CSSGrid.io - Fantastic course by Wes Bos.
- What the Flexbox - Course by Wes Bos. The best way I've found to learn Flexbox.
Our testing library of choice is Jest.
- Jest Docs
Storybook is a development environment for UI components. It allows you to browse a component library, view the different states of each component, and interactively develop and test components. Really improves team productivity and efficiency, especially between frontend engineers and designers.
- Storybook Docs - Detailed docs!
- Learn Storybook - The best Storybook tutorial I could find.
- Marie-Laure Thuret - React Storybook: Design, Dev, Doc, Debug Components - React Conf 2017
- Create Powerful Interactive Style Guides With The Power Of React Storybook (English)
- Adding Storybook Style Guide to a Create React App
Linters, Type Checkers, Editor Configuration
For type checking, we are currently using React's Prop Types, although we also have Flow integrated (in a very basic way). Flow is a static type checking library that allows you to type both your props and your state, as well as catch issues very early instead of at runtime. The goal is to migrate our typing to Flow after finishing Parts Ordering.
- We also use Flow-Typed to install libraries (when Flow-Typed has support for it) so we can utilize Flow to know when we are using a library incorrectly.
My editor of choice is currently Visual Studio Code. Here's a link to my settings (some of the settings are specific to me — if you are unsure, just ask!).
Here's the relevant extensions I have installed:
And here's the other extensions I have installed, in case you're curious:
- Git History
- Live Server
- Night Owl
- Path Intellisense
- React Pure to Class
- React-Native/React/Redux snippets for ES6/ES7
- React-Native/React/Redux Snippets for ES6/ES7 Standard
- VS Live Share
The main folder of concern is
src. It contains the entire source of the app. We use feature folders, here's an example:
src/auth ├── PrivateRoute.js ├── actions.js ├── authService.js ├── config.js ├── constants.js ├── reducer.js └── setAuthorizationHeader.js
As you can see, everything needed for auth can be found in this one folder, including components, reducers, actions, helper functions, etc.
Uses Concurrently to start the mock-api, storybook, and parcel dev server.
// package-json "dev": "concurrently \"npm:json\" \"npm:storybook\" \"npm:start\"",
npm run json
Spins up a mock API via the json-server package. Data is loaded from
// package.json "json": "json-server --watch ./test-data/db.json --routes ./test-data/routes.json",
Builds the app, runs the development server, and opens your default web browser to http://localhost:1234.
//package.json "start": "parcel ./public/index.html --open",
npm run build
Builds the app in production mode (minifies, uglifies, disables Hot Module Replacement). Output is found in
//package.json "build": "parcel build ./public/index.html",
npm run lint
Runs ESLint on the codebase and outputs any warnings or errors. Note that it does not fix the issues.
//package.json "lint": "eslint .",
npm run lintfix
Runs ESLint and automagically fixes violations, where possible.
//package.json "lintfix": "eslint . --fix",
npm run flow
Runs Flow on the codebase and reports any Type errors.
//package.json "flow": "flow",
Runs tests with Jest.
//package.json "test": "jest",
npm run storybook
Starts Storybook at http://localhost:6006.
//package.json "storybook": "start-storybook -p 6006",
npm run build-storybook
Builds storybook into a static, production-ready bundle and outputs the build into
/storybook-static. This folder currently automatically deploys to https://idpbp-storybook.netlify.com/ every time there's a push to
//package.json "build-storybook": "build-storybook --output-dir dist-storybook",
npm run fixparcel
.cache directory and starts Parcel. Useful if the app starts randomly failing to load in development mode and is outputting obscure errors. (See this question in the Troubleshooting section)
//package.json "fixparcel": "rm -rf ./cache && npm start"
- Production Branch:
master(do not push directly to this branch)
- When working on a feature or fix, create a branch with your name + a short description of the feature:
- Do not push directly to
- When you're ready to merge a branch, make a Pull Request, assign a reviewer (J.C. or Tyler), and assign it to J.C.
- Ensure your commits are relevant to the branch you are on
When should I create an issue?
TL;DR — Create an issue.
- Something need to be done? Create an issue.
- Got an idea for an enhancement? Create an issue.
- Something broken that wasn't before? Create an issue.
- Something missing from the docs? Create an issue.
- Describe how to reproduce the issue in detail. Be descriptive — err on the side of more details.
- Provide relevant logs, code, etc.
- Screenshots are great!
- Screencasts are even better!
Parcel is building successfully, but I'm getting obscure errors in my browser console and a blank screen.
If the frontend suddenly serves a blank page, try deleting the
.cache folder and re-running
npm start (or you can run
npm run fixparcel as a shortcut) — there's currently an occasional issue with Parcel that may cause this. It doesn't happen often, and typically only occurs when installing new packages (but not every time ¯\_(ツ)_/¯).
I'm getting a
Command not found error when attempting to run a script from a package that is installed in
Sometimes you may want to run
parcel as a standalone command in your shell. If you get a
Command not found error, double check the package is installed globally. For example, if you're trying to run
parcel, you can run
npm install -g parcel to install Parcel globally.
If that doesn't fix the issue, try running