Skip to content

Commit

Permalink
add boilerplate for redux, Close ant-design#24
Browse files Browse the repository at this point in the history
  • Loading branch information
sorrycc committed May 18, 2016
1 parent 6a642d9 commit 5ee7ae4
Show file tree
Hide file tree
Showing 34 changed files with 459 additions and 12 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
.idea
.DS_Store
tmp
spm_modules
node_modules
examples/**/dist
boilerplate/dist
1 change: 0 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
.idea
.DS_Store
tmp
spm_modules
node_modules
examples
42 changes: 32 additions & 10 deletions bin/antd-init
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ var vfs = require('vinyl-fs');
var fs = require('fs');
var through = require('through2');
var path = require('path');
var inquirer = require('inquirer');
var join = path.join;
var basename = path.basename;

Expand All @@ -13,17 +14,38 @@ if (process.argv.length === 3 &&
return;
}

var cwd = join(__dirname, '../boilerplate');
var dest = process.cwd();

vfs.src('**/*', {cwd: cwd, cwdbase: true, dot: true})
.pipe(template(dest))
.pipe(vfs.dest(dest))
.on('end', function() {
fs.renameSync(path.join(dest,'gitignore'),path.join(dest,'.gitignore'));
require('../lib/install');
inquirer.prompt({
name: 'type',
type: 'list',
message: 'Please select boilerplate type',
choices: [
{
name: 'plain react - for simple project',
value: 'plain-react',
},
{
name: 'redux - for complex project',
value: 'redux',
},
],
})
.resume();
.then(function(answers) {
init(answers.type);
});

function init(type) {
var cwd = join(__dirname, '../boilerplates', type);
var dest = process.cwd();

vfs.src('**/*', {cwd: cwd, cwdbase: true, dot: true})
.pipe(template(dest))
.pipe(vfs.dest(dest))
.on('end', function() {
fs.renameSync(path.join(dest,'gitignore'),path.join(dest,'.gitignore'));
require('../lib/install');
})
.resume();
}

function template(dest) {
return through.obj(function (file, enc, cb) {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
20 changes: 20 additions & 0 deletions boilerplates/redux/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"parser": "babel-eslint",
"extends": "eslint-config-airbnb",
"rules": {
"spaced-comment": [0],
"no-unused-vars": [0],
"no-empty": [0],
"react/wrap-multilines": [0],
"react/no-multi-comp": [0],
"no-constant-condition": [0],
"react/jsx-no-bind": [0],
"react/prop-types": [0],
"arrow-body-style": [0],
"react/prefer-stateless-function": [0],
"semi": [0]
},
"ecmaFeatures": {
"experimentalObjectRestSpread": true
}
}
109 changes: 109 additions & 0 deletions boilerplates/redux/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# react-redux-boilerplate

A boilerplate with react, redux, redux-saga, react-router, webpack, babel, css-modules ...

## 环境准备

先安装依赖

```bash
$ npm install
```

想要更好的开发体验,还需安装两个 Chrome 插件:[Redux DevTools](https://chrome.google.com/webstore/detail/lmhkpmbekcpmknklioeibfkpmmfibljd)[LiveReload](https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei)

## 启动调试

```bash
$ npm start
$ open http://localhost:8989/
```

## 构建代码

```bash
$ npm run build

// 构建但不压缩
$ npm run build -- --no-compress
```

## 目录结构

```
.
├── /dist/ # 构建输出的文件会在这里
├── /node_modules/ # 第三方类库和工具
├── /src/ # 应用源码
│ ├── /components/ # React components
│ ├── /constants/ # 常量 (比如 action types 等)
│ ├── /containers/ # React containers
│ ├── /entries/ # 应用入口
│ ├── /reducers/ # reducers
│ ├── /routes/ # 路由信息
│ ├── /sagas/ # redux-sagas
│ └── /services/ # 处理和服务器的交互
├── proxy.config.js # 配置 dora-plugin-proxy,用于 mock 和在线调试
├── webpack.config.js # 扩展 webpack 配置
└── package.json # 配置入口文件、依赖和 scripts
```

## 系统组织

![](https://camo.githubusercontent.com/068c4ff126977b861cff3338428bdde6927f7dad/68747470733a2f2f6f732e616c697061796f626a656374732e636f6d2f726d73706f7274616c2f43684d775a42755a6c614c725377652e706e67)

详见:[React + Redux 最佳实践](https://github.com/sorrycc/blog/issues/1)

## 内置类库

- [react](https://github.com/facebook/react)
- [redux](https://github.com/reactjs/redux)
- [redux-saga](https://github.com/yelouafi/redux-saga)
- [redux-actions](https://github.com/acdlite/redux-actions)
- [react-router](https://github.com/reactjs/react-router)
- [reselect](https://github.com/reactjs/reselect)
- [classnames](https://github.com/JedWatson/classnames)
- [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch)
- [react-router](https://github.com/reactjs/react-router)
- [react-router-redux](https://github.com/reactjs/react-router-redux)

## 工具特性

热替换和 LiveReload

> 基于 [Webpack Vanilla HMR](https://webpack.github.io/docs/hot-module-replacement-with-webpack.html),支持 `components`, `containers`, `reducers`, `routers` 目录的模块热替换,其余目录的修改则会自动刷新页面。
> CSS 的自动刷新需通过 [LiveReload](https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei) Chrome 插件配合使用。
> - [Why Vanilla HMR](https://github.com/reactjs/redux/pull/1455)
支持 css-modules

> 后缀为 `.module.less``.module.css` 的会被解析为 css-modules
内置支持 jsx-control-statements

> jsx 里可以通过 If, Else 和 For 标签来实现控制语句
运行错误和语法错误的提醒

> 通过 [redbox-react](https://github.com/KeywordBrain/redbox-react) 和 webpack hmr overlay 提示运行错误和语法错误
自动引入 `reducer``saga`

> 通过 webpack 的 `require.context` 黑魔法批量引入 `reducer``saga`,新增、删除和重命名时会更方便
自动安装 npm 依赖

> ![](https://camo.githubusercontent.com/898e02d6539900efe65fadbfd15e2a1d7ce4dccf/68747470733a2f2f6f732e616c697061796f626a656374732e636f6d2f726d73706f7274616c2f4b6541474f776a70746a6152684d6d2e676966)
数据 mock 和线上调试

> 通过 dora-plugin-proxy 实现,详见:https://github.com/dora-js/dora-plugin-proxy#规则定义
...

## License

MIT

4 changes: 4 additions & 0 deletions boilerplates/redux/gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dist
node_modules
.DS_Store
npm-debug.log
45 changes: 45 additions & 0 deletions boilerplates/redux/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"private": true,
"entry": {
"index": "./src/entries/index.js"
},
"dependencies": {
"atool-build": "0.6.x",
"babel-polyfill": "^6.3.14",
"classnames": "^2.2.3",
"history": "^2.0.1",
"isomorphic-fetch": "^2.2.1",
"jsx-control-statements": "^3.1.0",
"react": "0.14.x",
"react-dom": "0.14.x",
"react-redux": "4.4.x",
"react-router": "^2.0.1",
"react-router-redux": "^4.0.1",
"redux": "3.3.x",
"redux-actions": "0.9.x",
"redux-saga": "^0.9.5",
"reselect": "^2.0.3"
},
"devDependencies": {
"babel-eslint": "^6.0.2",
"dora": "0.3.x",
"dora-plugin-browser-history": "^0.1.1",
"dora-plugin-livereload": "^0.3.0",
"dora-plugin-proxy": "^0.6.1",
"dora-plugin-webpack": "0.6.x",
"dora-plugin-webpack-hmr": "^0.1.0",
"eslint": "^2.7.0",
"eslint-config-airbnb": "^6.2.0",
"eslint-plugin-react": "^4.2.3",
"pre-commit": "1.x",
"redbox-react": "^1.2.2"
},
"pre-commit": [
"lint"
],
"scripts": {
"start": "dora --plugins \"proxy,webpack,webpack-hmr,livereload?enableJs=false,browser-history?index=/src/entries/index.html\"",
"build": "atool-build",
"lint": "eslint --ext .js,.jsx src/"
}
}
5 changes: 5 additions & 0 deletions boilerplates/redux/proxy.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// More Examples: https://github.com/dora-js/dora-plugin-proxy#规则定义

module.exports = {
'/webapi/*': 'http://1.1.1.1',
};
27 changes: 27 additions & 0 deletions boilerplates/redux/src/components/Count/Count.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import styles from './Count.module.less';
import React, { Component, PropTypes } from 'react';
import classnames from 'classnames';
import { COUNT_DECREASE, COUNT_DECREASE_ASYNC, COUNT_REDUCE } from '../../constants/count';

const Count = ({ dispatch, count }) =>
<div className={classnames({
[styles.normal]: count % 2 === 0,
[styles.odd]: count % 2 === 1,
})}>
<div>{count}</div>
<button onClick={() => { dispatch({ type: COUNT_DECREASE }); }}>+</button>
<button onClick={() => { dispatch({ type: COUNT_REDUCE }); }}>-</button>
<button onClick={() => { dispatch({ type: COUNT_DECREASE_ASYNC }); }}>+ (async)</button>
<br /><br />
<If condition={count % 2 === 0}>
<span>even</span>
<Else />
<span>odd</span>
</If>
</div>

Count.propTypes = {
count: PropTypes.any,
};

export default Count;
7 changes: 7 additions & 0 deletions boilerplates/redux/src/components/Count/Count.module.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

.normal {
background: #fafafa;
}
.odd {
background: #ccc;
}
4 changes: 4 additions & 0 deletions boilerplates/redux/src/constants/count.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

export const COUNT_DECREASE = 'count/decrease';
export const COUNT_REDUCE = 'count/reduce';
export const COUNT_DECREASE_ASYNC = 'count/decrease/async';
20 changes: 20 additions & 0 deletions boilerplates/redux/src/containers/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import Count from '../components/Count/Count';

const App = (props) =>
<div>
<Count {...props} />
</div>

App.propTypes = {
};

const selectors = createSelector([
state => state.count,
], (count) => {
return { count };
});

export default connect(selectors)(App);
16 changes: 16 additions & 0 deletions boilerplates/redux/src/entries/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo</title>
<link rel="stylesheet" href="index.css" />
</head>
<body>

<div id="root"></div>

<script src="common.js"></script>
<script src="index.js"></script>

</body>
</html>
Loading

0 comments on commit 5ee7ae4

Please sign in to comment.