Skip to content

Instantly share code, notes, and snippets.

@liberium
Last active December 5, 2018 11:12
Show Gist options
  • Save liberium/5a3b55fd4d95083e34b7c28252b57a2c to your computer and use it in GitHub Desktop.
Save liberium/5a3b55fd4d95083e34b7c28252b57a2c to your computer and use it in GitHub Desktop.
JS/React Coding Codex

JS/React Coding Codex

Module structure

ES module is a .js file with at least one export or folder containing index.js with at least one export.
The guiding module structure design principle is: you should imagine that any module might be extracted to its own package some day.

Module names are in kebab-case

First, file paths in MacOS and Windows are case-insesitive. Developer on MacOS could misspell a component module named SignUpForm as components/SignupForm/ then import {SignUpForm} from '@app/components' and not to get an error. After changes are pushed to the CI, it will crash with an error if being run on GNU/Linux, where file paths are case-sensitive.
Second, see the guiding principle. Package name cannot contain uppercase letters. Therefore, camelCase should never be used. This leaves snake_case and kebab-case.
kebab-case is by far the most common convention today. The only use of underscores is for internal node packages, and this is simply a convention from the early days.

The module structure follows this scheme:

components/ — exports presentational components; has no default export
containers/ — exports container components; has no default export
store/ — exports the store object by default
  actions/ — exports Redux async action creators; has no default export
  reducers/ — exports Redux reducers; exports the root reducer by default
  sagas/ — (if redux-saga is used) exports Redux sagas; exports the root saga by default
  epics/ — (if redux-observable or redux-most is used) exports Redux epics; exports the root epic by default
api/ — exports the api object by default
utils/ — export utility functions; has no default export
style/ — exports fonts, colors, dimensions objects; has no default export
  fonts — exports fonts object by default
  colors — exports colors object by default
  dimensions — exports dimensions object by default
i18n/ — exports an object with translated messages by locale by default
main — exports a reference to the mounted app by default

package.json contains property "main": "src".

The main field is a module ID that is the primary entry point to the program. That is, if a package is named foo, and a user installs it, and then does require("foo"), then the main module’s exports object will be returned.
We define it in order to facilitate publishing of the app in private NPM repo for embedding in another app.

The src module is aliased as @app-name

This way we import modules of the app as if we had them published in a scoped NPM package. Later we could publish that package in a private NPM repo. This supports the guiding principle and facilitates the code reuse across apps being deleloped by an organisation.

React component structure

Component module structure is flat.

There are no nested component modules.

Component naming follows this scheme

Component props naming follows this scheme

Component methods naming follows this scheme

Infrastructure

Babel, Jest, ESLint, Prettier are configured in package.json.

The motivation for this is a mixture of keeping the project root clean and keeping static configuration all in one place. This approach becomes more common in the JS community with time.2

There are Git hooks for commit and push

They should be configured in package.json:

  "devDependencies": {
    "husky": "^1.2.0"
  },
  "husky": {
    "hooks": {
      "pre-commit": "eslint . && jest --passWithNoTests --lastCommit",
      "pre-push": "yarn build"
    }
  }

App folder contains these configuration files

.env
.env.local
.editorconfig
.nvmrc
.gitignore
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment