您的位置:

SplitChunksPlugin详解

一、SplitChunksPlugin简介

SplitChunksPlugin是webpack4中的一个插件,用于抽离公共代码,减少打包体积,提高加载速度,让页面更快地展现出来。

在基于webpack构建的项目中,通常存在着多个共同依赖的模块,每次打包时都会将这些共同依赖的模块进行打包,导致打包体积较大,下载速度慢,用户体验不佳。SplitChunksPlugin的作用就是将这些共同依赖的模块抽离成单独的chunk文件,避免重复打包,减小打包体积,提高页面加载速度,从而提升用户体验。

二、SplitChunksPlugin配置方式

SplitChunksPlugin的配置有两种方式:通过optimization属性配置和通过插件方式配置。我们主要介绍optimization属性配置方式。

三、optimization属性中的SplitChunksPlugin配置

optimization属性是webpack4中新引入的属性,用于优化webpack打包构建,其中的SplitChunksPlugin是用于分离代码的插件。

optimization属性中常见的配置项如下:

module.exports = {
  optimization: {
    // 压缩JS
    minimize: true,
    // 压缩CSS
    minimizer: [new CssMinimizerPlugin()],
    // 分离公共代码
    splitChunks: {
      // 分离代码的规则
      test: /\.js$/,
      // 分离出来的代码块的名称
      name: 'common',
      // 源代码块的最小大小
      minSize: 10000,
      // 共同依赖的模块的引入次数,大于等于该值才会被分离
      minChunks: 2,
      // 同步代码块之间的并行请求次数,0表示关闭
      maxAsyncRequests: 5,
      // 异步代码块之间的并行请求次数,0表示关闭
      maxInitialRequests: 3,
      // 模块路径抽取,默认采用模块名或包名
      automaticNameDelimiter: '~',
      // 拆分出来的块的策略
      chunks: 'all',
      // 只考虑会被切割出去的chunk
      enforceSizeThreshold: 50000,
      // 分离的代码块需要满足的条件
      cacheGroups: {
        // node_modules中的模块抽离
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all'
        },
        // 把src下的模块切割到一个单独的块中
        util: {
          test: /[\\/]src[\\/]utils[\\/]/,
          name: 'util',
          chunks: 'all'
        }
      }
    }
  }
}

以上代码中的属性含义如下:

  • test:用于选择出需要分离的模块。
  • name:抽离出来的chunk的名称。
  • minSize:限制最小大小,如果不满足,不会抽离。
  • minChunks:共同依赖的模块的引入次数,大于等于该值才会被分离。
  • maxAsyncRequests:同步代码块之间的并行请求次数,0表示关闭。
  • maxInitialRequests:异步代码块之间的并行请求次数,0表示关闭。
  • automaticNameDelimiter:模块路径抽取,默认采用模块名或包名。
  • chunks:拆分出来的块的策略,一般设置为'all'
  • cacheGroups:定义缓存组,用于分组配置。

四、cacheGroups配置项详解

cacheGroups是具体的分组配置,包含了name, test, priority, reuseExistingChunk的选项,是SplitChunksPlugin中非常重要的配置项。cacheGroups中常用的配置项如下:

  • name:抽离出来的chunk的名称。
  • test:用于选择出需要分离的模块。
  • priority:用于定义组抽取的优先级。
  • reuseExistingChunk:表示如果一个模块已经被分离出来了,是否继续重复分离。

以下是cacheGroups的配置实例。

module.exports = {
  optimization: {
    splitChunks: {
      cacheGroups: {
        // node_modules中的模块抽离
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
          priority: 1,
          reuseExistingChunk: true
        },
        // 把src下的模块切割到一个单独的块中
        util: {
          test: /[\\/]src[\\/]utils[\\/]/,
          name: 'util',
          chunks: 'all',
          priority: 2,
          reuseExistingChunk: true
        }
      }
    }
  }
}

以上配置中vendor为node_modules中的模块抽离,util为把src下的模块切割到一个单独的块中。

五、SplitChunksPlugin使用案例

下面来介绍一个使用SplitChunksPlugin插件的案例。

首先,配置webpack.config.js文件,如下:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'development',
  entry: {
    index: './src/index.js',
    detail: './src/detail.js'
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, 'dist')
  },
  optimization: {
    runtimeChunk: 'single',
    splitChunks: {
      minSize: 20000,
      maxAsyncRequests: 30,
      maxInitialRequests: 30,
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
          enforce: true
        }
      }
    }
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'SplitChunksPlugin Demo',
      template: './src/index.html'
    })
  ]
};

之后,你可以在src/index.js文件中导入react和react-dom模块,如下所示:

import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
  

Hello, world!

, document.getElementById('root') );

如果你在src/detail.js文件中也导入react和react-dom模块,那么这两个模块将会被重复打包。为了避免重复打包,使用SplitChunksPlugin,把这两个模块抽离出公共的chunk中,只需要在webpack.config.js中加入如下代码块即可:

optimization: {
  runtimeChunk: 'single',
  splitChunks: {
    minSize: 20000,
    maxAsyncRequests: 30,
    maxInitialRequests: 30,
    cacheGroups: {
      vendor: {
        test: /[\\/]node_modules[\\/]/,
        name: 'vendors',
        chunks: 'all',
        enforce: true
      }
    }
  }
}

其中,cacheGroups用于指定需要抽离的模块,这里的vendor表示需要抽离node_modules目录下的模块,因为React和React-DOM都在这个目录下,所以可以使用下面的代码引入React和React-DOM。

import React from 'react';
import ReactDOM from 'react-dom';

最后,我们运行webpack,就可以看到在dist目录下生成如下文件:

dist/
  index.html
  index.js
  vendors.js

index.js和vendors.js文件中分别包含了应用自身的代码和抽离出来的公共代码,index.html中引用的是index.js和vendors.js两个文件。

六、总结

通过使用SplitChunksPlugin插件可以抽离共同依赖的模块,减小打包体积,提高页面加载速度,提升用户体验。本文通过介绍SplitChunksPlugin的基本用法和案例,希望能够帮助读者更加深入地了解这个重要的webpack插件。