From 62cccd4154784aa5009fe34a8ecabdf60422256c Mon Sep 17 00:00:00 2001 From: zuiidea Date: Sat, 8 Oct 2016 22:31:19 +0800 Subject: [PATCH] dva --- .eslintignore | 1 + .eslintrc | 8 ++- .gitignore | 15 +---- .lesshintrc | 18 ------ .stylelintrc | 15 ----- package.json | 81 ++++++++------------------ proxy.config.js | 10 ++++ src/components/Example.js | 14 +++++ src/index.html | 18 +++--- src/index.js | 39 +++++-------- src/models/example.js | 24 ++++++++ src/router.js | 11 ++++ src/routes/IndexPage.js | 22 ++++++++ src/routes/IndexPage.less | 8 +++ src/services/example.js | 5 ++ src/tests/models/example-test.js | 11 ++++ src/utils0/request.js | 30 ++++++++++ webpack.config.js | 97 ++++++++++++-------------------- webpack.config.prod.js | 66 ---------------------- 19 files changed, 229 insertions(+), 264 deletions(-) create mode 100644 .eslintignore delete mode 100644 .lesshintrc delete mode 100644 .stylelintrc create mode 100644 proxy.config.js create mode 100644 src/components/Example.js create mode 100644 src/models/example.js create mode 100644 src/router.js create mode 100644 src/routes/IndexPage.js create mode 100644 src/routes/IndexPage.less create mode 100644 src/services/example.js create mode 100644 src/tests/models/example-test.js create mode 100644 src/utils0/request.js delete mode 100644 webpack.config.prod.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..aa91c16 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +src/**/*-test.js diff --git a/.eslintrc b/.eslintrc index e030fa3..4ff259b 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,6 +1,6 @@ { - "extends": "eslint-config-airbnb", "parser": "babel-eslint", + "extends": "eslint-config-airbnb", "rules": { "spaced-comment": [0], "no-unused-vars": [0], @@ -12,7 +12,11 @@ "react/prop-types": [0], "arrow-body-style": [0], "react/prefer-stateless-function": [0], - "semi": [0] + "semi": [0], + "global-require": [0], + "no-shadow": [0], + "no-useless-computed-key": [0], + "no-underscore-dangle": [0] }, "ecmaFeatures": { "experimentalObjectRestSpread": true diff --git a/.gitignore b/.gitignore index 72579f9..b186605 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,3 @@ -# Intellij -.idea -*.iml -*.iws - -# Mac -.DS_Store - -# node -node_modules -npm-debug.log - -#other dist +node_modules +.DS_Store diff --git a/.lesshintrc b/.lesshintrc deleted file mode 100644 index 8d51d12..0000000 --- a/.lesshintrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "propertyOrdering": false, - "hexLength": "short", - "stringQuotes": false, - "decimalZero": false, - "importantRule": false, - "zeroUnit": "no_unit", - "qualifyingElement": false, - "duplicateProperty": false, - "importPath": false, - "finalNewline": false, - "spaceAroundComma": false, - - "fileExtensions": [".less", ".css"], - "excludedFiles": [ - "test.less" - ] -} diff --git a/.stylelintrc b/.stylelintrc deleted file mode 100644 index 2fe96fd..0000000 --- a/.stylelintrc +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "stylelint-config-standard", - "rules": { - "string-quotes": "single", - "selector-pseudo-class-no-unknown": [ - true, - { - "ignorePseudoClasses": [ - "global", - "local" - ] - } - ] - } -} diff --git a/package.json b/package.json index 70e0cc6..0e6ff5e 100644 --- a/package.json +++ b/package.json @@ -1,63 +1,30 @@ { - "name": "antd-admin", - "version": "1.0.0", - "description": "React Admin Boilerplate, with React + Ant Design", - "license": "Apache-2.0", - "engines": { - "node": ">=5.0 <7", - "npm": ">=3.3 <4" - }, - "keywords": [ - "ant", - "react", - "admin", - "frontend" - ], - "devDependencies": { - "antd": "1.10.0", - "babel-core": "6.4.5", - "babel-eslint": "6.0.0", - "babel-loader": "6.2.1", - "babel-plugin-antd": "0.4.0", - "babel-polyfill": "6.9.1", - "babel-preset-es2015": "6.3.13", - "babel-preset-react": "6.3.13", - "babel-preset-stage-0": "6.5.0", - "css-loader": "^0.25.0", - "eslint": "2.7.0", - "eslint-config-airbnb": "6.x", - "eslint-plugin-react": "4.x", - "file-loader": "0.9.0", - "html-webpack-plugin": "^2.22.0", - "less": "2.7.1", - "less-loader": "^2.2.3", - "lesshint": "2.0.2", - "react": "15.0.2", - "react-cookie": "0.4.7", - "react-dom": "15.0.2", - "react-hot-loader": "1.3.0", - "react-router": "2.0.1", - "reqwest": "^2.0.5", - "strip-loader": "0.1.2", - "style-loader": "0.13.1", - "stylelint": "6.6.0", - "stylelint-config-standard": "9.0.0", - "url-loader": "0.5.7", - "webpack": "1.12.12", - "webpack-dev-server": "1.14.1" + "private": true, + "entry": { + "index": "./src/index.js" }, "dependencies": { - "extract-text-webpack-plugin": "^1.0.1", - "superagent": "2.0.0", - "whatwg-fetch": "^1.0.0" + "dva": "^1.0.0", + "react": "^15.1.0", + "react-dom": "^15.1.0" + }, + "devDependencies": { + "atool-build": "^0.7.6", + "atool-test-mocha": "^0.1.5", + "babel-plugin-dev-expression": "^0.2.1", + "babel-plugin-dva-hmr": "^0.1.0", + "babel-plugin-transform-runtime": "^6.9.0", + "babel-runtime": "^6.9.2", + "dora": "0.3.x", + "dora-plugin-proxy": "^0.7.0", + "dora-plugin-webpack": "0.6.x", + "dora-plugin-webpack-hmr": "^0.1.0", + "expect": "^1.20.2", + "redbox-react": "^1.2.10" }, "scripts": { - "build": "webpack --progress --colors --display-error-details", - "prod": "set NODE_ENV=production&&webpack --progress --colors --config webpack.config.prod.js -p --display-error-details", - "clean": "rd /s /q dist", - "dev": "webpack-dev-server --devtool eval --progress --colors --content-base dist --hot --inline --display-error-details", - "eslint": "eslint --ext .js,.jsx src/view", - "stylelint": "stylelint \"src/**/*.css\"", - "lesshint": "lesshint src/" + "start": "dora --plugins \"proxy,webpack,webpack-hmr\"", + "build": "atool-build", + "test": "atool-test-mocha ./src/**/*-test.js" } -} \ No newline at end of file +} diff --git a/proxy.config.js b/proxy.config.js new file mode 100644 index 0000000..752cfd7 --- /dev/null +++ b/proxy.config.js @@ -0,0 +1,10 @@ +'use strict'; + +const mock = {}; + +require('fs').readdirSync(require('path').join(__dirname + '/mock')) + .forEach(function (file) { + Object.assign(mock, require('./mock/' + file)); + }); + +module.exports = mock; diff --git a/src/components/Example.js b/src/components/Example.js new file mode 100644 index 0000000..a9bc7a0 --- /dev/null +++ b/src/components/Example.js @@ -0,0 +1,14 @@ +import React from 'react'; + +const Example = (props) => { + return ( +
+ Example +
+ ); +}; + +Example.propTypes = { +}; + +export default Example; diff --git a/src/index.html b/src/index.html index f77f60c..f65f403 100644 --- a/src/index.html +++ b/src/index.html @@ -1,14 +1,16 @@ - - + - - - Ant Design Admin + + Demo + - -
- + +
+ + + + diff --git a/src/index.js b/src/index.js index a4fc05b..2dfdcc0 100644 --- a/src/index.js +++ b/src/index.js @@ -1,27 +1,18 @@ -import React from 'react' -import ReactDOM from 'react-dom' -import {Router, Route, IndexRoute,IndexRedirect,Redirect,hashHistory} from 'react-router' -import './utils/index.js' +import './index.html'; +import './index.less'; +import dva from 'dva'; -import App from './view/index' -import SignIn from './view/user/signIn' -import List from './view/data/list' -import Dashboard from './view/user/dashboard' -import Error from './view/common/error' -import './utils/lib.less' +// 1. Initialize +const app = dva(); -const routes = ( - - - - - - - - - - - -) +// 2. Plugins +//app.use({}); -ReactDOM.render(routes, document.getElementById('view')) +// 3. Model +//app.model(require('./models/example')); + +// 4. Router +app.router(require('./router')); + +// 5. Start +app.start('#root'); diff --git a/src/models/example.js b/src/models/example.js new file mode 100644 index 0000000..c54bf1c --- /dev/null +++ b/src/models/example.js @@ -0,0 +1,24 @@ + +export default { + + namespace: 'example', + + state: {}, + + subscriptions: { + setup({ dispatch, history }) { + }, + }, + + effects: { + *fetchRemote({ payload }, { call, put }) { + }, + }, + + reducers: { + fetch(state, action) { + return { ...state, ...action.payload }; + }, + }, + +} diff --git a/src/router.js b/src/router.js new file mode 100644 index 0000000..13b526a --- /dev/null +++ b/src/router.js @@ -0,0 +1,11 @@ +import React, { PropTypes } from 'react'; +import { Router, Route, IndexRoute, Link } from 'dva/router'; +import IndexPage from './routes/IndexPage'; + +export default function({ history }) { + return ( + + + + ); +}; diff --git a/src/routes/IndexPage.js b/src/routes/IndexPage.js new file mode 100644 index 0000000..3214e8c --- /dev/null +++ b/src/routes/IndexPage.js @@ -0,0 +1,22 @@ +import React, { Component, PropTypes } from 'react'; +import { connect } from 'dva'; +import { Link } from 'dva/router'; +import styles from './IndexPage.less'; + +function IndexPage() { + return ( +
+

Welcome to dva!

+
+ +
+ ); +} + +IndexPage.propTypes = { +}; + +export default connect()(IndexPage); diff --git a/src/routes/IndexPage.less b/src/routes/IndexPage.less new file mode 100644 index 0000000..cc48bd6 --- /dev/null +++ b/src/routes/IndexPage.less @@ -0,0 +1,8 @@ + +.normal { + margin: 100px; +} + +.list { + margin-top: 20px; +} diff --git a/src/services/example.js b/src/services/example.js new file mode 100644 index 0000000..bbf54e3 --- /dev/null +++ b/src/services/example.js @@ -0,0 +1,5 @@ +import request from '../utils/request'; + +export async function query() { + return request('/api/users'); +} diff --git a/src/tests/models/example-test.js b/src/tests/models/example-test.js new file mode 100644 index 0000000..3b8bd44 --- /dev/null +++ b/src/tests/models/example-test.js @@ -0,0 +1,11 @@ +import expect from 'expect'; +import example from '../../models/example'; + +describe('example', () => { + + describe('reducer', () => { + it('it should save', () => { + expect(example.reducers['example/save']({}, { payload: { a: 1 }})).toEqual({ a: 1 }); + }); + }) +}); diff --git a/src/utils0/request.js b/src/utils0/request.js new file mode 100644 index 0000000..c808422 --- /dev/null +++ b/src/utils0/request.js @@ -0,0 +1,30 @@ +import fetch from 'dva/fetch'; + +function parseJSON(response) { + return response.json(); +} + +function checkStatus(response) { + if (response.status >= 200 && response.status < 300) { + return response; + } + + const error = new Error(response.statusText); + error.response = response; + throw error; +} + +/** + * Requests a URL, returning a promise. + * + * @param {string} url The URL we want to request + * @param {object} [options] The options we want to pass to "fetch" + * @return {object} An object containing either "data" or "err" + */ +export default function request(url, options) { + return fetch(url, options) + .then(checkStatus) + .then(parseJSON) + .then((data) => ({ data })) + .catch((err) => ({ err })); +} diff --git a/webpack.config.js b/webpack.config.js index 48375ef..f861251 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,66 +1,41 @@ -const webpack = require('webpack') -const HtmlWebpackPlugin = require('html-webpack-plugin') -const ExtractTextPlugin = require("extract-text-webpack-plugin") +const fs = require('fs'); +const path = require('path'); -const babelLoaderConfig = { - presets: ['es2015', 'stage-0', 'react'], - plugins: [ - ['antd', { - 'style': true - }] - ], -}; +module.exports = function(webpackConfig, env) { + webpackConfig.babel.plugins.push('transform-runtime'); -module.exports = { - entry: [ - 'webpack-dev-server/client?http://0.0.0.0:8080', - 'webpack/hot/only-dev-server', - 'babel-polyfill', - './src/index.js' - ], + // Support hmr + if (env === 'development') { + webpackConfig.devtool = '#eval'; + webpackConfig.babel.plugins.push(['dva-hmr', { + entries: [ + './src/index.js', + ], + }]); + } else { + webpackConfig.babel.plugins.push('dev-expression'); + } - output: { - path: __dirname + '/dist', - filename: 'bundle.js', - }, + // Support CSS Modules + // Parse all less files as css module. + webpackConfig.module.loaders.forEach(function(loader, index) { + if (typeof loader.test === 'function' && loader.test.toString().indexOf('\\.less$') > -1) { + loader.include = /node_modules/; + loader.test = /\.less$/; + } + if (loader.test.toString() === '/\\.module\\.less$/') { + loader.exclude = /node_modules/; + loader.test = /\.less$/; + } + if (typeof loader.test === 'function' && loader.test.toString().indexOf('\\.css$') > -1) { + loader.include = /node_modules/; + loader.test = /\.css$/; + } + if (loader.test.toString() === '/\\.module\\.css$/') { + loader.exclude = /node_modules/; + loader.test = /\.css$/; + } + }); - resolve: { - modulesDirectories: ['node_modules', './src'], - extensions: ['', '.js', '.jsx'], - alias: { - antdcss: 'antd/dist/antd.min.css', - }, - }, - - module: { - loaders: [{ - test: /\.jsx?$/, - loaders: ['react-hot', 'babel-loader?' + JSON.stringify(babelLoaderConfig)], - exclude: /node_modules/, - }, - { - test: /\.css$/, - loader: ExtractTextPlugin.extract("style-loader", "css-loader") - }, { - test: /\.less$/, - loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader") - }, - { - test: /\.(png|jpg|svg)$/, - loader: 'url?limit=25000', - }, - ], - }, - - plugins: [ - new HtmlWebpackPlugin({ - title: 'Ant Design Admin', - filename: 'index.html', - template: './src/index.html' - }), - new ExtractTextPlugin("[name].css"), - new webpack.DefinePlugin({ - __DEV__: JSON.stringify(JSON.parse(process.env.NODE_ENV === 'production' ? 'false' : 'true')), - }), - ], + return webpackConfig; }; diff --git a/webpack.config.prod.js b/webpack.config.prod.js deleted file mode 100644 index 7376467..0000000 --- a/webpack.config.prod.js +++ /dev/null @@ -1,66 +0,0 @@ -const webpack = require('webpack') -const HtmlWebpackPlugin = require('html-webpack-plugin') -const ExtractTextPlugin = require("extract-text-webpack-plugin") - -const babelLoaderConfig = { - presets: ['es2015', 'stage-0', 'react'], - plugins: [['antd', {'style': true}]], -}; - -module.exports = { - entry: [ - './src/index.js', - ], - - output: { - path: __dirname + '/dist', - filename: 'bundle.js', - // publicPath: 'http://mycdn.com/', - }, - - resolve: { - modulesDirectories: ['node_modules', './src'], - extensions: ['', '.js', '.jsx'], - }, - - module: { - loaders: [ - { - test: /\.jsx?$/, - loaders: ['babel-loader?' + JSON.stringify(babelLoaderConfig), 'strip-loader?strip[]=logger.debug,strip[]=console.log,strip[]=console.debug'], - exclude: /node_modules/, - }, - { - test: /\.(png|jpg|svg)$/, - loader: 'url?limit=25000', - },{ - test: /\.css$/, - loader: ExtractTextPlugin.extract("style-loader", "css-loader") - }, { - test: /\.less$/, - loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader") - }, - ], - }, - - plugins: [ - new webpack.optimize.UglifyJsPlugin({ - minimize: true, - compress: {warnings: false}, - }), - new HtmlWebpackPlugin({ - title: 'Ant Design Admin', - filename: 'index.html', - template: './src/index.html' - }), - new ExtractTextPlugin("[name].css"), - new webpack.optimize.DedupePlugin(), - new webpack.optimize.OccurenceOrderPlugin(), - new webpack.optimize.AggressiveMergingPlugin(), - new webpack.NoErrorsPlugin(), - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), - __DEV__: JSON.stringify(JSON.parse(process.env.NODE_ENV === 'production' ? 'false' : 'true')), - }), - ], -};