總結18個webpack插件

何爲插件(Plugin)?專一處理 webpack 在編譯過程當中的某個特定的任務的功能模塊,能夠稱爲插件。javascript

Plugin 是一個擴展器,它豐富了 webpack 自己,針對是 loader 結束後,webpack 打包的整個過程,它並不直接操做文件,而是基於事件機制工做,會監聽 webpack 打包過程當中的某些節點,執行普遍的任務。php

 

Plugin 的特色

  • 是一個獨立的模塊
  • 模塊對外暴露一個 js 函數
  • 函數的原型 (prototype) 上定義了一個注入 compiler 對象的 apply方法 apply 函數中須要有經過 compiler 對象掛載的 webpack 事件鉤子,鉤子的回調中能拿到當前編譯的 compilation 對象,若是是異步編譯插件的話能夠拿到回調 callback
  • 完成自定義子編譯流程並處理 complition 對象的內部數據
  • 若是異步編譯插件的話,數據處理完成後執行 callback 回調。

下面介紹 18 個經常使用的 webpack 插件。css

HotModuleReplacementPlugin

模塊熱更新插件。Hot-Module-Replacement 的熱更新是依賴於 webpack-dev-server,後者是在打包文件改變時更新打包文件或者 reload 刷新整個頁面,HRM 是隻更新修改的部分。html

HotModuleReplacementPlugin是webpack模塊自帶的,因此引入webpack後,在plugins配置項中直接使用便可。vue

const webpack = require('webpack') plugins: [ new webpack.HotModuleReplacementPlugin(), // 熱更新插件 ]

 

html-webpack-plugin

生成 html 文件。將 webpack 中entry配置的相關入口 chunk 和 extract-text-webpack-plugin抽取的 css 樣式 插入到該插件提供的template或者templateContent配置項指定的內容基礎上生成一個 html 文件,具體插入方式是將樣式link插入到head元素中,script插入到head或者body中。java

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 有四個選項值node

  • true:默認值,script 標籤位於 html 文件的 body 底部
  • body:script 標籤位於 html 文件的 body 底部(同 true)
  • head:script 標籤位於 head 標籤內
  • false:不插入生成的 js 文件,只是單純的生成一個 html 文件

多頁應用打包react

有時,咱們的應用不必定是一個單頁應用,而是一個多頁應用,那麼如何使用 webpack 進行打包呢。jquery

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。webpack

可是有個問題,index.html 和 login.html 會發現,都同時引入了 index.f7d21a.js 和 login.f7d21a.js,一般這不是咱們想要的,咱們但願 index.html 中只引入 index.f7d21a.js,login.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 文件。

vi設計http://www.maiqicn.com 辦公資源網站大全https://www.wode007.com

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(), // 所要清理的文件夾名稱 ]

 

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'), ]

 

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', }), ], }

 

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')), }), ], })

 

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({}) ] }

 

UglifyJsPlugin

uglifyJsPlugin 是 vue-cli 默認使用的壓縮代碼方式,用來對 js 文件進行壓縮,從而減少 js 文件的大小,加速 load 速度。它使用的是單線程壓縮代碼,打包時間較慢,因此能夠在開發環境將其關閉,生產環境部署時再把它打開。

const UglifyJsPlugin = require('uglifyjs-webpack-plugin') plugins: [ new UglifyJsPlugin({ uglifyOptions: { compress: { warnings: false } }, sourceMap: true, //是否啓用文件緩存 parallel: true //使用多進程並行運行來提升構建速度 })

 

ParallelUglifyPlugin

開啓多個子進程,把對多個文件壓縮的工做分別給多個子進程去完成,每一個子進程其實仍是經過 UglifyJS 去壓縮代碼,可是變成了並行執行。

const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin') plugins: [ new ParallelUglifyPlugin({ //cacheDir 用於配置緩存存放的目錄路徑。 cacheDir: '.cache/', sourceMap: true, uglifyJS: { output: { comments: false, }, compress: { warnings: false, }, }, }), ]

 

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, }), ] }

 

NoErrorsPlugin

報錯但不退出 webpack 進程。編譯出現錯誤時,使用 NoEmitOnErrorsPlugin 來跳過輸出階段。這樣能夠確保輸出資源不會包含錯誤。

plugins: [new webpack.NoEmitOnErrorsPlugin()]

 

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, // 是否刪除原文件 }), ]

固然,這個方法還須要後端配置支持。

 

DefinePlugin

咱們能夠經過 DefinePlugin 能夠定義一些全局的變量,咱們能夠在模塊當中直接使用這些變量,無需做任何聲明,DefinePlugin 是 webpack 自帶的插件。

plugins: [
  new webpack.DefinePlugin({ DESCRIPTION: 'This Is The Test Text.', }), ] // 直接引用 console.log(DESCRIPTION)

 

ProvidePlugin

自動加載模塊。 任什麼時候候,當 identifier 被看成未賦值的變量時, module 就會自動被加載,而且 identifier 會被這個 module 輸出的內容所賦值。這是 webpack 自帶的插件。

module.exports = { resolve: { alias: { jquery: './lib/jquery', }, }, plugins: [ //提供全局的變量,在模塊中使用無需用require引入 new webpack.ProvidePlugin({ $: 'jquery', react: 'react', }), ], }

 

DLLPlugin

這是在一個額外的獨立的 webpack 設置中建立一個只有 dll 的 bundle(dll-only-bundle)。 這個插件會生成一個名爲 manifest.json 的文件,這個文件是用來讓 DLLReferencePlugin 映射到相關的依賴上去的。

使用步驟以下

一、在 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, }, }), ], }

二、在 webpack.prod.conf.js 的 plugin 後面加入配置

new webpack.DllReferencePlugin({ manifest: require('../dist/vendor-manifest.json'), })

三、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生產其餘文件。

四、根目錄下的入口 index.html 加入引用

<script type="text/JavaScriptsrc="./vendor.dll.js"></script>

 

HappyPack

HappyPack 能讓 webpack 把任務分解給多個子進程去併發的執行,子進程處理完後再把結果發送給主進程。要注意的是 HappyPack 對 file-loader、url-loader 支持的不友好,因此不建議對該 loader 使用。

一、HappyPack 插件安裝

npm i -D happypack

二、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'], }, ] }

三、在生產環境 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, }), ]

注意,當項目較小時,多線程打包反而會使打包速度變慢。

 

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, }, ], }), ], }

 

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)
相關文章
相關標籤/搜索