<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【面試】815- 面試官常問的 webpack 插件

          共 18492字,需瀏覽 37分鐘

           ·

          2020-12-23 14:12

          Plugin

          ?

          何為插件(Plugin)?專注處理 webpack 在編譯過程中的某個(gè)特定的任務(wù)的功能模塊,可以稱為插件。plugin 是一個(gè)擴(kuò)展器,它豐富了 webpack 本身,針對(duì)是 loader 結(jié)束后,webpack 打包的整個(gè)過程,它并不直接操作文件,而是基于事件機(jī)制工作,會(huì)監(jiān)聽 webpack 打包過程中的某些節(jié)點(diǎn),執(zhí)行廣泛的任務(wù)。

          ?

          Plugin 的特點(diǎn)

          • 是一個(gè)獨(dú)立的模塊
          • 模塊對(duì)外暴露一個(gè) js 函數(shù)
          • 函數(shù)的原型 (prototype) 上定義了一個(gè)注入 compiler 對(duì)象的 apply方法 apply 函數(shù)中需要有通過 compiler 對(duì)象掛載的 webpack 事件鉤子,鉤子的回調(diào)中能拿到當(dāng)前編譯的 compilation 對(duì)象,如果是異步編譯插件的話可以拿到回調(diào) callback
          • 完成自定義子編譯流程并處理 complition 對(duì)象的內(nèi)部數(shù)據(jù)
          • 如果異步編譯插件的話,數(shù)據(jù)處理完成后執(zhí)行 callback 回調(diào)。

          下面介紹 18 個(gè)常用的 webpack 插件

          HotModuleReplacementPlugin

          模塊熱更新插件。Hot-Module-Replacement 的熱更新是依賴于 webpack-dev-server,后者是在打包文件改變時(shí)更新打包文件或者 reload 刷新整個(gè)頁面,HRM 是只更新修改的部分。

          HotModuleReplacementPluginwebpack模塊自帶的,所以引入webpack后,在plugins配置項(xiàng)中直接使用即可。

          const webpack = require('webpack')

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

          html-webpack-plugin

          生成 html 文件。將 webpack 中entry配置的相關(guān)入口 chunkextract-text-webpack-plugin抽取的 css 樣式 插入到該插件提供的template或者templateContent配置項(xiàng)指定的內(nèi)容基礎(chǔ)上生成一個(gè) 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文件
                removeCommentstrue// 移除HTML中的注釋
                collapseWhitespacetrue// 刪除空白符與換行符
                minifyCSStrue// 壓縮內(nèi)聯(lián)css
              },
              injecttrue,
            }),
          ]

          inject 有四個(gè)選項(xiàng)值

          • true:默認(rèn)值,script 標(biāo)簽位于 html 文件的 body 底部
          • body:script 標(biāo)簽位于 html 文件的 body 底部(同 true)
          • head:script 標(biāo)簽位于 head 標(biāo)簽內(nèi)
          • false:不插入生成的 js 文件,只是單純的生成一個(gè) html 文件

          多頁應(yīng)用打包

          有時(shí),我們的應(yīng)用不一定是一個(gè)單頁應(yīng)用,而是一個(gè)多頁應(yīng)用,那么如何使用 webpack 進(jìn)行打包呢。

          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'//打包后的文件名
              }),
            ],
          }

          如果需要配置多個(gè) HtmlWebpackPlugin,那么 filename 字段不可缺省,否則默認(rèn)生成的都是 index.html

          但是有個(gè)問題,index.htmllogin.html 會(huì)發(fā)現(xiàn),都同時(shí)引入了 index.f7d21a.jslogin.f7d21a.js,通常這不是我們想要的,我們希望 index.html 中只引入 index.f7d21a.jslogin.html 只引入 login.f7d21a.js

          HtmlWebpackPlugin 提供了一個(gè) chunks 的參數(shù),可以接受一個(gè)數(shù)組,配置此參數(shù)僅會(huì)將數(shù)組中指定的 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'],
              }),
            ],
          }

          這樣執(zhí)行 npm run build,可以看到 index.html 中僅引入了 index 的 js 文件,而 login.html 中也僅引入了 login 的 js 文件。

          clean-webpack-plugin

          clean-webpack-plugin 用于在打包前清理上一次項(xiàng)目生成的 bundle 文件,它會(huì)根據(jù) output.path 自動(dòng)清理文件夾;這個(gè)插件在生產(chǎn)環(huán)境用的頻率非常高,因?yàn)樯a(chǎn)環(huán)境經(jīng)常會(huì)通過 hash 生成很多 bundle 文件,如果不進(jìn)行清理的話每次都會(huì)生成新的,導(dǎo)致文件夾非常龐大。

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

          plugins: [
            new HtmlWebpackPlugin({
              template: path.join(__dirname, '/index.html'),
            }),
            new CleanWebpackPlugin(), // 所要清理的文件夾名稱
          ]

          extract-text-webpack-plugin

          將 css 成生文件,而非內(nèi)聯(lián) 。該插件的主要是為了抽離 css 樣式,防止將樣式打包在 js 中引起頁面樣式加載錯(cuò)亂的現(xiàn)象

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

          plugins: [
            // 將css分離到/dist文件夾下的css文件夾中的index.css
            new ExtractTextPlugin('css/index.css'),
          ]

          mini-css-extract-plugin

          將 CSS 提取為獨(dú)立的文件的插件,對(duì)每個(gè)包含 css 的 js 文件都會(huì)創(chuàng)建一個(gè) CSS 文件,支持按需加載 css 和 sourceMap。只能用在 webpack4 中,對(duì)比另一個(gè)插件 extract-text-webpack-plugin 有以下特點(diǎn):

          • 異步加載
          • 不重復(fù)編譯,性能更好
          • 更容易使用
          • 只針對(duì) CSS

          這個(gè)插件應(yīng)該只用在生產(chǎn)環(huán)境配置,并且在 loaders 鏈中不使用 style-loader, 而且這個(gè)插件暫時(shí)不支持 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

          有時(shí)候我們 css 寫得多了或者重復(fù)了,這就造成了多余的代碼,我們希望在生產(chǎn)環(huán)境進(jìn)行去除。

          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

          uglifyJsPluginvue-cli 默認(rèn)使用的壓縮代碼方式,用來對(duì) js 文件進(jìn)行壓縮,從而減小 js 文件的大小,加速 load 速度。它使用的是單線程壓縮代碼,打包時(shí)間較慢,所以可以在開發(fā)環(huán)境將其關(guān)閉,生產(chǎn)環(huán)境部署時(shí)再把它打開。

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

          plugins: [
            new UglifyJsPlugin({
              uglifyOptions: {
                compress: {
                  warningsfalse
                }
              },
              sourceMaptrue,  //是否啟用文件緩存
              paralleltrue   //使用多進(jìn)程并行運(yùn)行來提高構(gòu)建速度
            })

          ParallelUglifyPlugin

          開啟多個(gè)子進(jìn)程,把對(duì)多個(gè)文件壓縮的工作分別給多個(gè)子進(jìn)程去完成,每個(gè)子進(jìn)程其實(shí)還是通過 UglifyJS 去壓縮代碼,但是變成了并行執(zhí)行。

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

          plugins: [
            new ParallelUglifyPlugin({
              //cacheDir 用于配置緩存存放的目錄路徑。
              cacheDir'.cache/',
              sourceMaptrue,
              uglifyJS: {
                output: {
                  commentsfalse,
                },
                compress: {
                  warningsfalse,
                },
              },
            }),
          ]

          terser-webpack-plugin

          Webpack4.0 默認(rèn)是使用 terser-webpack-plugin 這個(gè)壓縮插件,在此之前是使用 uglifyjs-webpack-plugin,兩者的區(qū)別是后者對(duì) ES6 的壓縮不是很好,同時(shí)我們可以開啟 parallel 參數(shù),使用多進(jìn)程壓縮,加快壓縮。

          const TerserPlugin = require('terser-webpack-plugin'// 壓縮js代碼

          optimization: {
            minimizer: [
              new TerserPlugin({
                parallel4// 開啟幾個(gè)進(jìn)程來處理壓縮,默認(rèn)是 os.cpus().length - 1
                cachetrue// 是否緩存
                sourceMapfalse,
              }),
            ]
          }

          NoErrorsPlugin

          報(bào)錯(cuò)但不退出 webpack 進(jìn)程。編譯出現(xiàn)錯(cuò)誤時(shí),使用 NoEmitOnErrorsPlugin 來跳過輸出階段。這樣可以確保輸出資源不會(huì)包含錯(cuò)誤。

          plugins: [new webpack.NoEmitOnErrorsPlugin()]

          compression-webpack-plugin

          所有現(xiàn)代瀏覽器都支持 gzip 壓縮,啟用 gzip 壓縮可大幅縮減傳輸資源大小,從而縮短資源下載時(shí)間,減少首次白屏?xí)r間,提升用戶體驗(yàn)。

          gzip 對(duì)基于文本格式文件的壓縮效果最好(如:CSS、JavaScript 和 HTML),在壓縮較大文件時(shí)往往可實(shí)現(xiàn)高達(dá) 70-90% 的壓縮率,對(duì)已經(jīng)壓縮過的資源(如:圖片)進(jìn)行 gzip 壓縮處理,效果很不好。

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

          plugins: [
            new CompressionPlugin({
              // gzip壓縮配置
              test/\.js$|\.html$|\.css/// 匹配文件名
              threshold10240// 對(duì)超過10kb的數(shù)據(jù)進(jìn)行壓縮
              deleteOriginalAssetsfalse// 是否刪除原文件
            }),
          ]

          當(dāng)然,這個(gè)方法還需要后端配置支持。

          DefinePlugin

          我們可以通過 DefinePlugin 可以定義一些全局的變量,我們可以在模塊當(dāng)中直接使用這些變量,無需作任何聲明,DefinePluginwebpack 自帶的插件。

          plugins: [
            new webpack.DefinePlugin({
              DESCRIPTION'This Is The Test Text.',
            }),
          ]

          // 直接引用
          console.log(DESCRIPTION)

          ProvidePlugin

          自動(dòng)加載模塊。任何時(shí)候,當(dāng) identifier 被當(dāng)作未賦值的變量時(shí), module 就會(huì)自動(dòng)被加載,并且 identifier 會(huì)被這個(gè) module 輸出的內(nèi)容所賦值。這是 webpack 自帶的插件。

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

          DLLPlugin

          這是在一個(gè)額外的獨(dú)立的 webpack 設(shè)置中創(chuàng)建一個(gè)只有 dll 的 bundle(dll-only-bundle)。這個(gè)插件會(huì)生成一個(gè)名為 manifest.json 的文件,這個(gè)文件是用來讓 DLLReferencePlugin 映射到相關(guān)的依賴上去的。

          「使用步驟如下」

          1、在 build 下創(chuàng)建 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包會(huì)比較大。
              new webpack.optimize.UglifyJsPlugin({
                compress: {
                  warningsfalse,
                },
              }),
            ],
          }

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

          new webpack.DllReferencePlugin({
            manifestrequire('../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"
            }

          生產(chǎn)環(huán)境打包的時(shí)候先npm run build:dll命令會(huì)在打包目錄下生成 vendor-manifest.json 文件與 vendor.dll.js 文件。然后npm run build生產(chǎn)其他文件。

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

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

          HappyPack

          HappyPack 能讓 webpack 把任務(wù)分解給多個(gè)子進(jìn)程去并發(fā)的執(zhí)行,子進(jìn)程處理完后再把結(jié)果發(fā)送給主進(jìn)程。要注意的是 HappyPack 對(duì) file-loaderurl-loader 支持的不友好,所以不建議對(duì)該 loader 使用。

          1、HappyPack 插件安裝

          npm i -D happypack

          2、webpack.base.conf.js 文件對(duì) module.rules 進(jìn)行配置

          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、在生產(chǎn)環(huán)境 webpack.prod.conf.js 文件進(jìn)行配置

          const HappyPack = require('happypack')
          // 構(gòu)造出共享進(jìn)程池,在進(jìn)程池中包含5個(gè)子進(jìn)程
          const HappyPackThreadPool = HappyPack.ThreadPool({ size5 })
          plugins: [
            new HappyPack({
              // 用唯一的標(biāo)識(shí)符id,來代表當(dāng)前的HappyPack是用來處理一類特定的文件
              id'babel',
              // 如何處理.js文件,用法和Loader配置中一樣
              loaders: ['babel-loader?cacheDirectory'],
              threadPool: HappyPackThreadPool,
            }),
            new HappyPack({
              id'vue'// 用唯一的標(biāo)識(shí)符id,來代表當(dāng)前的HappyPack是用來處理一類特定的文件
              loaders: [
                {
                  loader'vue-loader',
                  options: vueLoaderConfig,
                },
              ],
              threadPool: HappyPackThreadPool,
            }),
          ]

          「注意,當(dāng)項(xiàng)目較小時(shí),多線程打包反而會(huì)使打包速度變慢。」

          copy-webpack-plugin

          我們?cè)?public/index.html 中引入了靜態(tài)資源,但是打包的時(shí)候 webpack 并不會(huì)幫我們拷貝到 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'),
                    flattentrue,
                  },
                ],
              }),
            ],
          }

          IgnorePlugin

          這是 webpack 內(nèi)置插件,它的作用是:忽略第三方包指定目錄,讓這些指定目錄不要被打包進(jìn)去。

          比如我們要使用 moment 這個(gè)第三方依賴庫(kù),該庫(kù)主要是對(duì)時(shí)間進(jìn)行格式化,并且支持多個(gè)國(guó)家語言。雖然我設(shè)置了語言為中文,但是在打包的時(shí)候,是會(huì)將所有語言都打包進(jìn)去的。這樣就導(dǎo)致包很大,打包速度又慢。對(duì)此,我們可以用 IgnorePlugin 使得指定目錄被忽略,從而使得打包變快,文件變小。

          const Webpack = require('webpack')
          plugins: [
            //moment這個(gè)庫(kù)中,如果引用了./locale/目錄的內(nèi)容,就忽略掉,不會(huì)打包進(jìn)去
            new Webpack.IgnorePlugin(/\.\/locale/, /moment/),
          ]

          我們雖然按照上面的方法忽略了包含’./locale/'該字段路徑的文件目錄,但是也使得我們使用的時(shí)候不能顯示中文語言了,所以這個(gè)時(shí)候可以手動(dòng)引入中文語言的目錄。

          import moment from 'moment'

          //手動(dòng)引入所需要的語言包
          import 'moment/locale/zh-cn'

          moment.locale('zh-cn')

          let r = moment().endOf('day').fromNow()
          console.log(r)

          前端學(xué)習(xí)筆記?

          ?

          最近花了點(diǎn)時(shí)間把筆記整理到語雀上了,方便同學(xué)們閱讀:公眾號(hào)回復(fù)筆記或者簡(jiǎn)歷

          ?


          轉(zhuǎn)載自:https://juejin.cn/post/6844904193589772301

          1. JavaScript 重溫系列(22篇全)
          2. ECMAScript 重溫系列(10篇全)
          3. JavaScript設(shè)計(jì)模式 重溫系列(9篇全)
          4. 正則 / 框架 / 算法等 重溫系列(16篇全)
          5. Webpack4 入門(上)|| Webpack4 入門(下)
          6. MobX 入門(上) ||  MobX 入門(下)
          7. 80+篇原創(chuàng)系列匯總

          回復(fù)“加群”與大佬們一起交流學(xué)習(xí)~

          點(diǎn)擊“閱讀原文”查看 100+ 篇原創(chuàng)文章

          瀏覽 61
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  尹人在线大香蕉 | 免费黄的在线观看中文字幕视频 | 高清毛片AAAAAAAAA郊外 | 国产一区二区在线导航 | 成人免费视频 国产免费 |