基本的文件目录

1
2
3
4
5
6
7
8
9
10
11
webpack-test
├── node_modules
├── public
│ └── template.html
├── src
│ ├── app.vue
│ ├── index.js
│ └── style.css
├── package-lock.json
├── package.json
└── postcss.config.js

基础配置如下

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
module.exports = env => {
const isDev = env === 'development'
return {
mode: env,
entry: path.resolve(__dirname, 'src/index.js'),
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.vue$/,
use: 'vue-loader'
},
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: [
"@babel/preset-env"
]
}
}
},
{
test: /\.(jpe?g|png|gif)$/,
use: 'file-loader'
},
{
test: /\.css$/,
use: [
!isDev ? MiniCSSExtractPlugin.loader : 'style-loader',
'css-loader'
]
}
]
},
plugins: [
new VueLoaderPlugin(),
!isDev && new MiniCSSExtractPlugin(),
new HTMLWebpackPlugin({
template: path.resolve(__dirname, 'public/template.html'),
filename: 'index.html'
})
].filter(Boolean)
}
}

webpack 自带优化

webpack 自带优化无需配置,在生产环境自动生效

作用域提升(Scope Hoisting)

假设有两个文件

module.js
1
2
export const a = 1
export const b = 2
index.js
1
2
3
4
5
import { a, b } from "./module.js"

const c = 3
const d = a + b + c
console.log(d, 'scope-hoisting')

可以看到在开发环境打包结果基本没有优化

1
2
3
4
// ...
// ...var c = 3;\nvar d = _module_js__WEBPACK_IMPORTED_MODULE_0__[\"a\"] + _module_js__WEBPACK_IMPORTED_MODULE_0__[\"b\"] + c;\nconsole.log(d, 'scope-hoisting');
// ...
// ...var a = 1;\nvar b = 2;...

而在生产环境下变量 a, b, c, d 则被省略,直接计算出了结果

1
// ...function(e,t,r){"use strict";r.r(t);console.log(6,"scope-hoisting")}

需要注意的是,仅在 ES6 的模块化语法中生效

Tree Shaking

通过 Tree Shaking 可以剔除 JavaScript 中用不上的代码,同样仅在 ES6 的模块化语法中生效

module.js
1
2
3
4
5
6
7
export const fn1 = (a, b) => {
return a + b
}

export const fn2 = (a, b) => {
return a - b
}
index.js
1
2
3
import { fn1, fn2 } from "./module.js"

console.log(fn1(1, 2), 'tree-shaking')

在生产环境下打包后只保留了fn1

1
// ...function(e,t,r){"use strict";r.r(t);console.log(1+2,"tree-shaking")}

删除多余的 CSS 样式

假设有如下 CSS 代码

1
2
3
4
5
6
div {
background: gray;
}
.useless-class {
background: yellow;
}

这里的.useless-class显然是多余的(没有该类),我们可以搜索src目录下的文件,并且使用 purgecss-webpack-plugin 插件删除无用的样式

1
$ npm install purgecss-webpack-plugin --save-dev

需要注意的是,该插件要配合 mini-css-extract 使用,配置如下

webpack.config.js
1
2
3
4
5
6
7
8
9
const glob = require('glob')
const PurgeCSSWebpackPlugin = require('purgecss-webpack-plugin')

plugins: [
!isDev && new MiniCSSExtractPlugin(),
!isDev && new PurgeCSSWebpackPlugin({
paths: glob.sync(`${path.join(__dirname, 'src')}/**/*`, { nodir: true })
})
]

运行npm run build之后打包结果为

1
2
3
div {
background: gray;
}

图片压缩

1
$ npm install image-webpack-loader --save-dev

CDN 加载文件

拆分 bundles

动态加载

打包文件分析工具

SplitChunks

热更新

IgnorePlugin

费时分析

noParse

resolve

include/exclude

在使用 loader 时,可以指定哪些文件不通过 loader ,或者指定哪些文件通过 loader

webpack.config.js
1
2
3
4
5
6
{
test: /\.js$/,
use: "babel-loader",
include:path.resolve(__dirname,'src'),
exclude:/node_modules/
}

happypack