Skip to content
On this page

webpack的高级配置,优化编译性能

高级配置主要会从以下的几个点出发

  1. 提升开发体验
  2. 提升打包构建速度
  3. 减少代码体积
  4. 优化代码性能

这个章节是webpack入门到进阶最重要的章节,可以让你在其他大多数的开发者中脱颖而出,面试的难点也会集中在这里

sourceMap

在开发中如果遇到报错,我们希望快速的找到报错的地点,但是如果没有sourceMap的帮助,在webpack打包的代码中寻找错误的位置非常困难,比如像是这样:

根本就无从查起

webpack devtool中可以看到各种sourceMap的类型

推荐两种模式cheap-module-source-mapsource-map分别用于开发环境和生产环境

js
module.exports = {
  // ...
  mode:'development',
  devtool:'cheap-module-source-map'
}
1
2
3
4
5
js
module.exports = {
  // ...
  mode:'production',
  devtool:'source-map'
}
1
2
3
4
5

在配置完后,再看看出现错误的位置,就非常好找了

提升打包速度

随之开发的项目越来越大,我们打包代码的速度也会越来越慢。那么提升打包速度就极大的优化我们的开发体验

HotModuleReplacement

HotModuleReplacement 简称 HMR 热模块替换,在程序运行中,替换、添加、删除模块,而不是重新加载整个页面

如何使用

js
devServer: {
  port: 8899,
  open: true,
  host: 'localhost',
  hot:true // 在webpack5中,默认就是打开的 , 如果要测试可以先关闭在打开试一试
},
1
2
3
4
5
6

在默认的热模块更新中,css的变动是webpack默认支持的,但是js是没有默认支持,如果要支持,需要写出以下的格式

js
import { sayName } from './test'
if (module.hot) {
  module.hot.accept('./test.js')
}
1
2
3
4

在框架的开发中,比如react-loader 或者vue-loader内部帮我们已经实现了热模块更新

oneOf

oneOf的功能,是让一个文件只被一个loader解析,默认的情况,文件会被所有的loader解析,这样影响了打包速度。

js
module.exports = {
 module: {
    rules: [{
      oneOf: [
        {
          test: /\.css$/,
          // use中的顺序是从下至上执行的
          use: [
            // 将css-loader 解析出来的字符串创建成style标签添加到head当中
            'style-loader',
            // 将css的内容解析成字符串
            'css-loader'
          ]
        },
        ...restLoader
      ]
    }]
  },
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

exclude / include

这些配置选项出现在babel-loader或者eslint内,一般我们开发肯定会引入其他的包

javascript
module.exports = {
  module: {
    rules: [{
      oneOf: [
        {
          test: /\.js$/,
          exclude: /(node_modules)/,
          use: {
            loader: 'babel-loader',
          }
        }
      ]
    }]
  },
  plugins: [
    new ESLintPlugin({
      context: resolve(__dirname, '../src'),
      exclude:/(node_modules)/
    }),
  ],
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

cache

缓存可以预存我们上一次打包的结果,这样下一次打包的速度就会更快一些

如何开启缓存

javascript
module.exports = {
    module: {
    rules: [{
      oneOf: [
        {
          test: /\.js$/,
          exclude: /(node_modules)/,
          use: {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true, // 打开Babel缓存
              cacheCompression: false, //关闭缓存的压缩
            }
          },

        }
      ]
    }]
  },
  plugins: [
    new ESLintPlugin({
      context: resolve(__dirname, '../src'),
      cache:true,
      cacheLocation:'./cache/eslintCache'
    }),
  ]
}
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

Thread

Thread的概念是多进程打包

当项目极其庞大时,我们就必须要寄出这一大杀器了,多进程打包,可以运行你电脑效率到极限来做这件事,自然打包速度就飞快。

WARNING

但仅在项目极大时使用,因为启动进程同样消耗时间,如果一些小项目使用此等杀器有些得不偿失了。

  1. 读取当前电脑cpu的数量,这是我们开启的最大进程数
js
const os = require('os')
const cpus = os.cpus().length
1
2
  1. 分别为babel-loader \ eslint \ terser-webpack-loader(webpack默认的一个压缩代码的库) 开启多进程处理
sh
yarn add -D thread-loader
1
javascript

const { resolve } = require('path')
const ESLintPlugin = require('eslint-webpack-plugin');
const path = require('path');
const TerserWebpackPlugin = require('terser-webpack-plugin')
const os = require('os')
const cpus = os.cpus().length

module.exports = {
  // 入口文件
  entry: "./src/index.js",
  // 打包后输出的文件
  output: {
    filename: 'build.js',
    path: resolve(__dirname, '../build/static/'),
    clean: true
  },
  // 配置我们的loader 
  module: {
    rules: [
      {
        oneOf: [{
          test: /\.js$/,
          exclude: /(node_modules)/,
          use: [
            {
              loader: 'thread-loader', // 使用多进程对于
              options: {
                works: cpus
              }
            },
            {
              loader: 'babel-loader',
              options: {
                cacheDirectory: true, // 打开Babel缓存
                cacheCompression: false, //关闭缓存的压缩
              }
            },
          ],
        }]
      }
    ]
  },
  mode: 'production',
  optimization: {

    minimizer: [
      new CssMinimizerPlugin(),
    ]
  },
  plugins: [
    new ESLintPlugin({
      context: resolve(__dirname, '../src'),
      cache: true,
      cacheLocation: './cache/eslintCache',
      threads: cpus
    }), // 使用eslint 检测代码
    new TerserWebpackPlugin({
      parallel:cpus
    })
  ],
}
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