├── .gitignore
├── .eslintignore
├── .babelrc
├── app
├── component
│ ├── bg.png
│ ├── logo.png
│ ├── Hello.js
│ └── Hello.scss
├── index.tpl.html
└── index.js
├── .editorconfig
├── server.js
├── package.json
├── webpack.config.prod.js
├── .eslintrc
├── webpack.config.dev.js
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | build/
3 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/**
2 | **/*.css
3 | **/*.html
4 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "es2015",
4 | "react"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/app/component/bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenbin92/react-redux-webpack-starter/HEAD/app/component/bg.png
--------------------------------------------------------------------------------
/app/component/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chenbin92/react-redux-webpack-starter/HEAD/app/component/logo.png
--------------------------------------------------------------------------------
/app/index.tpl.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | import Hello from './component/Hello';
5 |
6 | ReactDOM.render(
7 | ,
8 | document.getElementById('root')
9 | );
10 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/app/component/Hello.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './Hello.scss';
3 |
4 | import logo from './logo.png';
5 |
6 | class Hello extends React.Component {
7 | render() {
8 | return (
9 |
10 |
Hello React
11 |

12 |
Guangzhou, China
chenbin92
13 |
14 | );
15 | }
16 | }
17 |
18 | export default Hello;
19 |
--------------------------------------------------------------------------------
/app/component/Hello.scss:
--------------------------------------------------------------------------------
1 | .container {
2 | position: absolute;
3 | top: 0;
4 | bottom: 0;
5 | left: 0;
6 | right: 0;
7 | background: url(./bg.png) no-repeat 50%/cover;
8 | display: flex;
9 | justify-content: center;
10 | align-items: center;
11 | flex-direction: column;
12 | h1 {
13 | color: rgba(41, 58, 64, 0.82);
14 | font-size: 42px;
15 | }
16 | p {
17 | position: fixed;
18 | right: 20px;
19 | bottom: 20px;
20 | color: #fff;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*eslint no-console: 0*/
3 |
4 | const webpack = require('webpack');
5 | const webpackDevServer = require('webpack-dev-server');
6 | const devConfig = require('./webpack.config.dev.js');
7 | const prodConfig = require('./webpack.config.prod.js');
8 |
9 | const isDeveloping = process.env.NODE_ENV === 'development';
10 | const port = isDeveloping ? 8080 : 9090;
11 |
12 | function baseConfig(config, contentBase) {
13 | return new webpackDevServer(webpack(config), {
14 | historyApiFallback: true,
15 | hot: true,
16 | inline: true,
17 | progress: true,
18 | contentBase: contentBase,
19 | stats: { colors: true } // 用颜色标识
20 | });
21 | }
22 |
23 | let server;
24 | if(isDeveloping) {
25 | server = baseConfig(devConfig, "/app");
26 | console.log("development mode...");
27 | } else {
28 | server = baseConfig(prodConfig, "./build");
29 | console.log("production mode...");
30 | }
31 |
32 | server.listen(port, "localhost", function(err) {
33 | if(err) {
34 | console.log(err);
35 | }
36 | console.log('==> 🌎 Listening on ' + process.env.NODE_ENV + ' port ' + port);
37 | });
38 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-redux-webpack-starter",
3 | "version": "1.0.0",
4 | "description": "react-redux-webpack-starter",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "export NODE_ENV=development && webpack-dashboard -- node server.js && npm run lint:watch",
9 | "start:prod": "export NODE_ENV=production && npm run build && webpack-dashboard -- node server.js",
10 | "build": "npm run remove:build && NODE_ENV=production && webpack -p --config webpack.config.prod.js --progress --colors",
11 | "clean:build": "npm run remove-build && mkdir build",
12 | "remove:build": "rimraf build",
13 | "lint": "esw webpack.config.* app",
14 | "lint:watch": "npm run lint -- --watch"
15 | },
16 | "author": "chenbin92 (https://github.com/chenbin92)",
17 | "license": "ISC",
18 | "dependencies": {
19 | "react": "^15.1.0",
20 | "react-dom": "^15.1.0",
21 | "react-redux": "^4.4.5",
22 | "redux": "^3.5.2"
23 | },
24 | "devDependencies": {
25 | "babel-core": "^6.10.4",
26 | "babel-eslint": "^6.1.0",
27 | "babel-loader": "^6.2.4",
28 | "babel-preset-es2015": "^6.9.0",
29 | "babel-preset-react": "^6.11.0",
30 | "copy-webpack-plugin": "^3.0.1",
31 | "css-loader": "^0.23.1",
32 | "eslint": "^2.9.0",
33 | "eslint-plugin-react": "^5.2.2",
34 | "eslint-watch": "^2.1.13",
35 | "file-loader": "^0.9.0",
36 | "html-webpack-plugin": "^2.22.0",
37 | "image-webpack-loader": "^1.8.0",
38 | "node-sass": "^3.8.0",
39 | "open-browser-webpack-plugin": "0.0.2",
40 | "sass-loader": "^4.0.0",
41 | "style-loader": "^0.13.1",
42 | "url-loader": "^0.5.7",
43 | "webpack": "^1.13.1",
44 | "webpack-dashboard": "^0.1.6",
45 | "webpack-dev-server": "^1.14.1"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/webpack.config.prod.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const path = require('path');
3 | const OpenBrowserPlugin = require('open-browser-webpack-plugin');
4 | const HtmlWebpackPlugin = require('html-webpack-plugin');
5 |
6 | const config = {
7 | devtool: 'cheap-source-map',
8 | entry: [
9 | 'webpack-dev-server/client?http://localhost:9090',
10 | path.resolve(__dirname, 'app/index.js')
11 | ],
12 | output: {
13 | path: path.resolve(__dirname, 'build'),
14 | filename: '[chunkhash:8].bundle.js',
15 | publicPath: '/'
16 | },
17 | resolve: {
18 | extensions: ['', '.js', '.jsx']
19 | },
20 | module: {
21 | loaders: [
22 | {
23 | test: /\.js|jsx$/,
24 | exclude: /(node_modules|bower_components)/,
25 | loaders: ['babel']
26 | },
27 | {
28 | test: /(\.css|\.scss)$/,
29 | loaders: ["style", "css", "sass"]
30 | },
31 | {
32 | test: /\.(jpe?g|png|gif|svg)$/i,
33 | loaders: [
34 | 'url?limit=10000&name=[hash:8].[name].[ext]',
35 | 'image-webpack?{progressive:true, optimizationLevel: 7, interlaced: false, pngquant:{quality: "65-90", speed: 4}}'
36 | ]
37 | }
38 | ]
39 | },
40 | plugins: [
41 | new webpack.DefinePlugin({
42 | 'process.env.NODE_ENV': JSON.stringify('production'),
43 | __DEV__: JSON.stringify(JSON.parse(process.env.DEBUG || 'false'))
44 | }),
45 | new webpack.optimize.DedupePlugin(),
46 | new webpack.optimize.UglifyJsPlugin({
47 | compress: {
48 | warnings: false
49 | }
50 | }),
51 | new HtmlWebpackPlugin({
52 | template: 'app/index.tpl.html',
53 | filename: 'index.html',
54 | inject: true
55 | }),
56 | new OpenBrowserPlugin({ url: 'http://localhost:9090/' })
57 | ]
58 | };
59 |
60 | module.exports = config;
61 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parserOptions": {
3 | "ecmaVersion": 6,
4 | "sourceType": "module",
5 | "ecmaFeatures": {
6 | "jsx": true
7 | }
8 | },
9 | "env": {
10 | "browser": true,
11 | "node": true,
12 | "es6": true,
13 | "mocha": true
14 | },
15 | "plugins": [
16 | "react"
17 | ],
18 | parser: 'babel-eslint',
19 | extends: [
20 | "eslint:recommended"
21 | ],
22 | "rules": {
23 | "quotes": 0,
24 | "no-console": 1,
25 | "no-debugger": 1,
26 | "no-var": 1,
27 | "import/named": 0,
28 | "semi": [1, "always"],
29 | "no-trailing-spaces": 0,
30 | "eol-last": 0,
31 | "no-underscore-dangle": 0,
32 | "no-alert": 0,
33 | "no-lone-blocks": 0,
34 | "jsx-quotes": 1,
35 | "react/display-name": [ 1, {"ignoreTranspilerName": false }],
36 | "react/forbid-prop-types": [1, {"forbid": ["any"]}],
37 | "react/jsx-boolean-value": 0,
38 | "react/jsx-closing-bracket-location": 0,
39 | "react/jsx-curly-spacing": 1,
40 | "react/jsx-indent-props": 0,
41 | "react/jsx-key": 1,
42 | "react/jsx-max-props-per-line": 0,
43 | "react/jsx-no-bind": 0,
44 | "react/jsx-no-duplicate-props": 1,
45 | "react/jsx-no-literals": 0,
46 | "react/jsx-no-undef": 1,
47 | "react/jsx-pascal-case": 1,
48 | "react/jsx-sort-prop-types": 0,
49 | "react/jsx-sort-props": 0,
50 | "react/jsx-uses-react": 1,
51 | "react/jsx-uses-vars": 1,
52 | "react/no-danger": 1,
53 | "react/no-did-mount-set-state": 1,
54 | "react/no-did-update-set-state": 1,
55 | "react/no-direct-mutation-state": 1,
56 | "react/no-multi-comp": 1,
57 | "react/no-set-state": 0,
58 | "react/no-unknown-property": 1,
59 | "react/prefer-es6-class": 1,
60 | "react/prop-types": 1,
61 | "react/react-in-jsx-scope": 1,
62 | "react/require-extension": 1,
63 | "react/self-closing-comp": 1,
64 | "react/sort-comp": 1,
65 | "react/wrap-multilines": 1
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/webpack.config.dev.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const path = require('path');
3 | const OpenBrowserPlugin = require('open-browser-webpack-plugin');
4 | const HtmlWebpackPlugin = require('html-webpack-plugin');
5 | const DashboardPlugin = require('webpack-dashboard/plugin');
6 |
7 | const config = {
8 | devtool: "source-map", // or "inline-source-map"
9 | entry: [
10 | 'webpack/hot/dev-server',
11 | 'webpack-dev-server/client?http://localhost:8080',
12 | path.resolve(__dirname, 'app/index.js') // 定义入口文件
13 | ],
14 | output: { // 定义出口目录
15 | path: path.resolve(__dirname, 'build'),
16 | filename: 'bundle.js',
17 | publicPath: 'http://localhost:8080/' // html引用路径
18 | },
19 | resolve: { // resolve 指定可以被 import 的文件后缀
20 | extensions: ['', '.js', '.jsx']
21 | },
22 | module: {
23 | loaders: [
24 | {
25 | test: /\.js|jsx$/, // 检测哪些文件需要此loader,是一个正则表达式,用正则来匹配文件路径,这段意思是匹配 js 或者 jsx
26 | exclude: /(node_modules|bower_components)/,
27 | loaders: ['babel'] // 加载模块 "babel" 是 "babel-loader" 的缩写
28 | },
29 | {
30 | test: /(\.css|\.scss)$/,
31 | loaders: ["style", "css?sourceMap", "sass?sourceMap"]
32 | },
33 | {
34 | test: /\.(jpe?g|png|gif|svg)$/i,
35 | loaders: [
36 | 'url?limit=10000&name=img/[hash:8].[name].[ext]',
37 | 'image-webpack?{progressive:true, optimizationLevel: 7, interlaced: false, pngquant:{quality: "65-90", speed: 4}}'
38 | ]
39 | }
40 | ]
41 | },
42 | plugins: [
43 | new HtmlWebpackPlugin({
44 | template: 'app/index.tpl.html',
45 | inject: 'body',
46 | filename: 'index.html'
47 | }),
48 | new webpack.DefinePlugin({
49 | 'process.env.NODE_ENV': JSON.stringify('development'),
50 | __DEV__: JSON.stringify(JSON.parse(process.env.DEBUG || 'false'))
51 | }),
52 | new webpack.HotModuleReplacementPlugin(),
53 | new webpack.NoErrorsPlugin(),
54 | new OpenBrowserPlugin({ url: 'http://localhost:8080/' }),
55 | new DashboardPlugin()
56 | ]
57 | };
58 |
59 | module.exports = config;
60 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React-babel-webpack-es6 Starter Project
2 |
3 | A boilerplate using React, webpack and hot module reloading, and ES6 + JSX via Babel.You could use it as a base to build your own web app.
4 |
5 | ## Features
6 |
7 | The provided boilerplate enables client-side ES6 via the following technologies:
8 |
9 | - [webpack](http://webpack.github.io/) and [webpack-dev-server](https://webpack.github.io/docs/webpack-dev-server.html) as a client-side module builder and module loader.
10 | - [npm](https://www.npmjs.com/) as a package manager and task runner
11 | - [Babel](http://babeljs.io/) 6 as a transpiler from ES6 to ES5.
12 | - [React](https://facebook.github.io/react/) and [JSX](https://facebook.github.io/jsx/) as a virtual Dom JavaScript library for rendering user interfaces (views).
13 | - [ESLint](http://eslint.org/) as a reporter for syntax and style issues. [eslint-plugin-react](https://github.com/yannickcr/eslint-plugin-react) for additional React specific linting rules.
14 | - [Sass](http://sass-lang.com/) as a compiler of CSS styles with variables, mixins, and more.
15 | - Inline base64 URLs for images and fonts if their size is less than specified limit of [file-loader](https://github.com/webpack/file-loader)
16 | - Image compression processing of [image-webpack-loader](https://github.com/tcoopman/image-webpack-loader)
17 | - Watch `index.html` for changes of [html-webpack-plugin](https://github.com/ampedandwired/html-webpack-plugin)
18 |
19 | ## Getting Started
20 |
21 | ### Installation
22 |
23 | you should clone the repo and install the dependencies.
24 |
25 | ```
26 | $ git clone https://github.com/chenbin92/react-redux-webpack-starter.git app-name
27 | $ cd app-name
28 | $ npm install //or cnpm install
29 | ```
30 |
31 | ## Development
32 | In the development mode. launch the boilerplate app:
33 |
34 | ```
35 | // run the dev server http://localhost:8080
36 |
37 | $ npm start
38 | ```
39 |
40 | you should see a new browser tap opening and a title of "Hello React” in [http://localhost:8080/](http://localhost:8080/), page hot reloads automatically when there are changes
41 |
42 | 
43 | 
44 |
45 | When you run npm start:
46 |
47 | - The sass-loader compiles Sass into CSS
48 | - Webpack bundles the compiled CSS、JS into `bundle.js`
49 |
50 | ## Production
51 |
52 | In the production mode, you can:
53 |
54 | ```
55 | // run the prod server http://localhost:9090
56 |
57 | $ npm run start: prod
58 | ```
59 |
60 | ```
61 | // build the static files.
62 |
63 | $ npm run build
64 | ```
65 |
66 | ```npm run build```. This will prepare and build the project for production use. It does the following:
67 |
68 | - Minifies all JS and CSS
69 | - Inline base64 URLs for images and fonts if their size is less than specified limit
70 | - Sets NODE_ENV to production so that React is built in production mode
71 | - Places the resulting built project files into `/build` directory
72 |
73 | ## All configuration tasks
74 |
75 | - `npm start`: start the development model of server
76 | - `npm run start:prod`: start the production model of server
77 | - `npm run build`: compile code in production mode
78 | - `npm run lint`: lint with ESlint and Airbnb's style sheet.
79 | - `npm run lint:watch`: eslint watching
80 | - `npm run remove:build`: remove the dist directory
81 | - `npm run clean:build `: clean the dist directory
82 |
83 | ## TODO
84 |
85 | - [ ] add test
86 |
87 | ## Others
88 |
89 | * [more information](https://github.com/chenbin92/react-redux-webpack-starter/issues/1)
90 |
--------------------------------------------------------------------------------