New boilerplate
This commit is contained in:
23
README.md
23
README.md
@@ -1,38 +1,31 @@
|
|||||||
## React FLUX Boilerplate
|
## React FLUX Boilerplate
|
||||||
|
|
||||||
Based on the architecture suggestions from Facebook, this boilerplate will help you deal with it. It has included the
|
Based on the architecture suggestions from Facebook, this boilerplate will help you deal with it. It has included the flux-react extension to React JS, [flux-react](https://github.com/christianalfoni/flux-react).
|
||||||
flux-react extension to React JS. Read more about FLUX over at [Facebook Flux](http://facebook.github.io/flux/) and I wrote a post about it too: [React JS and FLUX](http://christianalfoni.github.io/javascript/2014/08/20/react-js-and-flux.html).
|
|
||||||
|
Read more about FLUX over at [Facebook Flux](http://facebook.github.io/flux/) and I wrote a post about it too: [React JS and FLUX](http://christianalfoni.github.io/javascript/2014/08/20/react-js-and-flux.html).
|
||||||
|
|
||||||
### How to use
|
### How to use
|
||||||
|
|
||||||
* Clone the repo
|
* Clone the repo
|
||||||
* Run `npm install`
|
* Run `npm install`
|
||||||
* Open `dev/index.html`, run `python -m SimpleHTTPServer` in the `dev` folder or set up your own server
|
* Open `build/index.html`, run `python -m SimpleHTTPServer` in the `build` folder or set up your own server
|
||||||
|
|
||||||
### Development
|
### Development
|
||||||
* Run `gulp`
|
* Run `gulp`
|
||||||
* Any changes to `app` or `styles` folder will automatically rebuild to `dev` folder
|
* Any changes to `app` folder will automatically rebuild to `build` folder
|
||||||
|
|
||||||
### Tests
|
|
||||||
* Run `gulp test -'./tests/App-test.js'
|
|
||||||
* Open `test.html`
|
|
||||||
* Any changes done to the test file or files in `app` folder will autoreload the browser
|
|
||||||
|
|
||||||
### Run all tests with Karma
|
### Run all tests with Karma
|
||||||
* Run `npm test`
|
* Run `npm test`
|
||||||
|
|
||||||
Karma will launch PhantomJS and run the tests once. If you need to run tests in a GUI browser, either change `karma.conf.js` to use Chrome or Firefox, or manually start it with:
|
Karma will launch PhantomJS and run the tests once. If you need to run tests in a normal browser change karma.conf.js to use 'Chrome' as browser. You can also keep running the tests as you write them. Set `autoWatch: true` and `singleRun: false`.
|
||||||
`./node_modules/karma/bin/karma start --single-run --browsers Chrome`
|
|
||||||
|
|
||||||
### Minify the code, ready for production
|
### Minify the code, ready for production
|
||||||
* Run `gulp deploy`
|
* Run `gulp deploy` to deploy to `dist` folder
|
||||||
|
|
||||||
### Directory
|
### Directory
|
||||||
* **app/**: Where you develop the application
|
* **app/**: Where you develop the application
|
||||||
* **dev/**: Where your automatically builds to. This is where you launch your app in development
|
* **build/**: Where your automatically builds to. This is where you launch your app in development
|
||||||
* **dist/**: Where the deployed code exists, ready for production
|
* **dist/**: Where the deployed code exists, ready for production
|
||||||
* **utils/**: Gulp tasks and other utils
|
|
||||||
* **styles/**: Where you put your css files
|
|
||||||
* **tests/**: Where you put your test files
|
* **tests/**: Where you put your test files
|
||||||
* **gulpfile**: Gulp configuration
|
* **gulpfile**: Gulp configuration
|
||||||
* **karma.conf.js**: Karma configuration
|
* **karma.conf.js**: Karma configuration
|
||||||
|
|||||||
BIN
app/.DS_Store
vendored
BIN
app/.DS_Store
vendored
Binary file not shown.
10
app/App.js
10
app/App.js
@@ -1,5 +1,5 @@
|
|||||||
/** @jsx React.DOM */
|
/** @jsx React.DOM */
|
||||||
var React = require('flux-react');
|
var React = require('react');
|
||||||
var Checkboxes = require('./components/Checkboxes.js');
|
var Checkboxes = require('./components/Checkboxes.js');
|
||||||
var NameThrower = require('./components/NameThrower.js');
|
var NameThrower = require('./components/NameThrower.js');
|
||||||
|
|
||||||
@@ -8,8 +8,12 @@ var App = React.createClass({
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>Hello world!</h1>
|
<h1>Hello world!</h1>
|
||||||
<Checkboxes/>
|
<div>
|
||||||
<NameThrower/>
|
<Checkboxes/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<NameThrower/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
EVENT_CHANGE: 'change'
|
|
||||||
};
|
|
||||||
5
app/actions.js
Normal file
5
app/actions.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = flux.createActions([
|
||||||
|
'checkAll',
|
||||||
|
'uncheckAll',
|
||||||
|
'check'
|
||||||
|
]);
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
'CHECK_ALL': 'check all',
|
|
||||||
'UNCHECK_ALL': 'uncheck all',
|
|
||||||
'CHECK': 'check'
|
|
||||||
};
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
/** @jsx React.DOM */
|
/** @jsx React.DOM */
|
||||||
var React = require('flux-react');
|
var React = require('react');
|
||||||
var Constants = require('../Constants.js');
|
var flux = require('flux-react');
|
||||||
|
var actions = require('./../actions.js');
|
||||||
var ColoredCheckbox = require('./Checkboxes/ColoredCheckbox.js');
|
var ColoredCheckbox = require('./Checkboxes/ColoredCheckbox.js');
|
||||||
var CheckboxActions = require('../actions/CheckboxActions.js');
|
|
||||||
var CheckboxStore = require('../stores/CheckboxStore.js');
|
var CheckboxStore = require('../stores/CheckboxStore.js');
|
||||||
|
|
||||||
var Checkboxes = React.createClass({
|
var Checkboxes = React.createClass({
|
||||||
@@ -12,36 +12,44 @@ var Checkboxes = React.createClass({
|
|||||||
checkboxes: CheckboxStore.getCheckboxes()
|
checkboxes: CheckboxStore.getCheckboxes()
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
storesDidUpdate: function () {
|
componentWillMount: function () {
|
||||||
|
CheckboxStore.addChangeListener(this.update);
|
||||||
|
},
|
||||||
|
componentWillUnmount: function () {
|
||||||
|
CheckboxStore.removeChangeListener(this.update);
|
||||||
|
},
|
||||||
|
update: function () {
|
||||||
this.setState({
|
this.setState({
|
||||||
checkboxes: CheckboxStore.getCheckboxes()
|
checkboxes: CheckboxStore.getCheckboxes()
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
check: function (color) {
|
check: function (color) {
|
||||||
React.dispatch({
|
actions.check(color);
|
||||||
type: CheckboxActions.CHECK,
|
|
||||||
color: color
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
checkAll: function () {
|
checkAll: function () {
|
||||||
React.dispatch({
|
actions.checkAll();
|
||||||
type: CheckboxActions.CHECK_ALL
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
uncheckAll: function () {
|
uncheckAll: function () {
|
||||||
React.dispatch({
|
actions.uncheckAll();
|
||||||
type: CheckboxActions.UNCHECK_ALL
|
},
|
||||||
});
|
renderCheckbox: function (checkbox, index) {
|
||||||
|
return <ColoredCheckbox
|
||||||
|
key={index}
|
||||||
|
color={checkbox.color}
|
||||||
|
checked={checkbox.checked}
|
||||||
|
onChange={this.check}/>
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var checkboxes = this.state.checkboxes.map(function (checkbox, index) {
|
var checkboxes = this.state.checkboxes.map(this.renderCheckbox);
|
||||||
return <ColoredCheckbox key={index} color={checkbox.color} checked={checkbox.checked} onChange={this.check}/>
|
|
||||||
}, this);
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{checkboxes}
|
<div>
|
||||||
<button onClick={this.checkAll}>Check all</button>
|
{checkboxes}
|
||||||
<button onClick={this.uncheckAll}>Uncheck all</button>
|
</div>
|
||||||
|
<div>
|
||||||
|
<button onClick={this.checkAll}>Check all</button>
|
||||||
|
<button onClick={this.uncheckAll}>Uncheck all</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
/** @jsx React.DOM */
|
/** @jsx React.DOM */
|
||||||
var React = require('flux-react');
|
var React = require('react');
|
||||||
|
|
||||||
var ColoredCheckbox = React.createClass({
|
var ColoredCheckbox = React.createClass({
|
||||||
|
changeColor: function () {
|
||||||
|
this.props.onChange(this.props.color);
|
||||||
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var style = {
|
var style = {
|
||||||
backgroundColor: this.props.color,
|
backgroundColor: this.props.color,
|
||||||
@@ -10,7 +13,7 @@ var ColoredCheckbox = React.createClass({
|
|||||||
return (
|
return (
|
||||||
<span key={this.props.key} style={style}>
|
<span key={this.props.key} style={style}>
|
||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
onChange={this.props.onChange.bind(null, this.props.color)}
|
onChange={this.changeColor}
|
||||||
checked={this.props.checked}/>
|
checked={this.props.checked}/>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,35 +1,44 @@
|
|||||||
/** @jsx React.DOM */
|
/** @jsx React.DOM */
|
||||||
var React = require('flux-react');
|
var React = require('react');
|
||||||
var Constants = require('../Constants.js');
|
|
||||||
var CheckboxStore = require('../stores/CheckboxStore.js');
|
var CheckboxStore = require('../stores/CheckboxStore.js');
|
||||||
|
|
||||||
var NameThrower = React.createClass({
|
var NameThrower = React.createClass({
|
||||||
stores: [CheckboxStore],
|
|
||||||
getInitialState: function () {
|
getInitialState: function () {
|
||||||
return {
|
return {
|
||||||
name: '',
|
name: '',
|
||||||
colors: CheckboxStore.getColors()
|
colors: CheckboxStore.getColors()
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
storesDidUpdate: function () {
|
componentWillMount: function () {
|
||||||
|
CheckboxStore.addChangeListener(this.update);
|
||||||
|
},
|
||||||
|
componentWillUnmount: function () {
|
||||||
|
CheckboxStore.removeChangeListener(this.update);
|
||||||
|
},
|
||||||
|
update: function () {
|
||||||
this.setState({
|
this.setState({
|
||||||
colors: CheckboxStore.getColors()
|
colors: CheckboxStore.getColors()
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
updateName: function () {
|
updateName: function (event) {
|
||||||
this.setState({
|
this.setState({
|
||||||
name: this.refs.input.getDOMNode().value
|
name: event.target.value
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
render: function() {
|
renderColors: function (color, index) {
|
||||||
var names = this.state.colors.map(function (color, index) {
|
|
||||||
var style = {color: color};
|
var style = {color: color};
|
||||||
return <div key={index} style={style}>{this.state.name}</div>
|
return <div key={index} style={style}>{this.state.name}</div>
|
||||||
}, this);
|
},
|
||||||
|
render: function() {
|
||||||
|
var names = this.state.colors.map(this.renderColors);
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input ref="input" type="text" value={this.state.name} onChange={this.updateName}/>
|
<div>
|
||||||
{names}
|
<input type="text" value={this.state.name} onChange={this.updateName}/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{names}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
/** @jsx React.DOM */
|
/** @jsx React.DOM */
|
||||||
var React = require('flux-react');
|
var React = require('react');
|
||||||
React.debug();
|
var flux = require('flux-react');
|
||||||
|
|
||||||
var App = require('./App.js');
|
var App = require('./App.js');
|
||||||
|
|
||||||
|
flux.debug();
|
||||||
|
|
||||||
React.renderComponent(<App/>, document.body);
|
React.renderComponent(<App/>, document.body);
|
||||||
@@ -1,63 +1,60 @@
|
|||||||
var React = require('flux-react');
|
var flux = require('flux-react');
|
||||||
var merge = require('react/lib/merge');
|
var actions = require('./../actions.js');
|
||||||
var CheckboxActions = require('../actions/CheckboxActions.js');
|
|
||||||
var mergeInto = require('react/lib/mergeInto');
|
|
||||||
var Constants = require('../Constants.js');
|
|
||||||
|
|
||||||
var checkboxes = [{
|
var CheckboxStore = flux.createStore({
|
||||||
color: 'red',
|
getInitialState: function () {
|
||||||
checked: false
|
return {
|
||||||
}, {
|
checkboxes: [{
|
||||||
color: 'blue',
|
color: 'red',
|
||||||
checked: false
|
checked: false
|
||||||
}, {
|
}, {
|
||||||
color: 'green',
|
color: 'blue',
|
||||||
checked: false
|
checked: false
|
||||||
}];
|
}, {
|
||||||
|
color: 'green',
|
||||||
var CheckboxStore = React.createStore({
|
checked: false
|
||||||
|
}]
|
||||||
getCheckboxes: function () {
|
};
|
||||||
return checkboxes.map(function (checkbox) {
|
|
||||||
var checkboxCopy = {};
|
|
||||||
mergeInto(checkboxCopy, checkbox); // Create a copy to make it impossible to mutate store
|
|
||||||
return checkboxCopy;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
getColors: function () {
|
actions: [
|
||||||
return checkboxes.map(function (checkbox) {
|
actions.checkAll,
|
||||||
if (checkbox.checked) {
|
actions.uncheckAll,
|
||||||
return checkbox.color;
|
actions.check
|
||||||
} else {
|
],
|
||||||
return 'black';
|
checkAll: function () {
|
||||||
|
this.state.checkboxes.forEach(function (checkbox) {
|
||||||
|
checkbox.checked = true;
|
||||||
|
});
|
||||||
|
this.emitChange();
|
||||||
|
},
|
||||||
|
uncheckAll: function () {
|
||||||
|
this.state.checkboxes.forEach(function (checkbox) {
|
||||||
|
checkbox.checked = false;
|
||||||
|
});
|
||||||
|
this.emitChange();
|
||||||
|
},
|
||||||
|
check: function (color) {
|
||||||
|
this.state.checkboxes.forEach(function (checkbox) {
|
||||||
|
if (checkbox.color === color) {
|
||||||
|
checkbox.checked = !checkbox.checked;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.emitChange();
|
||||||
},
|
},
|
||||||
dispatch: function (payload) {
|
exports: {
|
||||||
switch (payload.type) {
|
getCheckboxes: function () {
|
||||||
case CheckboxActions.CHECK_ALL:
|
return this.checkboxes;
|
||||||
checkboxes.forEach(function (checkbox) {
|
},
|
||||||
checkbox.checked = true;
|
getColors: function () {
|
||||||
});
|
return this.checkboxes.map(function (checkbox) {
|
||||||
break;
|
if (checkbox.checked) {
|
||||||
|
return checkbox.color;
|
||||||
case CheckboxActions.UNCHECK_ALL:
|
} else {
|
||||||
checkboxes.forEach(function (checkbox) {
|
return 'black';
|
||||||
checkbox.checked = false;
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CheckboxActions.CHECK:
|
|
||||||
checkboxes.forEach(function (checkbox) {
|
|
||||||
if (checkbox.color === payload.color) {
|
|
||||||
checkbox.checked = !checkbox.checked;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
this.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = CheckboxStore;
|
module.exports = CheckboxStore;
|
||||||
15
build/index.html
Normal file
15
build/index.html
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="vendors.js"></script>
|
||||||
|
<script src="main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
239
build/main.js
Executable file
239
build/main.js
Executable file
File diff suppressed because one or more lines are too long
3549
dev/main.js → build/vendors.js
Normal file → Executable file
3549
dev/main.js → build/vendors.js
Normal file → Executable file
File diff suppressed because one or more lines are too long
@@ -1,14 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8"/>
|
|
||||||
<link rel="stylesheet" href="main.css"/>
|
|
||||||
<script>
|
|
||||||
window.DEBUG = true;
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<script src="main.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
body {
|
|
||||||
background-color: #EAEAEA;
|
|
||||||
zoom: 150%;
|
|
||||||
}
|
|
||||||
27776
dev/test.js
27776
dev/test.js
File diff suppressed because one or more lines are too long
15
dist/index.html
vendored
Executable file
15
dist/index.html
vendored
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="vendors.js"></script>
|
||||||
|
<script src="main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
dist/main.js
vendored
Executable file
1
dist/main.js
vendored
Executable file
@@ -0,0 +1 @@
|
|||||||
|
!function e(t,o,c){function n(s,a){if(!o[s]){if(!t[s]){var i="function"==typeof require&&require;if(!a&&i)return i(s,!0);if(r)return r(s,!0);var l=new Error("Cannot find module '"+s+"'");throw l.code="MODULE_NOT_FOUND",l}var h=o[s]={exports:{}};t[s][0].call(h.exports,function(e){var o=t[s][1][e];return n(o?o:e)},h,h.exports,e,t,o,c)}return o[s].exports}for(var r="function"==typeof require&&require,s=0;s<c.length;s++)n(c[s]);return n}({"./app/main.js":[function(e){var t=e("react"),o=e("flux-react");o.debug(),o.createActions(["checkAll","uncheckAll","check"]);var c=e("./App.js");t.renderComponent(c(null),document.body)},{"./App.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/App.js","flux-react":"flux-react",react:"react"}],"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/App.js":[function(e,t){var o=e("react"),c=e("./components/Checkboxes.js"),n=e("./components/NameThrower.js"),r=o.createClass({displayName:"App",render:function(){return o.DOM.div(null,o.DOM.h1(null,"Hello world!"),o.DOM.div(null,c(null)),o.DOM.div(null,n(null)))}});t.exports=r},{"./components/Checkboxes.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/components/Checkboxes.js","./components/NameThrower.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/components/NameThrower.js",react:"react"}],"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/components/Checkboxes.js":[function(e,t){var o=e("react"),c=e("flux-react"),n=e("./Checkboxes/ColoredCheckbox.js"),r=e("../stores/CheckboxStore.js"),s=o.createClass({displayName:"Checkboxes",stores:[r],getInitialState:function(){return{checkboxes:r.getCheckboxes()}},componentWillMount:function(){r.addChangeListener(this.update)},componentWillUnmount:function(){r.removeChangeListener(this.update)},update:function(){this.setState({checkboxes:r.getCheckboxes()})},check:function(e){c.action.check(e)},checkAll:function(){c.action.checkAll()},uncheckAll:function(){c.action.uncheckAll()},renderCheckbox:function(e,t){return n({key:t,color:e.color,checked:e.checked,onChange:this.check})},render:function(){var e=this.state.checkboxes.map(this.renderCheckbox);return o.DOM.div(null,o.DOM.div(null,e),o.DOM.div(null,o.DOM.button({onClick:this.checkAll},"Check all"),o.DOM.button({onClick:this.uncheckAll},"Uncheck all")))}});t.exports=s},{"../stores/CheckboxStore.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/stores/CheckboxStore.js","./Checkboxes/ColoredCheckbox.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/components/Checkboxes/ColoredCheckbox.js","flux-react":"flux-react",react:"react"}],"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/components/Checkboxes/ColoredCheckbox.js":[function(e,t){var o=e("react"),c=o.createClass({displayName:"ColoredCheckbox",changeColor:function(){this.props.onChange(this.props.color)},render:function(){var e={backgroundColor:this.props.color,padding:"5px"};return o.DOM.span({key:this.props.key,style:e},o.DOM.input({type:"checkbox",onChange:this.changeColor,checked:this.props.checked}))}});t.exports=c},{react:"react"}],"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/components/NameThrower.js":[function(e,t){var o=e("react"),c=e("../stores/CheckboxStore.js"),n=o.createClass({displayName:"NameThrower",getInitialState:function(){return{name:"",colors:c.getColors()}},componentWillMount:function(){c.addChangeListener(this.update)},componentWillUnmount:function(){c.removeChangeListener(this.update)},update:function(){this.setState({colors:c.getColors()})},updateName:function(e){this.setState({name:e.target.value})},renderColors:function(e,t){var c={color:e};return o.DOM.div({key:t,style:c},this.state.name)},render:function(){var e=this.state.colors.map(this.renderColors);return o.DOM.div(null,o.DOM.div(null,o.DOM.input({type:"text",value:this.state.name,onChange:this.updateName})),o.DOM.div(null,e))}});t.exports=n},{"../stores/CheckboxStore.js":"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/stores/CheckboxStore.js",react:"react"}],"/Users/christianalfoni/Documents/dev/flux-react-boilerplate/app/stores/CheckboxStore.js":[function(e,t){var o=e("flux-react"),c=o.createStore({getInitialState:function(){return{checkboxes:[{color:"red",checked:!1},{color:"blue",checked:!1},{color:"green",checked:!1}]}},actions:["checkAll","uncheckAll","check"],checkAll:function(){this.state.checkboxes.forEach(function(e){e.checked=!0}),this.emitChange()},uncheckAll:function(){this.state.checkboxes.forEach(function(e){e.checked=!1}),this.emitChange()},check:function(e){this.state.checkboxes.forEach(function(t){t.color===e&&(t.checked=!t.checked)}),this.emitChange()},exports:{getCheckboxes:function(){return this.checkboxes},getColors:function(){return this.checkboxes.map(function(e){return e.checked?e.color:"black"})}}});t.exports=c},{"flux-react":"flux-react"}]},{},["./app/main.js"]);
|
||||||
6
dist/vendors.js
vendored
Executable file
6
dist/vendors.js
vendored
Executable file
File diff suppressed because one or more lines are too long
155
gulpfile.js
155
gulpfile.js
@@ -1,49 +1,132 @@
|
|||||||
// Gulp dependencies
|
|
||||||
var gulp = require('gulp');
|
var gulp = require('gulp');
|
||||||
|
var browserify = require('browserify');
|
||||||
|
var watchify = require('watchify');
|
||||||
|
var source = require('vinyl-source-stream');
|
||||||
|
var reactify = require('reactify');
|
||||||
|
var gulpif = require('gulp-if');
|
||||||
|
var uglify = require('gulp-uglify');
|
||||||
|
var streamify = require('gulp-streamify');
|
||||||
|
var notify = require('gulp-notify');
|
||||||
var gutil = require('gulp-util');
|
var gutil = require('gulp-util');
|
||||||
|
var shell = require('gulp-shell');
|
||||||
|
|
||||||
var browserify = require('./utils/browserify.js');
|
var appOptions = {
|
||||||
var css = require('./utils/css.js');
|
|
||||||
|
/*
|
||||||
|
* DIRECTORIES
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Where your app lives
|
||||||
|
appDir: './app',
|
||||||
|
|
||||||
|
// Where your production version is deployed
|
||||||
|
distDir: './dist',
|
||||||
|
|
||||||
|
// Where you bundled development version will run from
|
||||||
|
buildDir: './build',
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BUNDLE FILES
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The name of your main app file
|
||||||
|
entryFile: 'main.js',
|
||||||
|
|
||||||
|
// The name of your bundled vendors
|
||||||
|
vendorsFile: 'vendors.js',
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VENDORS
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Add other vendors here, if any
|
||||||
|
vendors: [
|
||||||
|
'react',
|
||||||
|
'flux-react'
|
||||||
|
]
|
||||||
|
|
||||||
var DEFAULT_OPTIONS = {
|
|
||||||
browserify: {
|
|
||||||
src: './app/main.js',
|
|
||||||
isTest: false,
|
|
||||||
dest: './dev/',
|
|
||||||
watch: true,
|
|
||||||
uglify: false
|
|
||||||
},
|
|
||||||
css: {
|
|
||||||
src: './styles/**/*.css',
|
|
||||||
dest: './dev/',
|
|
||||||
watch: true
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
gulp.task('browserify', function () {
|
// The task that handles both development and deployment
|
||||||
return browserify(DEFAULT_OPTIONS.browserify);
|
var browserifyTask = function (bundleOptions) {
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('css', function () {
|
// This bundle only runs when you start to develop,
|
||||||
return css(DEFAULT_OPTIONS.css);
|
// it is needed to prevent rebundling external deps
|
||||||
});
|
// on project changes
|
||||||
|
var vendorBundler = browserify({
|
||||||
|
debug: bundleOptions.debug,
|
||||||
|
require: appOptions.vendors
|
||||||
|
});
|
||||||
|
|
||||||
gulp.task('default', ['browserify', 'css']);
|
// This bundle is for the application
|
||||||
|
var appBundler = browserify({
|
||||||
|
entries: [appOptions.appDir + '/' + appOptions.entryFile],
|
||||||
|
debug: bundleOptions.debug,
|
||||||
|
|
||||||
|
// These options are needed by Watchify
|
||||||
|
cache: {},
|
||||||
|
packageCache: {},
|
||||||
|
fullPaths: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add reactify transformer
|
||||||
|
appBundler.transform(reactify);
|
||||||
|
|
||||||
|
// Add vendors as externals
|
||||||
|
appOptions.vendors.forEach(function (vendor) {
|
||||||
|
appBundler.external(vendor);
|
||||||
|
});
|
||||||
|
|
||||||
|
// The rebundle process
|
||||||
|
var rebundle = function () {
|
||||||
|
|
||||||
|
var start = Date.now();
|
||||||
|
appBundler.bundle()
|
||||||
|
.on('error', gutil.log)
|
||||||
|
.pipe(source(appOptions.entryFile))
|
||||||
|
.pipe(gulpif(bundleOptions.uglify, streamify(uglify())))
|
||||||
|
.pipe(gulp.dest(bundleOptions.dest))
|
||||||
|
.pipe(notify(function () {
|
||||||
|
console.log('Built in ' + (Date.now() - start) + 'ms');
|
||||||
|
}));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fire up Watchify when developing
|
||||||
|
if (bundleOptions.watch) {
|
||||||
|
appBundler = watchify(appBundler);
|
||||||
|
appBundler.on('update', rebundle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the vendor bundle when the default Gulp task starts
|
||||||
|
vendorBundler.bundle()
|
||||||
|
.on('error', gutil.log)
|
||||||
|
.pipe(source(appOptions.vendorsFile))
|
||||||
|
.pipe(gulpif(bundleOptions.uglify, streamify(uglify())))
|
||||||
|
.pipe(gulp.dest(bundleOptions.dest));
|
||||||
|
|
||||||
|
return rebundle();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
gulp.task('default', function () {
|
||||||
|
|
||||||
|
browserifyTask({
|
||||||
|
watch: true,
|
||||||
|
dest: appOptions.buildDir,
|
||||||
|
uglify: false,
|
||||||
|
debug: true
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
gulp.task('deploy', function () {
|
gulp.task('deploy', function () {
|
||||||
DEFAULT_OPTIONS.browserify.dest = './dist/';
|
|
||||||
DEFAULT_OPTIONS.browserify.watch = false;
|
|
||||||
DEFAULT_OPTIONS.browserify.uglify = true;
|
|
||||||
browserify(DEFAULT_OPTIONS.browserify);
|
|
||||||
|
|
||||||
DEFAULT_OPTIONS.css.dest = './dist/';
|
browserifyTask({
|
||||||
DEFAULT_OPTIONS.css.watch = false;
|
watch: false,
|
||||||
css(DEFAULT_OPTIONS.css);
|
dest: appOptions.distDir,
|
||||||
});
|
uglify: true,
|
||||||
|
debug: false
|
||||||
|
});
|
||||||
|
|
||||||
gulp.task('test', function () {
|
|
||||||
var src = '.' + gutil.env[''][''];
|
|
||||||
DEFAULT_OPTIONS.browserify.src = src;
|
|
||||||
DEFAULT_OPTIONS.browserify.isTest = true;
|
|
||||||
return browserify(DEFAULT_OPTIONS.browserify);
|
|
||||||
});
|
});
|
||||||
@@ -12,9 +12,8 @@ module.exports = function(config) {
|
|||||||
|
|
||||||
// list of files / patterns to load in the browser
|
// list of files / patterns to load in the browser
|
||||||
files: [
|
files: [
|
||||||
'utils/es5-shim.js',
|
'es5-shim.js',
|
||||||
'tests/**/*.js'
|
'tests/**/*.js'
|
||||||
// 'server/**/*.js'
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
||||||
@@ -27,7 +26,6 @@ module.exports = function(config) {
|
|||||||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||||
preprocessors: {
|
preprocessors: {
|
||||||
'tests/**/*.js': ['browserify']
|
'tests/**/*.js': ['browserify']
|
||||||
// 'server/**/*.js': ['browserify']
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@@ -57,7 +55,7 @@ module.exports = function(config) {
|
|||||||
|
|
||||||
|
|
||||||
// enable / disable watching file and executing tests whenever any file changes
|
// enable / disable watching file and executing tests whenever any file changes
|
||||||
autoWatch: false,
|
autoWatch: true,
|
||||||
|
|
||||||
|
|
||||||
// start these browsers
|
// start these browsers
|
||||||
@@ -68,6 +66,6 @@ module.exports = function(config) {
|
|||||||
|
|
||||||
// Continuous Integration mode
|
// Continuous Integration mode
|
||||||
// if true, Karma captures browsers, runs the tests and exits
|
// if true, Karma captures browsers, runs the tests and exits
|
||||||
singleRun: true
|
singleRun: false
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
19
package.json
19
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "flux-react-boilerplate",
|
"name": "flux-react-boilerplate",
|
||||||
"version": "1.0.0",
|
"version": "2.0.0",
|
||||||
"description": "React flux architecture boilerplate",
|
"description": "React flux architecture boilerplate",
|
||||||
"main": "gulp",
|
"main": "gulp",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -11,28 +11,25 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"browserify": "^5.9.3",
|
"browserify": "^5.9.3",
|
||||||
"chai": "^1.9.1",
|
"chai": "^1.9.1",
|
||||||
"es6-promise": "^1.0.0",
|
"flux-react": "^2.1.0",
|
||||||
"flux-react": "^1.3.2",
|
|
||||||
"gulp": "^3.8.7",
|
"gulp": "^3.8.7",
|
||||||
"gulp-concat": "^2.3.4",
|
|
||||||
"gulp-cssmin": "^0.1.6",
|
|
||||||
"gulp-if": "^1.2.4",
|
"gulp-if": "^1.2.4",
|
||||||
"gulp-livereload": "^2.1.0",
|
"gulp-livereload": "^2.1.0",
|
||||||
"gulp-notify": "^1.4.2",
|
"gulp-notify": "^1.4.2",
|
||||||
|
"gulp-shell": "^0.2.10",
|
||||||
"gulp-streamify": "0.0.5",
|
"gulp-streamify": "0.0.5",
|
||||||
"gulp-uglify": "^0.3.1",
|
"gulp-uglify": "^0.3.1",
|
||||||
"gulp-util": "^3.0.0",
|
"gulp-util": "^3.0.0",
|
||||||
|
"react": "^0.11.1",
|
||||||
|
"reactify": "^0.14.0",
|
||||||
|
"vinyl-source-stream": "^0.1.1",
|
||||||
|
"watchify": "^1.0.2",
|
||||||
"karma": "^0.12.21",
|
"karma": "^0.12.21",
|
||||||
"karma-bro": "^0.6.2",
|
"karma-bro": "^0.6.2",
|
||||||
"karma-chrome-launcher": "^0.1.4",
|
"karma-chrome-launcher": "^0.1.4",
|
||||||
"karma-firefox-launcher": "^0.1.3",
|
"karma-firefox-launcher": "^0.1.3",
|
||||||
"karma-mocha": "^0.1.7",
|
"karma-mocha": "^0.1.7",
|
||||||
"karma-phantomjs-launcher": "^0.1.4",
|
"karma-phantomjs-launcher": "^0.1.4",
|
||||||
"mocha": "^1.21.4",
|
"mocha": "^1.21.4"
|
||||||
"react": "^0.11.1",
|
|
||||||
"react-tools": "^0.11.1",
|
|
||||||
"reactify": "^0.14.0",
|
|
||||||
"vinyl-source-stream": "^0.1.1",
|
|
||||||
"watchify": "^1.0.2"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
body {
|
|
||||||
background-color: #EAEAEA;
|
|
||||||
zoom: 150%;
|
|
||||||
}
|
|
||||||
@@ -15,4 +15,4 @@ describe('App', function() {
|
|||||||
|
|
||||||
expect(h1.getDOMNode().textContent).to.equal('Hello world!');
|
expect(h1.getDOMNode().textContent).to.equal('Hello world!');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
/**
|
|
||||||
Use Browserify to bundle up our tests.
|
|
||||||
|
|
||||||
gulp test --watch --tests './tests/checkboxWithLabel-test.js'
|
|
||||||
|
|
||||||
Thanks to - http://blog.avisi.nl/2014/04/25/how-to-keep-a-fast-build-with-browserify-and-reactjs/
|
|
||||||
*/
|
|
||||||
|
|
||||||
var gulp = require('gulp');
|
|
||||||
var source = require('vinyl-source-stream');
|
|
||||||
var browserify = require('browserify');
|
|
||||||
var watchify = require('watchify');
|
|
||||||
var reactify = require('reactify');
|
|
||||||
var livereload = require('gulp-livereload');
|
|
||||||
var gulpif = require('gulp-if');
|
|
||||||
var path = require('path');
|
|
||||||
var uglify = require('gulp-uglify');
|
|
||||||
var streamify = require('gulp-streamify');
|
|
||||||
var notify = require('gulp-notify');
|
|
||||||
|
|
||||||
var handleError = require('./handleError');
|
|
||||||
|
|
||||||
var getTimeStamp = function () {
|
|
||||||
var date = new Date();
|
|
||||||
var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours();
|
|
||||||
var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes();
|
|
||||||
return hours + ':' + minutes;
|
|
||||||
};
|
|
||||||
|
|
||||||
var runBrowserify = function (options) {
|
|
||||||
|
|
||||||
var bundler = browserify({
|
|
||||||
entries: [options.src],
|
|
||||||
transform: [reactify],
|
|
||||||
debug: true,
|
|
||||||
standalone: 'ReactDispatcher',
|
|
||||||
cache: {}, packageCache: {}, fullPaths: true
|
|
||||||
});
|
|
||||||
var rebundle = function() {
|
|
||||||
console.log('[' + getTimeStamp() + '] Building');
|
|
||||||
var start = Date.now();
|
|
||||||
var fileName = options.uglify ? 'ReactDispatcher.min.js' : path.basename(options.src);
|
|
||||||
bundler.bundle()
|
|
||||||
.on('error', handleError('Browserify'))
|
|
||||||
.pipe(source(options.isTest ? 'test.js' : fileName))
|
|
||||||
.pipe(gulpif(options.uglify, streamify(uglify())))
|
|
||||||
.pipe(gulp.dest(options.dest))
|
|
||||||
.pipe(gulpif(options.isTest, livereload()))
|
|
||||||
.pipe(notify(function () {
|
|
||||||
console.log('[' + getTimeStamp() + '] Built in ' + (Date.now() - start) + 'ms');
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
if (options.isTest) {
|
|
||||||
livereload.listen();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.watch) {
|
|
||||||
bundler = watchify(bundler);
|
|
||||||
bundler.on('update', rebundle);
|
|
||||||
}
|
|
||||||
|
|
||||||
bundler.transform(reactify);
|
|
||||||
|
|
||||||
return rebundle();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = runBrowserify;
|
|
||||||
24
utils/css.js
24
utils/css.js
@@ -1,24 +0,0 @@
|
|||||||
var gulp = require('gulp');
|
|
||||||
var concat = require('gulp-concat');
|
|
||||||
var cssmin = require('gulp-cssmin');
|
|
||||||
|
|
||||||
var handleError = require('./handleError');
|
|
||||||
|
|
||||||
var runCss = function (options) {
|
|
||||||
|
|
||||||
if (options.watch) {
|
|
||||||
return gulp.watch(options.src, function () {
|
|
||||||
return gulp.src(options.src)
|
|
||||||
.pipe(concat('main.css'))
|
|
||||||
.pipe(gulp.dest(options.dest));
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return gulp.src(options.src)
|
|
||||||
.pipe(concat('main.css'))
|
|
||||||
.pipe(cssmin())
|
|
||||||
.pipe(gulp.dest(options.dest));
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = runCss;
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
var gutil = require('gulp-util');
|
|
||||||
var notify = require('gulp-notify');
|
|
||||||
|
|
||||||
module.exports = function (task) {
|
|
||||||
return function(err) {
|
|
||||||
gutil.log(gutil.colors.red(err));
|
|
||||||
notify.onError(task + ' failed, check the logs..')(err);
|
|
||||||
|
|
||||||
// Keep gulp or browserify from hanging on this task
|
|
||||||
this.emit('end');
|
|
||||||
};
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user