本文转载自 前端_Logic 的博文,
原文地址:http://blog.csdn.net/lx376693576/article/details/54591142
写于:2017-1-18
完整干净demo地址:coding.net/u/java_luo/p/react_luo/git
技术栈:
react,redux,webpack,eslint,babel,antd(蚂蚁金服ui)
1、前期准备
①、windows系统,本框架是在windows系统下配置的
②、SublimeText, 用的这个编辑器
②、安装Node.js
③、创建一个文件夹,用node命令行工具进入该文件夹,运行npm init命令 生成一个初始package.json
2、配置package.json
{
"name": "myreact",
"version": "1.0.0",
"description": "...",
"main": "index.js",
"scripts": {
"watch": "node server.js",
"build": "webpack -p --config webpack.production.config.js --progress --profile --colors"
},
"author": "luo",
"license": "ISC",
"private": true,
"dependencies": {
"antd": "^2.6.3",
"babel-polyfill": "^6.20.0",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-redux": "^5.0.1",
"react-router": "^3.0.0",
"react-router-redux": "^4.0.7",
"redux": "^3.6.0",
"redux-thunk": "^2.1.0",
"reqwest": "^2.0.5"
},
"devDependencies": {
"babel-core": "^6.21.0",
"babel-loader": "^6.2.10",
"babel-plugin-import": "^1.1.0",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-3": "^6.17.0",
"css-loader": "^0.26.1",
"eslint": "^3.13.1",
"eslint-loader": "^1.6.1",
"eslint-plugin-react": "^6.9.0",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.9.0",
"html-webpack-plugin": "^2.26.0",
"less": "^2.7.2",
"less-loader": "^2.2.3",
"style-loader": "^0.13.1",
"url-loader": "^0.5.7",
"webpack": "^1.14.0",
"webpack-dev-server": "^1.16.2"
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
3、然后创建一下项目的基本目录结构
图中有两个东西不是直接使用的,而是要加载到webpack中,让webpack打包的时候自动调用:
①、.babelrc,即babel功能是要让webpack去调用
②、.eslintrc.json, 即语法检测是在打包时自动去检测
4、配置babel
babel 用于解析ES6,jsx等新语法,让现代浏览器可以运行。
创建.babelrc文件(名为.babelrc,无后缀)
{
"presets": ["es2015", "stage-3", 'react'],
"plugins": [["import",[
{
"libraryName": "antd",
"libraryDirectory": "lib",
"style": true
},
{
"libraryName": "antd-mobile",
"libraryDirectory": "component",
},
]]]
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
5、配置eslint
{
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"jquery": true
},
"extends": "plugin:react/recommended",
"parserOptions": {
"ecmaVersion": 8,
"ecmaFeatures": {
"impliedStrict": true,
"experimentalObjectRestSpread": true,
"jsx": true
},
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
],
"no-cond-assign": "error",
"no-debugger": "error",
"no-dupe-args": "error",
"no-caller": "error",
"no-invalid-this": "error",
"no-unmodified-loop-condition": "error",
"no-with": "error",
"no-catch-shadow": "error"
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
eslit的具体使用和配置可以参考此网站:Eslint中文站
6、配置webpack
webpack用于项目打包,把众多的js,css等文件压缩,混淆加密,最终只生成几个合并后的文件
开发环境和生产环境的配置有所不同,下面先配置开发环境:
webpack.dev.config.js
var path = require('path');
var webpack = require('webpack');
var ROOT_PATH = path.resolve(__dirname);
var APP_PATH = path.resolve(ROOT_PATH, 'src');
var APP_FILE = path.resolve(APP_PATH, 'app');
var BUILD_PATH = path.resolve(ROOT_PATH, '/build');
module.exports = {
entry: {
app: [
'webpack-dev-server/client?http://localhost:8888',
'webpack/hot/only-dev-server',
APP_FILE
]
},
output: {
publicPath: '/test/',
path: BUILD_PATH,
filename: 'bundle.js',
},
devtool: 'source-map',
module: {
preLoaders: [
{
test: /\.js?$/,
loader: 'eslint',
exclude: /node_modules/,
},
],
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel',
},
{
test: /\.css$/,
loaders: ['style', 'css'],
},
{
test: /\.less$/,
loaders: ['style', 'css', 'less'],
},
{
test: /\.(eot|woff|svg|ttf|woff2|gif|appcache|mp3)(\?|$)/,
exclude: /node_modules/,
loader: 'file-loader?name=[name].[ext]',
},
{
test: /\.(png|jpg|gif)$/,
exclude: /node_modules/,
loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]',
}
]
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
],
resolve: {
extensions: ['', '.js', '.jsx', '.less', '.css'],
}
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
开发模式下:
①、所有的样式文件会以内嵌方式全部加到index.html的head中。
②、会生成一个仅存在于内存中的bunde.js文件
7、写server.js
第6步配置了webpack.dev.config.js,打包后,需要运行这个项目,
所以写一个server.js:
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.dev.config.js');
var server = new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: true,
inline: true,
historyApiFallback: true,
progress: true,
stats: { colors: true },
});
server.app.get('*', function(req, res) {
res.sendFile(__dirname + '/src/index.html')
});
server.listen(8888, function() {
console.log('启动服务:8888端口')
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
启动服务的命令在package.json中已经配好:
运行 npm run watch 即可
现在启动服务,将什么也没有,因为src/app.js和src/index.html是空的
这个之后再配置,下面来看一下配置最终打包所需的webpack配置文件
8、配置webpack.production.config.js
即最终用于生产环境的正式打包所需配置
webpack.production.config.js:
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ROOT_PATH = path.resolve(__dirname);
var APP_PATH = path.resolve(ROOT_PATH, 'src');
var APP_FILE = path.resolve(APP_PATH, 'app');
var BUILD_PATH = path.resolve(ROOT_PATH, 'build/dist');
module.exports = {
entry: {
app: APP_FILE,
},
output: {
path: BUILD_PATH,
publicPath: '/',
filename: '[name].js',
chunkFilename: '[name].chunk.js',
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel',
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style', ['css']),
},
{
test: /\.less$/,
loader: ExtractTextPlugin.extract('style', ['css','less']),
},
{
test: /\.(eot|woff|svg|ttf|woff2|gif|appcache|mp3)(\?|$)/,
exclude: /node_modules/,
loader: 'file-loader?name=[name].[ext]',
},
{
test: /\.(png|jpg|gif)$/,
exclude: /node_modules/,
loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]',
}
]
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
}),
new HtmlWebpackPlugin({
filename: '../index.html',
template: './src/index_template.html',
inject: true,
hash: false,
}),
new ExtractTextPlugin('[name].css'),
new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js', (module, count) =>
module.resource && module.resource.indexOf(APP_PATH) === -1),
new webpack.optimize.UglifyJsPlugin({
output: {
comments: false,
},
compress: {
warnings: false,
},
}),
],
resolve: {
extensions: ['', '.js', '.jsx', '.less', '.css'],
}
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
9、写index.html 和 index_template.html模板
index.html:
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />
<title>项目名字</title>
</head>
<body>
<div id="app-root"></div>
<script src="/test/bundle.js"></script>
</body>
</html>
上面的代码中,因为在webpack.dev.config.js中配置的output.publicPath是‘/test/’,
所以html中的script标签也相应的是/test/bundle.js
上面的这个index.html只是用于开发时,启动服务,然后就会跳转到这个html
index_template.html
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />
<title>项目名称</title>
</head>
<body>
<div id="app-root"></div>
</body>
</html>
这个模版html是用于真正打包时,生成最终的index.html,可以交给后台人员直接使用的。js和css,webpack会自动加到最终的index.html中
到此为止,已经配置了可以正常运行的基本雏形,下一篇将在这个基本框架中,加入react,redux,以及基本业务逻辑