18个常用 webpack插件,总会有适合你的!

可莉
• 阅读 945

18个常用 webpack插件,总会有适合你的!

来源 | https://github.com/Michael-lzg/my--article/blob/master/webpack/

Plugin

何为插件(Plugin)?专注处理 webpack 在编译过程中的某个特定的任务的功能模块,可以称为插件。

Plugin 是一个扩展器,它丰富了 webpack 本身,针对是 loader 结束后,webpack 打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听 webpack 打包过程中的某些节点,执行广泛的任务。

  • 是一个独立的模块。

  • 模块对外暴露一个 js 函数。

  • 函数的原型 (prototype) 上定义了一个注入 compiler 对象的 apply方法 apply 函数中需要有通过 compiler 对象挂载的 webpack 事件钩子,钩子的回调中能拿到当前编译的 compilation 对象,如果是异步编译插件的话可以拿到回调 callback

  • 完成自定义子编译流程并处理 complition 对象的内部数据。

  • 如果异步编译插件的话,数据处理完成后执行 callback 回调。

下面介绍 18 个常用的 webpack 插件。

1、HotModuleReplacementPlugin

模块热更新插件。 Hot-Module-Replacement  的热更新是依赖于  webpack-dev-server ,后者是在打包文件改变时更新打包文件或者 reload 刷新整个页面, HRM  是只更新修改的部分。

HotModuleReplacementPluginwebpack 模块自带的,所以引入 webpack 后,在 plugins 配置项中直接使用即可。

`const webpack = require('webpack')`

  




  


`plugins: [`

  


` new webpack.HotModuleReplacementPlugin(), // 热更新插件`

  


`]`

 

2、html-webpack-plugin


生成 html 文件。将 webpack 中 entry 配置的相关入口  chunk  和  extract-text-webpack-plugin 抽取的 css 样式 插入到该插件提供的 template 或者 templateContent 配置项指定的内容基础上生成一个 html 文件,具体插入方式是将样式 link 插入到 head 元素中, script 插入到 head 或者 body 中。

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

  




  


`plugins: [`

  


` new HtmlWebpackPlugin({`

  


` filename: 'index.html',`

  


` template: path.join(__dirname, '/index.html'),`

  


` minify: {`

  


` // 压缩HTML文件`

  


` removeComments: true, // 移除HTML中的注释`

  


` collapseWhitespace: true, // 删除空白符与换行符`

  


` minifyCSS: true, // 压缩内联css`

  


` },`

  


` inject: true,`

  


` }),`

  


`]`

 

inject 有四个选项值

  • true:默认值,script 标签位于 html 文件的 body 底部

  • body:script 标签位于 html 文件的 body 底部(同 true)

  • head:script 标签位于 head 标签内

  • false:不插入生成的 js 文件,只是单纯的生成一个 html 文件

多页应用打包

有时,我们的应用不一定是一个单页应用,而是一个多页应用,那么如何使用 webpack 进行打包呢。

`const path = require('path')`

  


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

  


`module.exports = {`

  


` entry: {`

  


` index: './src/index.js',`

  


` login: './src/login.js',`

  


` },`

  


` output: {`

  


` path: path.resolve(__dirname, 'dist'),`

  


` filename: '[name].[hash:6].js',`

  


` },`

  


` //...`

  


` plugins: [`

  


` new HtmlWebpackPlugin({`

  


` template: './public/index.html',`

  


` filename: 'index.html', //打包后的文件名`

  


` }),`

  


` new HtmlWebpackPlugin({`

  


` template: './public/login.html',`

  


` filename: 'login.html', //打包后的文件名`

  


` }),`

  


` ],`

  


`}`

 

如果需要配置多个  HtmlWebpackPlugin ,那么  filename  字段不可缺省,否则默认生成的都是  index.html

但是有个问题, index.html  和  login.html  会发现,都同时引入了  index.f7d21a.js  和  login.f7d21a.js ,通常这不是我们想要的,我们希望  index.html  中只引入  index.f7d21a.jslogin.html  只引入  login.f7d21a.js

HtmlWebpackPlugin  提供了一个  chunks  的参数,可以接受一个数组,配置此参数仅会将数组中指定的 js 引入到 html 文件中

`module.exports = {`

  


` //...`

  


` plugins: [`

  


` new HtmlWebpackPlugin({`

  


` template: './public/index.html',`

  


` filename: 'index.html', //打包后的文件名`

  


` chunks: ['index'],`

  


` }),`

  


` new HtmlWebpackPlugin({`

  


` template: './public/login.html',`

  


` filename: 'login.html', //打包后的文件名`

  


` chunks: ['login'],`

  


` }),`

  


` ],`

  


`}`

 

这样执行  npm run build ,可以看到  index.html  中仅引入了 index 的 js 文件,而  login.html  中也仅引入了 login 的 js 文件。

3、clean-webpack-plugin

clean-webpack-plugin  用于在打包前清理上一次项目生成的 bundle 文件,它会根据  output.path  自动清理文件夹;这个插件在生产环境用的频率非常高,因为生产环境经常会通过 hash 生成很多 bundle 文件,如果不进行清理的话每次都会生成新的,导致文件夹非常庞大。

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

  




  


`plugins: [`

  


` new HtmlWebpackPlugin({`

  


` template: path.join(__dirname, '/index.html'),`

  


` }),`

  


` new CleanWebpackPlugin(), // 所要清理的文件夹名称`

  


`]`

 

4、extract-text-webpack-plugin

将 css 成生文件,而非内联 。 该插件的主要是为了抽离 css 样式,防止将样式打包在 js 中引起页面样式加载错乱的现象。

`const ExtractTextPlugin = require('extract-text-webpack-plugin')`

  




  


`plugins: [`

  


` // 将css分离到/dist文件夹下的css文件夹中的index.css`

  


` new ExtractTextPlugin('css/index.css'),`

  


`]`

 

5、mini-css-extract-plugin

将 CSS 提取为独立的文件的插件,对每个包含 css 的 js 文件都会创建一个 CSS 文件,支持按需加载 css 和  sourceMap 。只能用在 webpack4 中,对比另一个插件 extract-text-webpack-plugin 有以下特点:

  • 异步加载

  • 不重复编译,性能更好

  • 更容易使用

  • 只针对 CSS

这个插件应该只用在生产环境配置,并且在  loaders  链中不使用  style-loader , 而且这个插件暂时不支持 HMR。

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

  




  


`module.exports = {`

  


` module: {`

  


` rules: [`

  


` {`

  


` test: /\.(le|c)ss$/,`

  


` use: [`

  


` {`

  


` loader: MiniCssExtractPlugin.loader,`

  


` options: {`

  


` publicPath: '../',`

  


` },`

  


` },`

  


` 'css-loader',`

  


` 'postcss-loader',`

  


` 'less-loader',`

  


` ],`

  


` },`

  


` ],`

  


` },`

  


` plugins: [`

  


` new MiniCssExtractPlugin({`

  


` filename: 'css/[name].[contenthash:8].css',`

  


` chunkFilename: 'css/[id].[contenthash:8].css',`

  


` }),`

  


` ],`

  


`}`

 

6、purifycss-webpack

有时候我们 css 写得多了或者重复了,这就造成了多余的代码,我们希望在生产环境进行去除。

`const path = require('path')`

  


`const PurifyCssWebpack = require('purifycss-webpack') // 引入PurifyCssWebpack插件`

  


`const glob = require('glob') // 引入glob模块,用于扫描全部html文件中所引用的css`

  




  


`module.exports = merge(common, {`

  


` plugins: [`

  


` new PurifyCssWebpack({`

  


` paths: glob.sync(path.join(__dirname, 'src/*.html')),`

  


` }),`

  


` ],`

  


`})`

 

7、optimize-css-assets-webpack-plugin

我们希望减小 css 打包后的体积,可以用到  optimize-css-assets-webpack-plugin

`const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin") // 压缩css代码`

  




  


`optimization: {`

  


` minimizer: [`

  


` // 压缩css`

  


` new OptimizeCSSAssetsPlugin({})`

  


` ]`

  


` }`

 

8、UglifyJsPlugin

uglifyJsPlugin  是  vue-cli  默认使用的压缩代码方式,用来对 js 文件进行压缩,从而减小 js 文件的大小,加速 load 速度。

它使用的是单线程压缩代码,打包时间较慢,所以可以在开发环境将其关闭,生产环境部署时再把它打开。

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

  




  


`plugins: [`

  


` new UglifyJsPlugin({`

  


` uglifyOptions: {`

  


` compress: {`

  


` warnings: false`

  


` }`

  


` },`

  


` sourceMap: true,  //是否启用文件缓存`

  


` parallel: true   //使用多进程并行运行来提高构建速度`

  


` })`

 

9、ParallelUglifyPlugin

开启多个子进程,把对多个文件压缩的工作分别给多个子进程去完成,每个子进程其实还是通过  UglifyJS  去压缩代码,但是变成了并行执行。

`const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')`

  




  


`plugins: [`

  


` new ParallelUglifyPlugin({`

  


` //cacheDir 用于配置缓存存放的目录路径。`

  


` cacheDir: '.cache/',`

  


` sourceMap: true,`

  


` uglifyJS: {`

  


` output: {`

  


` comments: false,`

  


` },`

  


` compress: {`

  


` warnings: false,`

  


` },`

  


` },`

  


` }),`

  


`]`

 

10、terser-webpack-plugin

Webpack4.0 默认是使用  terser-webpack-plugin  这个压缩插件,在此之前是使用  uglifyjs-webpack-plugin ,两者的区别是后者对 ES6 的压缩不是很好,同时我们可以开启  parallel  参数,使用多进程压缩,加快压缩。

`const TerserPlugin = require('terser-webpack-plugin') // 压缩js代码`

  




  


`optimization: {`

  


` minimizer: [`

  


` new TerserPlugin({`

  


` parallel: 4, // 开启几个进程来处理压缩,默认是 os.cpus().length - 1`

  


` cache: true, // 是否缓存`

  


` sourceMap: false,`

  


` }),`

  


` ]`

  


`}`

 

11、NoErrorsPlugin

报错但不退出 webpack 进程。编译出现错误时,使用  NoEmitOnErrorsPlugin  来跳过输出阶段。这样可以确保输出资源不会包含错误。

`plugins: [new webpack.NoEmitOnErrorsPlugin()]`

 

12、compression-webpack-plugin

所有现代浏览器都支持  gzip  压缩,启用  gzip  压缩可大幅缩减传输资源大小,从而缩短资源下载时间,减少首次白屏时间,提升用户体验。

gzip 对基于文本格式文件的压缩效果最好(如:CSS、JavaScript 和 HTML),在压缩较大文件时往往可实现高达 70-90% 的压缩率,对已经压缩过的资源(如:图片)进行 gzip 压缩处理,效果很不好。

`const CompressionPlugin = require('compression-webpack-plugin')`

  




  


`plugins: [`

  


` new CompressionPlugin({`

  


` // gzip压缩配置`

  


` test: /\.js$|\.html$|\.css/, // 匹配文件名`

  


` threshold: 10240, // 对超过10kb的数据进行压缩`

  


` deleteOriginalAssets: false, // 是否删除原文件`

  


` }),`

  


`]`

 

当然,这个方法还需要后端配置支持。

13、DefinePlugin

我们可以通过  DefinePlugin  可以定义一些全局的变量,我们可以在模块当中直接使用这些变量,无需作任何声明, DefinePlugin  是  webpack  自带的插件。

`plugins: [`

  


` new webpack.DefinePlugin({`

  


` DESCRIPTION: 'This Is The Test Text.',`

  


` }),`

  


`]`

  




  


`// 直接引用`

  


`console.log(DESCRIPTION)`

 

14、ProvidePlugin

自动加载模块。任何时候,当  identifier  被当作未赋值的变量时, module 就会自动被加载,并且  identifier  会被这个 module 输出的内容所赋值。这是 webpack 自带的插件。

`module.exports = {`

  


` resolve: {`

  


` alias: {`

  


` jquery: './lib/jquery',`

  


` },`

  


` },`

  


` plugins: [`

  


` //提供全局的变量,在模块中使用无需用require引入`

  


` new webpack.ProvidePlugin({`

  


` $: 'jquery',`

  


` React: 'react',`

  


` }),`

  


` ],`

  


`}`

 

15、DLLPlugin

这是在一个额外的独立的 webpack 设置中创建一个只有 dll 的  bundle(dll-only-bundle) 。这个插件会生成一个名为  manifest.json  的文件,这个文件是用来让  DLLReferencePlugin  映射到相关的依赖上去的。

使用步骤如下

1、在 build 下创建  webpack.dll.config.js

`const path = require('path')`

  


`const webpack = require('webpack')`

  


`module.exports = {`

  


` entry: {`

  


` vendor: [`

  


` 'vue-router',`

  


` 'vuex',`

  


` 'vue/dist/vue.common.js',`

  


` 'vue/dist/vue.js',`

  


` 'vue-loader/lib/component-normalizer.js',`

  


` 'vue',`

  


` 'axios',`

  


` 'echarts',`

  


` ],`

  


` },`

  


` output: {`

  


` path: path.resolve('./dist'),`

  


` filename: '[name].dll.js',`

  


` library: '[name]_library',`

  


` },`

  


` plugins: [`

  


` new webpack.DllPlugin({`

  


` path: path.resolve('./dist', '[name]-manifest.json'),`

  


` name: '[name]_library',`

  


` }),`

  


` // 建议加上代码压缩插件,否则dll包会比较大。`

  


` new webpack.optimize.UglifyJsPlugin({`

  


` compress: {`

  


` warnings: false,`

  


` },`

  


` }),`

  


` ],`

  


`}`

 

2、在  webpack.prod.conf.js  的 plugin 后面加入配置

`new webpack.DllReferencePlugin({`

  


` manifest: require('../dist/vendor-manifest.json'),`

  


`})`

 

3、 package.json 文件中添加快捷命令 (build:dll)

`"scripts": {`

  


` "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",`

  


` "start": "npm run dev",`

  


` "lint": "eslint --ext .js,.vue src",`

  


` "build": "node build/build.js",`

  


` "build:dll": "webpack --config build/webpack.dll.conf.js"`

  


` }`

 

生产环境打包的时候先 npm run build:dll 命令会在打包目录下生成  vendor-manifest.json  文件与 vendor.dll.js 文件。然后 npm run build 生产其他文件。

4、根目录下的入口  index.html  加入引用

`<script type="text/javascript" src="./vendor.dll.js"></script>`

 

16、HappyPack

HappyPack  能让 webpack 把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。要注意的是  HappyPack  对  file-loaderurl-loader  支持的不友好,所以不建议对该 loader 使用。

1、HappyPack 插件安装

`npm i -D happypack`

 

2、 webpack.base.conf.js  文件对 module.rules 进行配置

`module: {`

  


` rules: [`

  


` {`

  


` test: /\.js$/,`

  


` use: ['happypack/loader?id=babel'],`

  


` include: [resolve('src'), resolve('test')],`

  


` exclude: path.resolve(__dirname, 'node_modules'),`

  


` },`

  


` {`

  


` test: /\.vue$/,`

  


` use: ['happypack/loader?id=vue'],`

  


` },`

  


` ]`

  


`}`

 

3、在生产环境  webpack.prod.conf.js  文件进行配置

`const HappyPack = require('happypack')`

  


`// 构造出共享进程池,在进程池中包含5个子进程`

  


`const HappyPackThreadPool = HappyPack.ThreadPool({ size: 5 })`

  


`plugins: [`

  


` new HappyPack({`

  


` // 用唯一的标识符id,来代表当前的HappyPack是用来处理一类特定的文件`

  


` id: 'babel',`

  


` // 如何处理.js文件,用法和Loader配置中一样`

  


` loaders: ['babel-loader?cacheDirectory'],`

  


` threadPool: HappyPackThreadPool,`

  


` }),`

  


` new HappyPack({`

  


` id: 'vue', // 用唯一的标识符id,来代表当前的HappyPack是用来处理一类特定的文件`

  


` loaders: [`

  


` {`

  


` loader: 'vue-loader',`

  


` options: vueLoaderConfig,`

  


` },`

  


` ],`

  


` threadPool: HappyPackThreadPool,`

  


` }),`

  


`]`

 

注意,当项目较小时,多线程打包反而会使打包速度变慢。

17、copy-webpack-plugin

我们在  public/index.html  中引入了静态资源,但是打包的时候 webpack 并不会帮我们拷贝到 dist 目录,因此  copy-webpack-plugin  就可以很好地帮我做拷贝的工作了。

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

  


`module.exports = {`

  


` plugins: [`

  


` new CopyWebpackPlugin({`

  


` patterns: [`

  


` {`

  


` from: 'public/js/*.js',`

  


` to: path.resolve(__dirname, 'dist', 'js'),`

  


` flatten: true,`

  


` },`

  


` ],`

  


` }),`

  


` ],`

  


`}`

 

18、IgnorePlugin

这是 webpack 内置插件,它的作用是:忽略第三方包指定目录,让这些指定目录不要被打包进去。

比如我们要使用  moment  这个第三方依赖库,该库主要是对时间进行格式化,并且支持多个国家语言。虽然我设置了语言为中文,但是在打包的时候,是会将所有语言都打包进去的。这样就导致包很大,打包速度又慢。

对此,我们可以用  IgnorePlugin  使得指定目录被忽略,从而使得打包变快,文件变小。

`const Webpack = require('webpack')`

  


`plugins: [`

  


` //moment这个库中,如果引用了./locale/目录的内容,就忽略掉,不会打包进去`

  


` new Webpack.IgnorePlugin(/\.\/locale/, /moment/),`

  


`]`

 

我们虽然按照上面的方法忽略了包含 ’./locale/' 该字段路径的文件目录,但是也使得我们使用的时候不能显示中文语言了,所以这个时候可以手动引入中文语言的目录。

`import moment from 'moment'`

  




  


`//手动引入所需要的语言包`

  


`import 'moment/locale/zh-cn'`

  




  


`moment.locale('zh-cn')`

  




  


`let r = moment().endOf('day').fromNow()`

  


`console.log(r)`

 

本文完~

18个常用 webpack插件,总会有适合你的!

18个常用 webpack插件,总会有适合你的!

本文分享自微信公众号 - web前端开发(web_qdkf)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这