master | |
---|---|
dev | |
This project is part of the larger Logistics Wizard project.
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.
- Features
- Requirements
- Getting Started
- Application Structure
- Development
- Developer Tools
- Redux-cli
- Storybook
- Routing
- Testing
- Deployment
- Build System
- Configuration
- Root Resolve
- Globals
- Styles
- Server
- Production Optimization
- Learning Resources
- node
^4.2.0
- npm
^3.0.0
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:
First, clone or download:
$ git clone [email protected]:IBM-Cloud/logistics-wizard-webui.git
// or
$ wget -O logistics-wizard-webui.zip https://github.com/IBM-Cloud/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>
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>',
}
$ 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. |
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)
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.
npm install redux-cli --save-dev
TODO: Describe generating various components and routes with redux-cli
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.
With Storybook, you can design and code components in isolation.
npm run storybook
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
.
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).
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.
We use the staticfile_buildpack to deploy the client to IBM Cloud 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
- Manually Install Cloud Foundry and IBM Cloud CLI or use homebrew on Mac:
```bash
brew tap cloudfoundry/tap
brew install cf-cli
brew tap caskroom/cask
brew cask install bluemix-cli
```
- Connect and Login to Bluemix
ibmcloud api https://api.ng.bluemix.net
ibmcloud login -u <your username> -o <your org> -s <your space>
- Update the
host
key inmanifest.yml
to whatever you like - From now on, all you have to do is
cf push
- Visit
<hostname from manifest.yml>.mybluemix.net
to view your running app
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 |
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'
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. |
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.
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.
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.
TODO: post some links to blog posts / references once we write them
- Starting out with react-redux-starter-kit is an introduction to the components used in this starter kit with a small example in the end.