/logistics-wizard-webui

Primary LanguageJavaScriptOtherNOASSERTION

Logistics Wizard Web User Interface

master Build Status Coverage Status
dev Build Status Coverage Status

This project is part of the larger Logistics Wizard project.

Overview

This project is designed with a bunch of awesome new front-end technologies, all on top of a configurable, feature-rich webpack build system that's already setup to provide hot reloading, CSS modules with Sass support, unit testing, code coverage reports, bundle splitting, and a whole lot more, while providing amazing developer tools such as Redux CLI (a generator), Redux devtools (Chrome extension), and Storybook for visually developing and testing components.

Table of Contents

  1. Features
  2. Requirements
  3. Getting Started
  4. Application Structure
  5. Development
  6. Developer Tools
  7. Redux-cli
  8. Storybook
  9. Routing
  10. Testing
  11. Deployment
  12. Build System
  13. Configuration
  14. Root Resolve
  15. Globals
  16. Styles
  17. Server
  18. Production Optimization
  19. Learning Resources

Features

Requirements

  • node ^4.2.0
  • npm ^3.0.0

Getting Started

After confirming that your development environment meets the specified requirements, you can create a new project based on logistics-wizard-webui in one of two ways:

Install from source

First, clone or download:

$ git clone git@github.com:IBM-Bluemix/logistics-wizard-webui.git
// or
$ wget -O logistics-wizard-webui.zip https://github.com/IBM-Bluemix/logistics-wizard-webui/archive/master.zip
$ unzip logistics-wizard-webui.zip

Then, rename to your project name and change into the directory:

$ mv logistics-wizard-webui <my-project-name>
$ cd <my-project-name>

Set up env vars

Create a file called config/.env with the following data

module.exports = {
  controller_service: '<url to your controller api deployment or localhost>',
  google_maps_key: '<your google maps api key here>',
}

Install dependencies, and check to see it works

$ npm install                   # Install project dependencies
$ npm start                     # Compile and launch

If everything works, you should see the following:

While developing, you will probably rely mostly on npm start; however, there are additional scripts at your disposal:

npm run <script> Description
start Serves your app at localhost:3000. HMR will be enabled in development.
storybook Opens React Storybook at localhost:9001.
compile Compiles the application to disk (~/dist by default).
dev Same as npm start, but enables nodemon for the server as well.
dev:no-debug Same as npm run dev but disables devtool instrumentation.
test Runs unit tests with Ava and generates a coverage report.
test:dev Runs Ava and watches for changes to re-run tests; does not generate coverage reports.
test:dev-verbose Same as test:dev but with verbose test output.
check-coverage Returns true or false based on successful code coverage
coveralls Pipes lcov.info to coveralls process
deploy Runs linter, tests, and then, on success, compiles your application to disk.
deploy:dev Same as deploy but overrides NODE_ENV to "development".
deploy:prod Same as deploy but overrides NODE_ENV to "production".
lint Lint all .js files.
lint:fix Lint and fix all .js files. Read more on this.

Application Structure

The application structure presented in this project is fractal, where functionality is grouped primarily by feature rather than file type. Please note, however, that this structure is only meant to serve as a guide, it is by no means prescriptive. That said, it aims to represent generally accepted guidelines and patterns for building scalable applications. If you wish to read more about this pattern, please check out this awesome writeup by Justin Greenberg.

.
├── .storybook               # Config and root stories for React Storybook
├── bin                      # Build/Start scripts
├── blueprints               # Blueprint files for redux-cli
├── config                   # Project, build, and test configuration settings
│   └── webpack              # Environment-specific configuration files for webpack
├── server                   # Koa application (uses webpack middleware)
│   └── main.js              # Server application entry point
└── src                      # Application source code
    ├── index.html           # Main HTML page container for app
    ├── main.js              # Application bootstrap and rendering
    ├── components           # Reusable Presentational Components
    ├── containers           # Reusable Container Components
    ├── layouts              # Components that dictate major page structure
    ├── modules              # reducer, action, creators not part of a route
    ├── routes               # Main route definitions and async split points
    │   ├── index.js         # Bootstrap main application routes with store
    │   └── Home             # Fractal route
    │       ├── index.js     # Route definitions and async split points
    │       ├── assets       # Assets required to render components
    │       ├── components   # Presentational React Components
    │       ├── container    # Connect components to actions and store
    │       ├── modules      # Collections of reducers/constants/actions
    │       └── routes **    # Fractal sub-routes (** optional)
    ├── services             # API wrappers
    ├── static               # Static assets (not imported anywhere in source code)
    ├── store                # Redux-specific pieces
    │   ├── createStore.js   # Create and instrument redux store
    │   ├── reducers.js      # Reducer registry and injection
    │   └── sagas.js         # Saga registry and injection
    └── styles               # Application-wide styles (generally settings)

Development

Developer Tools

We recommend using the Redux DevTools Chrome Extension. Using the chrome extension allows your monitors to run on a separate thread and affords better performance and functionality. It comes with several of the most popular monitors, is easy to configure, filters actions, and doesn’t require installing any packages.

redux-cli

npm install redux-cli --save-dev

TODO: Describe generating various components and routes with redux-cli

Routing

We use react-router route definitions (<route>/index.js) to define units of logic within our application. See the application structure section for more information.

Storybook

With Storybook, you can design and code components in isolation.

npm run storybook

Testing

To add a unit test, simply create a .test.js file anywhere in ~/src. Ava will pick up on these files automatically. If you are using redux-cli, test files should automatically be generated when you create a component or route. If you wish to change test file locations or settings you may do so within the ava object in ~/package.json.

Coverage reports will be compiled to ~/coverage by default. If you wish to change what reporters are used and where reports are compiled, you can do so by modifying the nyc object in ~/package.json.

Deployment

Out of the box, this project is deployable by serving the ~/dist folder generated by npm run deploy (make sure to specify your target NODE_ENV as well).

Static Deployments

Whether you are serving the application via node or a web server such as nginx, make sure to direct incoming routes to the root ~/dist/index.html file and let react-router take care of the rest. The Koa server that is being used as the dev server can be extended to host the app and serve as an API or whatever else you need, but that's entirely up to you.

Bluemix

We use the staticfile_buildpack to deploy the client to Bluemix with an nginx web server. In order to override the default nginx.conf provided by the buildpack, we simply copied the provided config from the buildpack repo and added the try_files directive:

...
location / {
  root <%= ENV["APP_ROOT"] %>/public;
  + try_files $uri $uri/ /index.html;
  ...

Deploy Instructions

  1. Manually Install Cloud Foundry and Bluemix CLI or use homebrew on Mac:
```bash
brew tap cloudfoundry/tap
brew install cf-cli
brew tap caskroom/cask
brew cask install bluemix-cli
```
  1. Connect and Login to Bluemix
bluemix api https://api.ng.bluemix.net
bluemix login -u <your username> -o <your org> -s <your space>
  1. Update the host key in manifest.yml to whatever you like
  2. From now on, all you have to do is
cf push
  1. Visit <hostname from manifest.yml>.mybluemix.net to view your running app

Build System

Configuration

Default project configuration can be found in ~/config/index.js. Here you'll be able to redefine your src and dist directories, adjust compilation settings, tweak your vendor dependencies, and more. For the most part, you should be able to make changes in here without ever having to touch the actual webpack build configuration.

If you need environment-specific overrides (useful for dynamically setting API endpoints, for example), you can edit ~/config/environments.js and define overrides on a per-NODE_ENV basis. There are examples for both development and production, so use those as guidelines. Here are some common configuration options:

Key Description
dir_src application source code base path
dir_dist path to build compiled application to
server_host hostname for the Koa server
server_port port for the Koa server
compiler_css_modules whether or not to enable CSS modules
compiler_devtool what type of source-maps to generate (set to false/null to disable)
compiler_vendor packages to separate into to the vendor bundle

Root Resolve

Webpack is configured to make use of resolve.root, which lets you import local packages as if you were traversing from the root of your ~/src directory. Here's an example:

// current file: ~/src/views/some/nested/View.js
// What used to be this:
import SomeComponent from '../../../components/SomeComponent'

// Can now be this, HORRAY!:
import SomeComponent from 'components/SomeComponent'

Globals

These are global variables available to you anywhere in your source code. If you wish to modify them, they can be found as the globals key in ~/config/index.js. When adding new globals, make sure you also add them to ~/.eslintrc.

Variable Description
process.env.NODE_ENV the active NODE_ENV when the build started
__DEV__ True when process.env.NODE_ENV is development
__PROD__ True when process.env.NODE_ENV is production
__TEST__ True when process.env.NODE_ENV is test
__DEBUG__ True when process.env.NODE_ENV is development and cli arg --no_debug is not set (npm run dev:no-debug)
__BASENAME__ history basename option
__CONTROLLER_API__ The API endpoint for the Logistics Wizard Controller. It is initialized from process.env.CONTROLLER_SERVICE variable specified as https://host:port. The Controller API prefix /api/v1/ is added automatically.

Styles

Both .scss and .css file extensions are supported out of the box and are configured to use CSS Modules. After being imported, styles will be processed with PostCSS for minification and autoprefixing, and will be extracted to a .css file during production builds.

Server

This starter kit comes packaged with an Koa server. It's important to note that the sole purpose of this server is to provide webpack-dev-middleware and webpack-hot-middleware for hot module replacement. Using a custom Koa app in place of webpack-dev-server makes it easier to extend the starter kit to include functionality such as API's, universal rendering, and more -- all without bloating the base config.

Production Optimization

Babel is configured to use babel-plugin-transform-runtime so transforms aren't inlined. Additionally, in production, we use react-optimize to further optimize your React code.

In production, webpack will extract styles to a .css file, minify your JavaScript, and perform additional optimizations such as module deduplication.

Learning Resources

TODO: post some links to blog posts / references once we write them