Skip to content

Instantly share code, notes, and snippets.

@kasper573
Created April 10, 2018 20:38
Show Gist options
  • Save kasper573/4d614f39cb5faaf6ebeb247d8ac574d6 to your computer and use it in GitHub Desktop.
Save kasper573/4d614f39cb5faaf6ebeb247d8ac574d6 to your computer and use it in GitHub Desktop.

Application structure

This document explains how the application code flows and is structured, ie. "what code goes where" and teaches you application specific terminology.

The application is a Single Page Application bundled by webpack.

Webpack outputs an index.html with the script tags required to bootstrap the application already embedded. All required assets and scripts will be output to the dist folder. To serve the application simply serve the dist folder.

In development we use webpack-dev-server to automate this process, so this is something that you only need to care about if working with the build or deployment infrastructure.

In production we also render the application server side to improve SEO (see server.tsx).

Webpack

Our application uses one common webpack.config.ts that is configured via --env.<optionName> <optionValue>. See BuildOptions for options. Make sure you have webpack and webpack-dev-server installed globally for an optimal work flow.

npm install -g webpack webpack-dev-server
  • Run webpack-dev-server --env.<optionName> <optionValue> to run the dev server with fine tuned options.
  • Run webpack --env.<optionName> <optionValue> to create a build with fine tuned options (this is what CI does)

Recommendations

A recommended preconfigured webpack-dev-server can be used by simply running:

npm run dev-server

However, you are encouraged to fine tune the dev-server to your daily and situational needs (ie. when polishing UI you often don't need source maps, so disabling them will decrease built times and thus improve your work flow).

Application flow

index.pug -> client.tsx -> App.tsx

The above sequence illustrates in which order key code files act to bootstrap the application. Down below follows an in depth explanation of each step.

<rootDir>/src/entries/index.pug

The entry point of the browser.

This is a PUG template that generates index.html. We prefer a template over a plain index.html primarily for convenience together with HtmlWebpackPlugin.

<rootDir>/src/entries/client.tsx

The entry point of the application.

  • Initializes application state
  • Sets up global behaviors
  • Sets up HMR in development.
  • Renders App.tsx.

<rootDir>/src/content/app/App.tsx

The root react component.

Sets up application behaviors and context providers.

Noteworthy folders and files

The codebase is separated into specific folders, each with a singular purpose.

<rootDir>/docs

This documentation.

<rootDir>/dev/

Development code. Tools that aid your dev workflow. Not part of the deployed application.

May not use application code (don't import from <rootDir>/src).

<rootDir>/src

Application code. Everything that makes up the deployed application.

May not use development code (don't import from <rootDir>/dev).

This is a webpack module folder: This means <rootDir>/src behaves like node_modules.

This enables convenient import expressions like require('assets/logo.svg').

<rootDir>/src/entries

Webpack entries.

Some entries act as plug ins for the application (ie. raven.ts, while others are completely independent variants of the application (ie. sitemap.ts.

You can find more documentation about each entry in their respective file.

<rootDir>/src/assets

All assets that the application uses.

Example asset usage:

const style = {
  backgroundImage: `url(${require('assets/images/foo.jpg')})`
}

Note that assets load differently depending on their type. See webpack.config.tsx for a detailed list of asset loaders to get an insight in how each asset loads.

<rootDir>/src/assets/fonts.ts

The fonts defined here are automatically loaded in main.tsx.

Example font usage:

import {fonts} from 'assets/fonts';
const style = {
  fontFamily: fonts.Default
};

Never specify fonts inline. Always reference the fonts variable.

<rootDir>/src/config

Configuration files like routes and buildOptions.

<rootDir>/src/content

This is the bulk code of the application, where everything comes together and creates the application.

If content exceeds a single file in complexity, create a folder and name the files <contentName>/<contentName><something>.tsx.

Example:

  • <rootDir>/src/content/browse/Browse.tsx
  • <rootDir>/src/content/browse/BrowseCard.tsx
  • <rootDir>/src/content/browse/BrowseFoo.tsx

<rootDir>/src/state

State code. See state.md for more information.

<rootDir>/src/forms

We create forms using a factory pattern.

  • Each form requires its own factory function named create<Name>Form, exported from a file of the same name.
  • The function is passed a reference to the I18nStore so that labels can be internationalized.

Example:

// src/forms/createTestForm.ts
export function createTestForm (i18n: I18nStore) {
  return new Form({
    email: {
      label: i18n.format('common.field.label.email'),
      rules: 'required'
    }
  });
}

<rootDir>/src/ui

Common reusable UI code, primarily react components.

Complex components

If a component exceeds one file in complexity, create a folder and name the files <moduleName>/<moduleName><something>.tsx.

Example:

  • <rootDir>/src/ui/chatbox/Chatbox.tsx
  • <rootDir>/src/ui/chatbox/ChatboxMessage.tsx
  • <rootDir>/src/ui/chatbox/ChatboxUsername.tsx

Component series

If a component is part of a series (ie. many buttons), create a folder and name the files <seriesName>/<variationName><seriesSubject>.tsx.

Example:

  • <rootDir>/src/ui/buttons/CommonButton.tsx
  • <rootDir>/src/ui/buttons/WideButton.tsx
  • <rootDir>/src/ui/buttons/SmallButton.tsx

Component categories

If a component is part of a category (ie. components with animations), create a folder and name the files <categoryName>/<moduleName>.tsx.

The category convention should only be used when your ui code fits neither of the above conventions but still justifies its own structure.

Example:

  • <rootDir>/src/ui/animations/Morph.tsx
  • <rootDir>/src/ui/animations/Collapse.tsx
  • <rootDir>/src/ui/animations/Sequencer.tsx

Core components

If a component falls under none of the above conventions it should be generic enough to be regarded as a core component and should reside directly under <rootDir>/src/ui

<rootDir>/src/ui/demos/index.tsx

A list of ui component demos.

Thanks to the modular nature of react components it is easy to demonstrate and unit test each component independently.

When to set up demos for UI components has no clear guideline, but it's recommended to develop new ui components using the demo interface. That way you will get demos and tests essentially for free.

Read more about the benefits of and how to create component demos in demos/index.tsx)

<rootDir>/src/lib

Standalone libraries being incubated in this project.

This folder exists purely for convenience so we don't have to maintain separate npm projects for each library.

Must be truly standalone (May only depend on npm modules and other code in lib)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment