webpack全面理解
/ / 点击 / 阅读耗时 13 分钟什么是Webpack
Webpack是一个静态模块打包工具。将一切文件视为模块,可以像引入JavaScript文件一样,在代码中引入。
Entry Points
入口点,就是打包的起始文件。有多种定义方式。
单入口,使用字符串:
1
2
3
4const config = {
entry: './path/to/my/entry/file.js'
};
module.exports = config;多入口,使用对象语法:
1
2
3
4
5
6const config = {
entry: {
app: './src/app.js',
vendors: './src/vendors.js'
}
};
Output
输出,告诉webpack怎样将编译后的文件写入磁盘。输出只有一个。
基本用法:
1
2
3
4
5
6
7const config = {
output: {
filename: 'bundle.js',
path: '/home/proj/public/assets'
}
};
module.exports = config;多入口点的用法:
1
2
3
4
5
6
7
8
9
10
11{
entry: {
app: './src/app.js',
search: './src/search.js'
},
output: {
filename: '[name].js',
path: __dirname + '/dist'
}
}
// writes to disk: ./dist/app.js, ./dist/search.js
Loaders
装载机,用于转换一个模块的源代码。类似于其他打包工具的任务功能。它允许你讲其他语言转换成JavaScript,或者像引入JavaScript文件一样引入图片,数据,CSS文件等。
安装:
npm install --save-dev style-loader css-loader
配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
]
}
Plugins
插件,是webpack的支柱,webpack本身就是创建在same plugin system之上的。它用来做loader不能做的事。
插件的结构:是一个有apply属性的JavaScript对象。apply属性会被webpack编译器调用,用于整个编译周期。
基本用法:
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//installed via npm
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); //to access built-in plugins
const path = require('path');
const config = {
entry: './path/to/my/entry/file.js',
output: {
filename: 'my-first-webpack.bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: 'babel-loader'
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({template: './src/index.html'})
]
};
module.exports = config;常用插件:
html-webpack-plugin(输出控制的插件)
- 安装:
npm install --save-dev html-webpack-plugin
- 配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18const path = require('path');
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: './src/index.js',
print: './src/print.js'
},
+ plugins: [
+ new HtmlWebpackPlugin({
+ title: 'Output Management'
+ })
+ ],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};- 结论:使用该插件,每次创建会将index.html替换掉,自动引入多个入口的JavaScript文件。当我们在配置中新增、修改入口点时,就不用手动修改源代码。
- 安装:
clean-webpack-plugin(清理/dist文件夹)
- 安装:
npm install --save-dev clen-webpack-plugin
配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
+ const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: {
app: './src/index.js',
print: './src/print.js'
},
plugins: [
+ new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Output Management'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};结论:创建之后,不会再有旧文件,只有刚生成的文件。
- 安装:
uglifyjs-webpack-plugin(Tree shaking插件,用于去除为使用的代码,以及最小化代码)
- 安装:
npm install --save-dev uglifyjs-webpack-plugin
配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14const path = require('path');
+ const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
- }
+ },
+ plugins: [
+ new UglifyJSPlugin()
+ ]
};结论:创建后,最小化了代码文件,并且没有将未使用的代码创建进来。就像一棵树,源代码像绿色的活着的叶子,死代码像秋天到了棕色的,死了的叶子,通过摇动这棵树,将死去的叶子摇下。
- 安装:
CommonsChunkPlugin(代码分裂插件)
- 安装: 属于webpack内建插件
配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23const path = require('path');
+ const webpack = require('webpack');
const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: './src/index.js',
another: './src/another-module.js'
},
plugins: [
new HTMLWebpackPlugin({
title: 'Code Splitting'
- })
+ }),
+ new webpack.optimize.CommonsChunkPlugin({
+ name: 'common' // Specify the common bundle's name.
+ })
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};结论: 在没有使用该插件时,配置了多个入口,每个入口中都会存在共同使用的模块,代码就出现了重复。使用之后,共同使用的代码,会被创建在一个新的,单独的文件中。
Development
开发时,我们需要做一些设置,使开发变得容易。
Using source maps
- 描述: 在使用webpack创建代码时,我们很难通过错误和警告去追踪源代码位置。
配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17module.exports = {
entry: {
app: './src/index.js',
print: './src/print.js'
},
+ devtool: 'inline-source-map',
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Development'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
- 结论: 在devtool属性中配置
inline-source-map
之后,我们将可以在控制台中找到出错的行数,并可以链接进源代码。
Using Watch Mode
- 描述: 如果每次修改源代码,我们都要去手动创建一次,这是一件很麻烦的事。
配置:
1
2
3
4
5"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
+"watch": "webpack --watch",
"build": "webpack"
},结论: 添加watch参数,每次修改源代码之后,webpack会帮忙自动创建。
Using webpack-dev-server
- 描述: 提供一个简单的web服务器,并且能够自动刷新页面。
- 安装:
npm install --save-dev webpack-dev-server
配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: {
app: './src/index.js',
print: './src/print.js'
},
devtool: 'inline-source-map',
+ devServer: {
+ contentBase: './dist'
+ },
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Development'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};- 添加npm执行脚本:
"start": "webpack-dev-server --open"
- 添加npm执行脚本:
Production
如何添加一个产品配置?我们需要将产品和开发时相同的配置提取出来,通过npm脚本传入不同的参数,在产品和开发时使用不同的webpack配置。
- 安装:
npm install --save-dev webpack-merge
配置:
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
98project:
webpack-demo
|- package.json
- |- webpack.config.js
+ |- webpack.common.js
+ |- webpack.dev.js
+ |- webpack.prod.js
|- /dist
|- /src
|- index.js
|- math.js
|- /node_modules
webpack.common.js
+ const path = require('path');
+ const CleanWebpackPlugin = require('clean-webpack-plugin');
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
+
+ module.exports = {
+ entry: {
+ app: './src/index.js'
+ },
+ plugins: [
+ new CleanWebpackPlugin(['dist']),
+ new HtmlWebpackPlugin({
+ title: 'Production'
+ })
+ ],
+ output: {
+ filename: '[name].bundle.js',
+ path: path.resolve(__dirname, 'dist')
+ }
+ };
webpack.dev.js
+ const merge = require('webpack-merge');
+ const common = require('./webpack.common.js');
+
+ module.exports = merge(common, {
+ devtool: 'inline-source-map',
+ devServer: {
+ contentBase: './dist'
+ }
+ });
webpack.prod.js
+ const merge = require('webpack-merge');
+ const webpack = require('webpack');
+ const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
+ const common = require('./webpack.common.js');
+
+ module.exports = merge(common, {
+ devtool: 'source-map,
+ plugins: [
+ new UglifyJSPlugin({
+ sourceMap: true
+ }),
+ new webpack.DefinePlugin({
+ 'process.env.NODE_ENV': JSON.stringify + ('produdction)
+ })
+ ]
+ });
NPM Scripts
{
"name": "development",
"version": "1.0.0",
"description": "",
"main": "webpack.config.js",
"scripts": {
- "start": "webpack-dev-server --open",
+ "start": "webpack-dev-server --open --config webpack.dev.js",
- "build": "webpack"
+ "build": "webpack --config webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"clean-webpack-plugin": "^0.1.17",
"css-loader": "^0.28.4",
"csv-loader": "^2.1.1",
"express": "^4.15.3",
"file-loader": "^0.11.2",
"html-webpack-plugin": "^2.29.0",
"style-loader": "^0.18.2",
"webpack": "^3.0.0",
"webpack-dev-middleware": "^1.12.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0",
"xml-loader": "^1.2.1"
}
}
其他功能:Split CSS
- 安装:
npm install --save-dev extract-text-webpack-plugin
配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}
]
},
plugins: [
new ExtractTextPlugin("styles.css"),
]
}