- General
- Installation
- Build Process: Development
- Application Logic
- Flux Data Flow: An Overview
- Code Structure
- Additional Resources
- Node: 4.2.1
- NPM: 2.14.7
- React: 0.14.0
This application uses the following tools:
- Homebrew
- NVM
- Node.js 4.2.1
- npm 2.14.7
- Gulp and various Gulp plugins (gulp-imagemin, gulp-autoprefixer, etc.)
- React 0.14.6
- Alt
- Flux-style data management
- Webpack JavaScript compiler
- react-hot-loader Reload browser
# Recommend installing NVM
$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.30.1/install.sh | bash
# Install Node and NPM
$ nvm install v4.2.0
# Set Node default
$ nvm alias default v4.2.0
# clone the Git repository
$ git clone [email protected]:thebarbariangroup/pepsico-pepfeed.git
# change directory to the project folder
$ cd pepsico-pepfeed
# if node_modules folder is an alias, remove it
$ rm node_modules
# install the node modules
$ npm install
# build the code
$ gulp
In browser navigate to `localhost:3000`
Once the application is installed, you'll find everything in the app
folder:
app/
├── assets/
│ ├── fonts/
│ ├── icons/
│ ├── images/
│ ├── javascripts/
│ │ ├── App.js
│ │ ├── index.js
│ │ ├── __tests__/
│ │ ├── actions/
│ │ │ └── AppActions.js
│ │ ├── components/
│ │ ├── lib/
│ │ │ ├── alt.js
│ │ │ ├── Localization.js
│ │ │ ├── Config.js
│ │ │ └── API.js
│ │ ├── pages/
│ │ └── stores/
│ │ └── AppStore.js
│ ├── stylesheets/
│ │ ├── base/
│ │ ├── generated/
│ │ ├── components/
│ │ ├── mixins/
│ │ ├── pages/
│ │ ├── _components.scss
│ │ ├── _mixins.scss
│ │ ├── _pages.scss
│ │ ├── _base.scss
│ │ └── global.scss
│ └── localization/
│ └── en.json
└── views/
└── index.html (bare bone html file where the css/js are loaded )
public/
├── assets/
│ ├── fonts/
│ ├── localization/
│ └── stylesheets/
└── index.html
$ gulp
You may need to alias gulp
to node_modules/.bin/gulp
, or npm install -g gulp
.
Start editing assets and views from the gulp/assets
folder. Files compile to public
.
If you need to add a new route, add it to index.js
. Application bootstrapping described below:
boot·strap: /ˈbo͞otˌstrap/ a technique of loading a program into a computer by means of a few initial instructions that enable the introduction of the > rest of the program.
Once React loads and bundle.js is loaded into the browser, routing is handled client-side by the rules defined in React.render().
Add a 'page' and its route in the React.render()
method. Nest routes and add query parameters (e.g., :module
param in the URI /page/:sub-page
). Query parameters are passed into the rendered component as this.props.routeParams
.
We're using Alt.js, an implementation of Facebook's Flux architecture.
From app/assets/javascripts/lib/alt.js:
.__ __
_____ | |_/ |_
\__ \ | |\ __\
/ __ \| |_| |
(____ /____/\__|
\/
Alt: Isomorphic Flux Implementation
app/assets/javascripts/lib/alt.js
: creates an Alt/Flux instance to manage application data flow, from view to Action Creator to the store.
Example Data Flow via alt:
view --> action --> dispatcher --> store --> view
'use strict';
class AppActions {
constructor () {
this.generateActions(
'updateContent',
'toggleEditMode'
)
}
}
export default alt.createActions(AppActions)
'use strict';
class AppStore {
constructor () {
this.bindListeners({
updateContent: ActionCreator.UPDATE_CONTENT,
toggleEditMode: ActionCreator.TOGGLE_EDIT_MODE
})
}
...
updateContent(o) {
this.data[o.field] = o.value
}
}
export default alt.createStore(AppStore, 'AppStore');
'use strict';
import React, { Component } from 'react';
import AppStore from '../stores/AppStore';
import ActionCreator from '../actions/AppActions';
import UI from './UI';
export default class Widget extends UI {
constructor (props) {
super(props);
this.state = AppStore.getState();
this._onChange = () => {
this.setState( AppStore.getState() );
}
}
componentWillMount () {
AppStore.listen(this._onChange);
}
componentWillUnmount () {
AppStore.unlisten(this._onChange);
}
};
'use strict';
import ActionCreator from '../actions/AppActions';
import Widget from '../components/Widget';
...
this.updateContent (object) {
ActionCreator.updateContent(object)
},
...
...
<Widget onClick={ this.updateContent } />
Inside this file: /app/assets/stylesheets/_icons.scss
You will see all of the icons' names that exist within the /app/assets/images/icons
folder. Each name has the following syntax: icon-whatever-image-name
I add the precursor icon-
to associate icons that have short names, like Bookmarks
or Home
.
When we create new icons, we add them to the same icons folder. After adding them, you must create the classes and reference their corresponding mixin as follows:
.icon-Home {
@include get-sprite( Home );
}
This dynamically creates the icon, in retina, for the specified icon.
To use the icon within our DOM, I've created a JS Directive /app/assets/javascripts/components/Icon.js
. When you want to use an Icon, simply write within your JSX markup.
This will dynamically create the following syntax: <span className="icon icon-whatever-image-name"/>
I do this because if we want to change all Icons across the entire site, all we need to do is change this Icon.js file rather than going everywhere searching for all the instances.
More information on the following: