-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathwebpack.config.js
More file actions
302 lines (267 loc) · 9.45 KB
/
Copy pathwebpack.config.js
File metadata and controls
302 lines (267 loc) · 9.45 KB
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
const webpack = require('webpack');
const webpackMerge = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const ImageminPlugin = require('imagemin-webpack-plugin').default;
const CleanWebpackPlugin = require('clean-webpack-plugin');
const BabiliPlugin = require('babili-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const OpenBrowserPlugin = require('open-browser-webpack-plugin');
// 去除不需要的css
const PurifyCSSPlugin = require('purifycss-webpack');
const cssnano = require('cssnano');
const path = require('path');
const glob = require('glob');
const PATHS = {
app: path.resolve(__dirname, 'app/js'),
build: path.resolve(__dirname, 'build'),
};
function commonConfig() {
return {
entry: {
// app:['babel-polyfill',PATHS.app], 如果想使用promise等es6对象
app: PATHS.app,
test: PATHS.app,
},
output: {
path: PATHS.build,
filename: '[name].js',
},
resolve:{
// 要搜索的目录,前面的优先于后面的
// modules: [path.resolve(__dirname, 'app'), 'node_modules'],
// 路径的别名
alias:{
// sds:path.resolve(__dirname,'app/images/'),
styles:path.resolve(__dirname,'app/styles/'),
js:path.resolve(__dirname,'app/js/'),
},
},
module: {
rules: [{
test: /\.js$/,
include: PATHS.app,
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets: ['es2015'],
},
},
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.(eot|ttf|woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[hash:8].[ext]',
},
},
},
{
test: /\.html$/,
loader: 'raw-loader',
},
],
},
plugins: [
new HtmlWebpackPlugin({
title: 'Webpack demo',
// chunks: ['vendor', 'app'],
template: './app/index.html',
}),
],
};
}
function developmentConfig() {
return webpackMerge(commonConfig(), {
output: {
devtoolModuleFilenameTemplate: 'webpack:///[absolute-resource-path]',
},
module: {
rules: [{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
}, {
// 将以下资源转成Base64编码,保存在js文件中,这样减少了图片的请求
test: /\.(jpg|png|svg)$/,
loader: 'url-loader',
options: {
name: '[name].[ext]',
},
}],
},
devServer: {
port: 3333,
// 启动服务的时候自动开启浏览器
// open: true,
historyApiFallback: true,
// 控制台只输出错误消息
stats: 'errors-only',
overlay: {
errors: true,
warnings: true,
},
// hotOnly: true,
hot: true,
watchOptions: {
// Delay the rebuild after the first change
aggregateTimeout: 300,
// Poll using interval (in ms, accepts boolean too)
poll: 1000,
},
contentBase: ['images'],
},
devtool: 'cheap-module-eval-source-map',
plugins: [
new webpack.HotModuleReplacementPlugin(),
// 在控制台可以看到那个module更新了
new webpack.NamedModulesPlugin(),
// Ignore node_modules so CPU usage with poll
// watching drops significantly.
new webpack.WatchIgnorePlugin([
path.join(__dirname, 'node_modules'),
]),
new OpenBrowserPlugin({
url:'http://localhost:3333/',
browser:'google chrome',
}),
],
});
}
function productionConfig() {
return webpackMerge(commonConfig(), {
entry: {
// vendor: ['jquery', 'react'],
},
output: {
chunkFilename: './js/[name].[chunkhash:8].js',
filename: './js/[name].[chunkhash:8].js',
},
module: {
rules: [{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: ['css-loader', {
loader: 'postcss-loader',
options: {
plugins: () => ([require('autoprefixer')]),
},
}],
// 解决css url()的路径问题
publicPath:'../',
fallback: 'style-loader',
}),
}, {
// 将以下资源转成Base64编码,保存在js文件中,这样减少了图片的请求
test: /\.(jpg|png|svg)$/,
loader: 'url-loader',
options: {
limit: 25000, //限制不能超过25kb,超过后会调用file-loader
name: './images/[name].[hash:8].[ext]',
},
}],
},
plugins: [
// 删除文件
new CleanWebpackPlugin([PATHS.build]),
// new webpack.DefinePlugin({
// 'process.env.NODE_ENV': 'production',
// }),
// 提取entry中公共的库js代码
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
// 从app.js中抽离与vendor中重复的代码
// 不写chunks,默认将所有entry里的公共js提取出来,vendor一般不会有太多变化
miniChunks: isVendor,
}),
// 单独抽离
// new webpack.optimize.CommonsChunkPlugin({
// name: 'test.vendor',
// chunks: ['test'],
// miniChunks: isVendor,
// }),
// 抽离公共模块
// new webpack.optimize.CommonsChunkPlugin({
// name: 'common',
// // 抽离app与tes文件中自己写的代码的公共的部分,不是引用的库的公共部分
// chunks: ['app', 'test'],
// // module引用的模块,count引用的次数
// minChunks: (module, count) => {
// return count >= 2 && isVendor(module);
// },
// }),
// 生成一个js加载的清单,如果vendors文件没有变化,不改变它的hash值,这样可以利用浏览器的cache,manifest文件的hash值也不会有变化
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
// 从app.js中抽离与vendor中重复的代码
// chunks: ['app','test'],
miniChunks: Infinity,
}),
// js代码压缩,不适用uglify的原因是,uglify不支持es6,压缩会出现问题
new BabiliPlugin(),
new ExtractTextPlugin({
filename: './styles/[name].[contenthash:8].css',
// 所有entry如果生成的css文件合并成一个
allChunks:true,
}),
new webpack.HashedModuleIdsPlugin(),
new PurifyCSSPlugin({
paths: glob.sync(path.join(PATHS.app, '**', '*')),
// options: {
// minify: true,
// },
}),
// css压缩
new OptimizeCSSAssetsPlugin({
cssProcessor: cssnano,
cssProcessorOptions: {
discardComments: {
removeAll: true,
},
// Run cssnano in safe mode to avoid
// potentially unsafe transformations.
safe: true,
},
}),
// 图片压缩
new ImageminPlugin({
disable: process.env.NODE_ENV !== 'production', // Disable during development
pngquant: {
quality: '95-100',
},
}),
],
// recordsPath: 'records.json',
// performance: {
// hints: 'warning', // 'error' or false are valid too
// maxEntrypointSize: 100000, // in bytes
// maxAssetSize: 450000, // in bytes
// },
});
}
function extractBundles(bundles) {
return {
plugin: bundles.map(bundle =>
new webpack.optimize.CommonsChunkPlugin(bundle)
),
};
}
// 判断是不是加载来自nodnode_modules里的文件
function isVendor({
resource,
}) {
return resource &&
resource.indexOf('node_modules') >= 0 &&
resource.match(/\.js$/);
}
function buildConfig(env) {
process.env.BABEL_ENV = env;
if (env === 'prod') {
return productionConfig();
}
return developmentConfig();
}
module.exports = buildConfig;