用生命谱写代码的赞歌

0%

Webpack2 开发与生产环境配置文件详解

Webpack2 如何配置

Webpack2 开发环境与生产环境配置文件详细说明,具体参见我的这个 TodoList 应用 github 地址里面的 webpack2 配置方式。

package.json 命令

webpack-dev-server 命令参数似乎不支持 --colors ,支持 --color

1
2
3
4
5
6
7
{
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "set NODE_ENV=dev&&webpack-dev-server --devtool eval --progress --colors --content-base src",
"build": "set NODE_ENV=production&&webpack --config webpack.production.js --progress --colors"
},
}

Webpack2 开发环境配置文件

webpack.config.js

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
var path = require('path')
var webpack = require('webpack')
var OpenBrowserPlugin = require('open-browser-webpack-plugin')

module.exports = {
context: __dirname + '/src', // 开发环境目录
entry: {
app: './index.jsx'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
enforce: 'pre', // 在babel-loader对源码进行编译前进行lint的检查
include: /src/, // src文件夹下的文件需要被lint
use: [{
loader: 'eslint-loader',
options: {
formatter: require('eslint-friendly-formatter') // 编译后错误报告格式
}
}]
// exclude: /node_modules/ 可以不用定义这个字段的属性值,eslint会自动忽略node_modules和bower_components
},
{
test: /\.jsx?$/,
exclude: /node_modules/,
loaders: [
'babel-loader',
'eslint-loader'
]
},
{
test: /\.css$/,
loaders: [
'style-loader',
'css-loader'
]
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.(png|jpg|jpeg|gif)$/,
loader: 'url-loader?limit=25000'
},
{
test: /\.(eot|woff|ttf|woff2|svg)$/,
loader: 'url-loader?limit=50000'
}
]
},

plugins: [
// 打包完成自动打开浏览器
new OpenBrowserPlugin({url: 'http://localhost:8080/', browser: 'chrome'}),
// 可在业务js代码中使用__DEV__判断是否是dev模式(dev模式下可以提示错误、测试报告等,production模式不提示)
new webpack.DefinePlugin({
__DEV__: JSON.stringify(JSON.parse((process.env.NODE_ENV == 'dev') || 'false'))
})
]
}

Webpack2 生产环境配置文件

webpack.production.js

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
* 项目部署配置文件(在module中抽取CSS时使用clean-css包压缩css)
*/
var path = require('path')
var webpack = require('webpack')
// 抽取css第三方插件
var ExtractTextPlugin = require('extract-text-webpack-plugin')
// 自动生成index.html页面插件
var HtmlWebpackPlugin = require('html-webpack-plugin')
// 删除文件夹(可以省去,直接在package.json里面设置:windows环境: rd/s/q build)build不能写成./build,windows不识别
var CleanPlugin = require('clean-webpack-plugin')

// 如果需要分别抽取 css 与 less 文件使用下面配置
// css 文件抽取配置项
//var ExtractCSS = new ExtractTextPlugin({
// filename: "/css/[name].[contenthash].css",
// disable: process.env.NODE_ENV === "dev"
//})
// less文件抽取配置项
//var ExtractLess = new ExtractTextPlugin({
// filename: "/css/[name].[contenthash].css",
// disable: process.env.NODE_ENV === "dev"
//})

module.exports = {
entry: {
app: path.resolve(__dirname, './src/index.jsx'), // 文件入口
vendor: ['react', 'react-dom', 'react-router', 'react-loading', 'antd', 'react-addons-perf', 'react-addons-pure-render-mixin'] // 通过CommonsChunkPlugin抽取第三方库
},
output: {
path: path.resolve(__dirname, './dist'), // 文件打包输出目录
filename: 'js/[name].[chunkhash:8].js', // name对应入口的app, 打包为一个整体
// 为了做代码的异步加载
publicPath: '/',
chunkFilename: '[name].[chunkhash:8].js' // name对应Routers.jsx中异步加载各个组件的名称
},
module: {
rules: [
// 处理jsx语法和ES6语法
{
test: /\.jsx?$/,
loader: 'babel-loader', // 使用babel-loader加载js语法
exclude: /node_modules/ // 必须排除掉node_modules的js文件, 否则报错
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [{
loader: 'css-loader',
options: {
minimize: true // 压缩抽取的css, 需要安装clean-css包
}
}]
})
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'sass-loader']
})
},
// 1kb=1024b 1b=8bit 25000bit~3kb
// 如果图片小于25000b, 自动转化为base64格式图片文件, 减少网络请求服务器次数
{
test: /\.(png|jpg|jpeg|gif)$/,
loader: 'url?limit=25000&name=images/[name].[ext]'
},
{
test: /\.(eot|woff|ttf|woff2|svg)$/,
loader: 'url?limit=50000&name=fonts/[name].[ext]'
},
]
},
resolve: {
// 自动扩展文件后缀名,意味着我们require模块可以省略不写后缀名
// 注意一下, extensions 第一个是空字符串! 对应不需要后缀的情况.
extensions: ['.js', '.json', '.scss', '.jsx'],
// 模块别名定义,方便后续直接引用别名,无须多写长长的地址。后续直接 require('AppStore') 即可
// alias: {
// ReactJS:"node_modules/react/react.min.js",
// AppStore: 'js/stores/AppStores.js',
// }
},
// 在这个属性里面定义的包是不会被打包进bundle.js文件中的,如果你要用这个属性,别忘了在index.html中引入cdn
// externals: {
// // 配置了这个属性之后react和react-dom这些第三方的包都不会被构建进js中,那么我们就需要通过cdn进行文件的引用了
// // 前边这个名称是在项目中引用用的,相当于import React from 'react1'中的react,
// 'react1':"react",
// 'react-dom1':"react-dom",
// '$1':"jQuery"
// },

plugins: [
// 构建之前先删除dist目录下面的文件夹
new CleanPlugin(['./dist']),
// 分离第三方应用插件,name属性会自动指向entry中vendor属性,filename属性中的文件会自动构建到output中的path属性下面
// webpack 内置的 banner-plugin(为抽取的文件添加版权信息等等)
new webpack.BannerPlugin("Copyright hushiking@github.com."),
// 提供公共代码
new webpack.optimize.CommonsChunkPlugin({name: 'vendor', filename: 'js/[name].[chunkhash:8].js'}),
// 用webpack压缩代码,可以忽略代码中的警告
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
// 可以新建多个抽离样式的文件,这样就可以有多个css文件了。
new ExtractTextPlugin("css/[name].[chunkhash:8].css"), // name对应入口的app
// compiling our final assets
new HtmlWebpackPlugin({
template: './src/template.html', // html模板路径,HtmlWebpackPlugin自动引入css,js文件
/*htmlWebpackPlugin: { // 打包后的html文件自动引用css, js文件
"files": {
"css": ["[name].[chunkhash:8].css"],
"js": ["[name].[chunkhash:8].js","[name].[chunkhash:8].js"]
}
},*/
// 效果不大,情怀至上
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true // 移除html属性的引号
}
}),
new webpack.DefinePlugin({
// 根据生产环境去掉react中的警告,react会自己判断,定义生产环境,编译React时压缩到最小
'process.env': {
NODE_ENV: '"production"'
}
}),
]
}