Synopsis

Javascript framework built on top of ReactJS and Redux. It should provide common application abstraction, basic routes, state initialization, error handling, dialogs, UI components and much more!

Motivation

This project is intended to enforce same versions of dependent libraries, provide coding style and standard, reusable components, common build/test/lint tools, basic routing, styling integration and utility functions.

Installation

Project can be found on Providus internal Nexus server.

npm install olaf --save

Core Concepts

In order to keep things organized in the same manner and provide common reasoning guidelines, we have introduced these concepts:

  • There are 4 types of components:
    • Layout
    • Container
    • View
    • UIComponent
  • Application main file should create routes
  • When building run both build and build:dev to ensure node_modules/olaf/dist
  • Each route is written as Layout component
  • Layout component does not render HTML but rather React Components (nested layout, containers and/or view components). This approach improves reasoning and readability.
  • Containers are Higher Order components that are connected with redux state and pass data and actions down to child components described in layout file. They should appear only on layout files to explicitly list relationships between data and views. Container should carry reducers, selectors and sagas if needed.
  • View Components are only dependent on props
  • UIComponent have internal state/logic not dependent on application data and/or state (ie TabPanel, Button...)
  • Modules are composition of components that can be reusable (any type: ie container module providing only data/actions. ie Header as composition of AuthContainer and HeaderView)

Create new olaf application

npm i -g create-olaf-app
create-olaf-app my-app
cd my-app

npm run start

Code Example

Example of new application entry file

import { createOlafApplication } from 'olaf';

import App from './containers/App';
import appReducer from './containers/App/reducer';
import appSagas from './containers/App/sagas';

createOlafApplication({
  name: 'app',
  thunk: true,
  hash: false,
  getRootDomElement: () => document.body.children[0],
  routes: [
    {
      path: '/',
      exact: false,
      component: App,
    },
  ],
  reducers: {
    app: appReducer,
  },
  sagas: {
    app: appSagas,
  },
});

Application properties

  • name - name of application | type: string | default: 'app'
  • hash - hash router history | type: boolean | default: false
  • thunk - use redux-thunk provided by redux toolkit | type: boolean | default: true
  • getRootDomElement - root element selector | type: function | default: null
  • rootReactComponent - main react app component | _type: Component | default: null | !!required!!
  • reducers - map of application reducers | type: object | default: {}
  • sagas - map of application sagas | type: object | default: {}
  • persistSetup - redux persist setup | type: object | default: null
  • reduxSagaMonitorOptions - sagaMiddleware config | type: object | default: {}

List of olaf exports

  • Application - class which create olaf application
  • createOlafApplication - function which create olaf application
  • injectReducer - reducer injector | (key, reducer)
  • injectSaga - saga injector | (key, saga)
  • fetch - fetch
  • resolveState - selector helper function
  • getAppName - application name selector

Provided dependencies

  • olaf
  • react
  • react-dom
  • react-redux
  • @reduxjs/toolkit
  • @reduxjs/toolkit/query
  • react-router
  • react-router-dom
  • connected-react-router
  • redux-persist
  • history
  • redux-saga
  • redux-saga/effects
  • redux-actions
  • normalizr

Standards, styles, tests, tools and workflow

  • eslint

    Base configuration for coding style is popular airbnb setup. Complete ruleset can be found on their official github page https://github.com/airbnb/javascript Providus guide to setup eslint and Visual Studio Code can be found here.

This implementation is done with babel -> eslint. We will create new configuration where we can override base and add custom rules if needed.

  • tests

    Read more about unit testing here.

  • git pre-commit hook. No commit is possible if:

    • eslint finds unresolved problems (these can be flagged out in code explicitly to make eslint pass and thus commit possible, but still remains in code as reminder that we need to update eslint ruleset for this case)
    • tests fail (More about the scope of the test can be found here)
    • build fails
  • Jenkins (Maybe?) When possible, we would like to execute same procedure as local pre-commit hook on Jenkins automatically after merge request.

  • Flow Static type checker that finds compile time errors. Enforce structures used, especially if shared structure (ie. BetSlip)

  • PropTypes Runtime type checker. Works only in development. Can be useful as flow (enforce structures used), but also provides runtime error logging for unexpected structure changes (ie. backend changes API)

  • JS Docs Generate documentation files from source code

Deploying a new version of Olaf

  1. Create your branch, make your changes, increment the version of Olaf in package.json before sending MR
  2. Once MR approved and merged, trigger the deployment of the pipeline on GitLab
  3. Within Olaf, delete the dist directory and any previous tarball generated version of Olaf at the project root, if any
  4. Run npm run build to have the latest production build within the project
  5. Run npm run build:dev to have the latest development build within the project
  6. Run npm pack within the root of the Olaf project => A versioned tarball file, corresponding to the package.json version, is generated
  7. Login to nexus and upload the generated tar file
  8. Using create-olaf-app, create your new project and the latest published version of Olaf on nexus will be used

Ideas we are working on

  • resolve routes dynamically based on directory structure in project
  • resolve automatic injections reducers, selectors and sagas
  • implement CLI to ease managing/generating/testing code (APPLICATION|MODULE, SKIN, DISPLAY_SIZE, RESOLUTION, ORIENTATION...)
  • unit testing (API testing, generating API test page, Business logic testing)
  • provide module abstractions
  • UIComponents
  • CSS in JS

License

Providus Technologies Limited