Webpack 项目打包压缩优化

2023-10-23 17:51:24 浏览数 (3)

针对与webpack项目打包,我们正常做的最多的就是脚手架安装,后run build直接部署,不会去做过多的处理。

对webpack学习,使用webpack打包优化,主要注重两点

  • 面向开发者:提示打包速度
  • 面向用户:缩小打包体积

webpack 优化常用

打包速度优化

  • 安装 speed-measure-webpack-plugin speed-measure-webpack-plugin中有对应操作。 来看下项目打包的速度。
代码语言:txt复制
npm i speed-measure-webpack-plugin -D

使用

代码语言:txt复制
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");

const smp = new SpeedMeasurePlugin();

// 将webpack配置内容用wrap包裹起来
const webpackConfig = smp.wrap({
  plugins: [new MyPlugin(), new MyOtherPlugin()],
});

执行打包命令后,可以看出哪个插件打包耗时比较高,已进行针对优化打包速度

使用thread-loader进行多线程打包优化

  • 安装thread-loader
代码语言:txt复制
npm install --save-dev thread-loader

使用时在配置loader时将thread-loader加在比较耗时的loader前面

代码语言:txt复制
  module: {
    rules: [
      {
        test: /.js$/,
        include: path.resolve('src'),
        use: [
          "thread-loader", // 在耗时的loader前加上thread-loader进行多线程打包
          // 耗时的 loader (例如 babel-loader)
        ],
      },
    ],
  },

官方提供了thread-loader的配置参数,可以修改参数达到提速的效果。

代码语言:txt复制
 use: [
  {
    loader: "thread-loader",
    // 有同样配置的 loader 会共享一个 worker 池
    options: {
      // 产生的 worker 的数量,默认是 (cpu 核心数 - 1),或者,
      // 在 require('os').cpus() 是 undefined 时回退至 1
      workers: 2,

      // 一个 worker 进程中并行执行工作的数量
      // 默认为 20
      workerParallelJobs: 50,

      // 额外的 node.js 参数
      workerNodeArgs: ['--max-old-space-size=1024'],

      // 允许重新生成一个僵死的 work 池
      // 这个过程会降低整体编译速度
      // 并且开发环境应该设置为 false
      poolRespawn: false,

      // 闲置时定时删除 worker 进程
      // 默认为 500(ms)
      // 可以设置为无穷大,这样在监视模式(--watch)下可以保持 worker 持续存在
      poolTimeout: 2000,

      // 池分配给 worker 的工作数量
      // 默认为 200
      // 降低这个数值会降低总体的效率,但是会提升工作分布更均一
      poolParallelJobs: 50,

      // 池的名称
      // 可以修改名称来创建其余选项都一样的池
      name: "my-pool"
    },
  },
  // 耗时的 loader(例如 babel-loader)
];

现在的脚手架大多更新迭代很快,可能会出现 使用了多线程但是速度并未提升很多的可能。除了工具还需要阅读代码,查看使用的插件在项目中的场景,综合考虑解决办法

打包体积优化

  • 安装 webpack-bundle-analyzer 会弹出一个网页来显示项目打包后的体积大小,根据打包提及来优化 使用
代码语言:txt复制
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
      // 只需要在plugin中new一个实例就可以了。 
    new BundleAnalyzerPlugin()
  ]
}

webpack 分包处理

我们可以自行决定将webpack中哪内容分包出去。

例如我们要将项目中的react-dom@material-ui/xxx相关内容分包出去

  • 创建 webpack.dll.config,js用来写分包的配置文件
代码语言:txt复制
const path = require('path')
const webpack = require('webpack')
modules.exports = {
    mode:'production', // 只在生产环境才使用
    entry:{
        common:[
            // 想要分包的依赖
            'react-dom',
            '@material-ui/core',
            '@material-ui/icons',
            '@material-ui/lab'
        ]
    },
    output:{
        path:path.resolve(__dirname, "../dll"), //文件生成的路径再上一级的dll文件夹
        fillname:'[name].dll.js', // [name]会与入口文件名称相同,
        library:'[name]_[hash]' // [hash] 会自动生成hash值
    },
    plugins:[
        new webpack.DllPlugin({
            path: path.resolve(__dirname, "../dll", "[name]-manifest.json"),
            name: '[name]_[hash]' // 要与library名称相同
        })
    ]
}

随后需要在package.json中配置分包命令

代码语言:txt复制
"scripts": {
    "build-dll":"webpack --config config/webpack.dll.config.js" //config/webpack.dll.config.js 是分包的配置文件地址
}

运行时需要安装webpack-cli 如果没有安装,会提示安装

代码语言:txt复制
npm run build-dll

运行成功后,dll文件夹下会生成 对应的 common-manifest.jsonconmon.dll.js文件

  • 生产分包需要需要在webpack中将分的包排除出去 在项目打包的webpack配置文件中
代码语言:txt复制
plugins:[
    new webpack.DllReferencePlugin({
        context:path.resolve(__dirname, '../'),
        manifest:path.resolve(__dirname, '../dll/common-manifest.json') //对应生成的manifest文件路径
    })
]

此时运行npm run build webpack-bundle-analyzer弹出页面,分包出去的依赖就已经消失了。体积也会缩小。

  • 引入分包文件 引入分包文件需要安装 copy-webpack-pluginhtml-webpack-tags-pluginnpm i copy-webpack-plugin html-webpack-tags-plugin -Dcopy-webpack-plugin使用如果webpack版本可能会报错,报错可以尝试修改copy-webpack-plugin的版本后再重新打包
  • 使用
代码语言:txt复制
const CopyWebpackPlugin  =require('copy-webpack-plugin')
const HtmlWebpackTagsPlugin = require('html-webpack-tags-plugin')
plugins:[
    new webpack.DllReferencePlugin({
        context:path.resolve(__dirname, '../'),
        manifest:path.resolve(__dirname, '../dll/common-manifest.json') //对应生成的manifest文件路径
    }),
    // 将生成的dll文件拷贝到打包生成的目录
    new CopyWebpackPlugin = ({
        patterns:[
            {
                from:"./dll/common.dll.js", // 分包生成的文件
                to:"./static/js" //打包生成目录
            }
        ]
    })
    // 将拷贝过来的分包文件进行引用
    new HtmlWebpackTagsPlugin({
        tags:['/static/js/common.dll.js'],
        append:false
    })
]

这里可能会存在打包后生成的连接名称替换不成功,大多是因为speed-measure-webpack-plugin可能会有冲突,将speed-measure-webpack-plugin禁用可以解决。

代码语言:txt复制
const smp = new SpeedMeasurePlugin({
    disable:true
});

常用的webpack plugin

plugin名称

作用

HotModuleReplacementPlugin

模块热更新

clean-webpack-plugin

目录清理

html-webpack-plugin

自动生成一个index.html文件,将打包的js文件自动通过<script>标签引用

uglifyjs-webpack-plugin

js压缩

mini-css-extract-plugin

分离样式文件,将ss提取为单独文件

DefinePlugin

定义全局常量,应用:在不用环境下引入不通的配置

speed-measure-webpack-plugin

输出打包内容速度

webpack-bundle-analyzer

可视化webpack输入文件体积

常用loader 介绍

loader名称

作用

css-loader

用于处理css文件,是的在js文件中可以引入

style-loader

将css文件注入到index.html中的style标签上

less-loader

处理less代码

sass-loader

处理sass代码

babel-loader

把ES6转ES5

ts-loader

把typescript 转成es5

file-loader

打包图片,打包字体图标

webpack-bundle-analyzer

可视化webpack输入文件体积

html-withimg-loader

打包HTML文件中的图片

eslint-loader

用于检查常见的代码错误,和书写规范检查

0 人点赞