webpack打包优化

114 阅读3分钟

1.代码分割

SplitChunksPlugin 是 Webpack 中的一个强大插件,自动优化和分割共享的代码块。可以通过以下配置来实现:

module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all', // 对于所有类型的块进行分割
      minSize: 20000, // 分割的最小大小
      maxSize: 0, // 最大大小,设置为0表示不限制
      minChunks: 1, // 最少被引用的次数
      maxAsyncRequests: 30, // 最大异步请求数
      maxInitialRequests: 30, // 最大初始请求数
      automaticNameDelimiter: '~', // 自动名称分隔符
      name: true, // 是否使用自动命名
    }
  }
};
代码分割的好处
  1. 减少初始加载时间:只加载用户需要的代码,提升页面响应速度。
  2. 提高性能:通过懒加载和按需加载,降低网络带宽消耗。
  3. 更好的缓存:分割后的文件可以被独立缓存,只有在实际变化时才会重新加载。

2.分包

在使用 webpack 进行打包时候,对于依赖的第三方库,比如 vue,vuex 等这些不会修改的依赖,我们可以让它和我们自己编写 的代码分开打包,这样做的好处是每次更改我本地代码的文件的时候,webpack 只需要打包我项目本身的文件代码,而不会再 去编译第三方库,那么第三方库在第一次打包的时候只打包一次,以后只要我们不升级第三方包的时候,那么 webpack 就不会 对这些库去打包,这样可以快速提高打包的速度。因此为了解决这个问题,DllPlugin 和 DllReferencePlugin 插件就产生了。这种 方式可以极大的减少打包类库的次数,只有当类库更新版本才需要重新打包,并且也实现了将公共代码抽离成单独文件的优化方案。

webpack.dll.config.js

const path = require('path');
const webpack = require('webpack');

module.exports = {
    mode: 'production', // 使用生产模式
    entry: {
        // 这里列出需要打包的第三方库
        vendor: ['vue', 'vuex'], // 可根据需要添加更多库
    },
    output: {
        path: path.resolve(__dirname, 'dll'), // 输出目录
        filename: '[name].dll.js', // 输出文件名
        library: '[name]_library', // 使 DLL 文件中的模块可以被引用
    },
    plugins: [
        new webpack.DllPlugin({
            name: '[name]_library', // 与 output.library 保持一致
            path: path.join(__dirname, 'dll', '[name]-manifest.json'), // 生成的 manifest 文件路径
        }),
    ],
};

创建主 Webpack 配置 webpack.config.js

const path = require('path');
const webpack = require('webpack');

module.exports = {
    mode: 'production', // 使用生产模式
    entry: './src/index.js', // 应用的入口文件
    output: {
        path: path.resolve(__dirname, 'dist'), // 输出目录
        filename: 'bundle.js', // 输出文件名
    },
    module: {
        rules: [
            {
                test: /\.js$/, // 针对 JS 文件
                exclude: /node_modules/, // 排除 node_modules
                use: 'babel-loader', // 使用 Babel 进行转译
            },
        ],
    },
    plugins: [
        // 引用 DLL 文件的插件
        new webpack.DllReferencePlugin({
            context: __dirname, // 上下文
            manifest: require(path.resolve(__dirname, 'dll', 'vendor-manifest.json')), // 引用 DLL 生成的 manifest 文件
        }),
    ],
};

3.缓存

当设置 cache.type:“filesystem”时,webpack 会在内部以分层方式启用文件系统缓存和内存缓存,将处理结果结存放到内存中, 下次打包直接使用缓存结果而不需要重新打包

const path = require('path');

module.exports = {
  mode: 'development', // 可以选择 'development' 或 'production'
  entry: './src/index.js', // 入口文件
  output: {
    filename: 'bundle.js', // 打包后的文件名
    path: path.resolve(__dirname, 'dist'), // 输出目录
  },
  cache: {
    type: 'filesystem', // 启用文件系统缓存
    buildDependencies: {
      config: [__filename], // 监视配置文件变化
    },
  },
  module: {
    rules: [
      {
        test: /\.js$/, // 处理所有 JavaScript 文件
        exclude: /node_modules/, // 排除 node_modules
        use: {
          loader: 'babel-loader', // 使用 Babel 转换 ES6 语法
        },
      },
    ],
  },
};

4.treeShaking

Tree Shaking 利用 ES6 的 importexport 语法,分析模块的依赖关系。Webpack 在构建过程中会生成一个依赖图,标记出哪些模块是被使用的,未被使用的代码会在最终打包时被剔除。

5.代码压缩

Webpack 默认在生产模式中使用 TerserWebpackPlugin 来进行代码压缩。它能够消除冗余代码,缩短变量名,从而减小文件体积

// webpack.config.js
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
    mode: 'production',
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist'),
    },
    optimization: {
        minimize: true,
        minimizer: [new TerserPlugin()],
    },
};

可以使用 css-minimizer-webpack-plugin 来压缩 CSS 文件

const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
    // 其他配置...
    optimization: {
        minimizer: [
            new TerserPlugin(),
            new CssMinimizerPlugin(),
        ],
    },
};

6.js和css分离

在项目中使用 SCSS,需要安装以下依赖:

  • sass-loader:用于编译 SCSS 文件。
  • sass:SCSS 的核心库。
  • css-loader:处理 CSS 的导入和解析。
  • mini-css-extract-plugin:提取 CSS 为单独文件。
  • style-loader(可选):在开发环境中使用。
webpack.config.js 文件中配置 loader 和插件,以实现 SCSS 和 JS 的分离:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    entry: './src/index.js', // 入口文件
    output: {
        filename: 'bundle.js', // 输出 JS 文件
        path: path.resolve(__dirname, 'dist'), // 输出路径
    },
    module: {
        rules: [
            {
                test: /\.scss$/, // 匹配 SCSS 文件
                use: [
                    MiniCssExtractPlugin.loader, // 提取 CSS
                    'css-loader', // 处理 CSS
                    'sass-loader', // 处理 SCSS
                ],
            },
        ],
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'styles.css', // 输出的 CSS 文件名
        }),
    ],
};