webpack系列之16个常用的插件

3,458 阅读4分钟

webpack 是个很强大的构建工具,其丰富灵活的配置决定了使用也不简单。在面试中经常能遇到 webpack 相关的问题,如果平常只是使用脚手架如 vue-cli 而没有好好深入学习研究 webpack 的话,估计答不上什么。我相信,如果没有深入了解,部分面试官也问不出什么。可能也就变成了两个人侃侃如何配置出入口,常见的 loader,plugin 有哪些。

作为一名多年油条前端,一直没有正视 webpack 相关知识,面对 webpack 相关的面试题更是一问三不知。这次准备好好学习研究 webpack相关内容,并且将学习内容记录成 webpack 系列,希望可以让不了解 webpack 的小白能对其有所掌握。

常用的webpack插件

前面我们简单介绍了如何开发一个 webpack 插件,现在我们来看看在日常开发中有哪些常用的插件

1、HtmlWebpackPlugin

作用:根据模板文件自动生成 html 文件,并且将输出文件JS自动插入到 html 中,免去了需要手动更新版本号的烦恼。

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

new HtmlWebpackPlugin({
    template: './public/index.html',
    filename: 'index.html'
})

2、CleanWebpackPlugin

作用:用于清除打包的输出文件夹,试想如果每次打包出的文件都带有不同版本号,不及时清除文件夹,那么是不是会越来越大。本插件可以帮助我们自动清除,避免手动操作。

const { CleanWebpackPlugin } = require('clean-webpack-plugin')

new CleanWebpackPlugin()

3、CopyWebpackPlugin

作用:将文件从某一目录复制到另一目录,可以用于 public 下的静态文件,比如和 html 同级的 JS 文件,无需参与编译但是需要输出到 dist 目录

const CopyWebpackPlugin = require('copy-webpack-plugin')

new CopyWebpackPlugin([
    { from: 'public/*.js', flatten: true },
])

4、webpack.DefinePlugin

作用:定义某些变量的值,在打包时用变量值替代变量

new webpack.DefinePlugin({
    ISPRO: true
})

在JS中

if (ISPRO) {
    console.log(true);
}

打包后将被替换为

if (true) {
    console.log(true);
}

5、MiniCssExtractPlugin

作用:抽离 css 到独立的文件中,否则将会以内嵌的方式嵌在 html 中

const MiniCssExtractPlugin = require('mini-css-extract-plugin')

new MiniCssExtractPlugin({
    filename: '[name].css'
})

6、PurgeCSSPlugin

作用:删除没有引用到的选择器及其样式,需要配置判断引用文件,如 html,js。起到 css tree-shaking 的效果。需要注意的是,不会删除重复的选择器样式,这个属于压缩的任务。

const glob = require('glob-all');
const PurgeCSSPlugin = require('purgecss-webpack-plugin')

new PurgeCSSPlugin({
    paths: glob.sync([path.resolve(__dirname, 'public/*.html'), 
        path.resolve(__dirname, '*.js')],  { nodir: true }),
})

7、webpack.ProvidePlugin

作用:配置全局模块,避免多次引入的麻烦

new webpack.ProvidePlugin({
    _: 'lodash'
})

在任意 JS 中可以使用 _ 而无需再次引入

console.log(_)

8、BundleAnalyzerPlugin

作用:文件分析插件,可以用于打包后资源的依赖及大小分析

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

new BundleAnalyzerPlugin({
    generateStatsFile: true
})

9、ImageminPlugin

作用:压缩图片

const ImageminPlugin = require('imagemin-webpack-plugin').default

new ImageminPlugin({
    pngquant: {
        quality: '95-100'
    }
})

PS: 由于该插件安装依赖其它文件的下载,可能会导致下载不了的情况,可以尝试切换为 cnpm 下载,以及尝试不同版本的下载情况。

10、CompressionPlugin

作用:启用传输压缩,比如将资源压缩为 GZIP 格式。需要服务端进行配合。

const CompressionPlugin = require("compression-webpack-plugin");

new CompressionPlugin({
    // gzip压缩配置
    test: /\.js$|\.html$|\.css/, // 匹配文件名
    threshold: 10240, // 对超过10kb的数据进行压缩
    deleteOriginalAssets: false, // 是否删除原文件
})

11、webpack.NoEmitOnErrorsPlugin

作用:遇到编译报错不输出。比如我们启用热加载开发时,改错资源引用将导致页面实时报错,配置该插件可以让遇到错误的编译不再输出资源文件,页面也不会更新报错。打包时也是如此,遇到错误将跳过输出。

new webpack.NoEmitOnErrorsPlugin()

12、OptimizeCssAssetsPlugin

作用:压缩css,会去除重复的类名样式

const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');

new OptimizeCssAssetsPlugin({
    assetNameRegExp: /\.css$/g
})

13、UglifyJsPlugin

作用:压缩JS

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

new UglifyJsPlugin()

14、webpack.HotModuleReplacementPlugin

作用:热加载插件,配合热加载设置,提高开发效率

new webpack.HotModuleReplacementPlugin()

15、TerserPlugin

作用:压缩JS,和 UglifyJsPlugin 插件相比,能更好的处理 ES6 以上语法

const TerserPlugin = require('terser-webpack-plugin');

optimization: {
    minimize: true,
    minimizer: [
        new TerserPlugin({
            parallel: true
        }),
    ]
}

16、optimization.splitChunks

作用:提取多入口的公共文件,避免重复打包。或者提取某一模块文件(如node_modules),配合页面缓存来提高页面加载速度

optimization: {
   splitChunks: {
        chunks: 'all',
        cacheGroups: {
            vendor: {
                test: /node_modules/,
                name: 'vendor',
                minChunks: 1,
            }
        }
    }
}

后话

其实每个插件都有其丰富的配置选项,在这里我只是简单的罗列了下其主要功能及极简配置。如果想要深入学习理解的话还是得往每个插件的 npm 主页进行查看,学习其配置文档。在配置的过程中我也遇到不同的坑,主要是版本问题,所以在这边贴出我的配置版本及代码,遇到问题的可以看看。

webpack.config.js

const path = require('path');
const glob = require('glob-all');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const PurgeCSSPlugin = require('purgecss-webpack-plugin')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CompressionPlugin = require("compression-webpack-plugin");
const TerserPlugin = require('terser-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const ImageminPlugin = require('imagemin-webpack-plugin').default

module.exports = {
    mode: 'none',
    entry: './index.js',
    output: {
        filename: '[name]-[chunkhash:6].js',
        path: path.resolve(__dirname, 'dist'),
        publicPath: './'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    'style-loader'
                ]
            },
            {
                test: /\.css$/,
                use: [{
                    loader: MiniCssExtractPlugin.loader,
                    options: {
                        esModule: false
                    }
                }, 'css-loader']
            },
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                {
                    loader: 'url-loader',
                    options: {
                        limit: 1024
                    }
                }]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './public/index.html',
            filename: 'index.html'
        }),

        new CleanWebpackPlugin(),

        new webpack.DefinePlugin({
            ISPRO: true
        }),
        
        new CopyWebpackPlugin([
            { from: 'public/*.js', flatten: true },
        ]),

        new MiniCssExtractPlugin({
            filename: '[name].css'
        }),

        new PurgeCSSPlugin({
            paths: glob.sync([path.resolve(__dirname, 'public/*.html'), 
                path.resolve(__dirname, '*.js')],  { nodir: true }),
        }),

        new webpack.ProvidePlugin({
            _: 'lodash'
        }),

        new BundleAnalyzerPlugin({
            generateStatsFile: true
        }),

        // cnpm i imagemin-webpack-plugin@1.5.0-beta.1 -D
        new ImageminPlugin({
            pngquant: {
                quality: '95-100'
            }
        }),
        
        new CompressionPlugin({
            // gzip压缩配置
            test: /\.js$|\.html$|\.css/, // 匹配文件名
            threshold: 10240, // 对超过10kb的数据进行压缩
            deleteOriginalAssets: false, // 是否删除原文件
        }),
        
        new webpack.NoEmitOnErrorsPlugin(),

        new OptimizeCssAssetsPlugin({
            assetNameRegExp: /\.css$/g
        }),
        
        // new webpack.HotModuleReplacementPlugin()

        // new UglifyJsPlugin()
    ],

    optimization: {
        splitChunks: {
            chunks: 'all',
            cacheGroups: {
                vendor: {
                    test: /node_modules/,
                    name: 'vendor',
                    minChunks: 1,
                }
            }
        },
        minimize: true,
        minimizer: [
            new TerserPlugin({
                parallel: true
            }),
        ]
    }
}

package.json

{
    "name": "webpack-test",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "dependencies": {
        "lodash": "^4.17.20"
    },
    "devDependencies": {
        "clean-webpack-plugin": "^3.0.0",
        "compression-webpack-plugin": "^6.0.0",
        "copy-webpack-plugin": "^5.1.2",
        "css-loader": "^5.0.1",
        "file-loader": "^6.2.0",
        "glob-all": "^3.2.1",
        "html-webpack-plugin": "^4.3.0",
        "imagemin-webpack-plugin": "^1.5.0-beta.1",
        "mini-css-extract-plugin": "^1.3.3",
        "npm": "^6.14.9",
        "optimize-css-assets-webpack-plugin": "^5.0.4",
        "purgecss-webpack-plugin": "^3.0.0",
        "style-loader": "^2.0.0",
        "terser-webpack-plugin": "^4.0.0",
        "uglifyjs-webpack-plugin": "^2.2.0",
        "url-loader": "^4.1.1",
        "webpack": "^4.44.2",
        "webpack-bundle-analyzer": "^4.2.0",
        "webpack-cli": "^3.3.12"
    },
    "author": "",
    "license": "ISC"
}

参考


欢迎到前端菜鸟群一起学习交流~516913974