亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

80行代碼寫(xiě)一個(gè)Webpack插件并發(fā)布到npm

 更新時(shí)間:2021年05月24日 11:30:05   作者:Yuan-yiming  
最近在學(xué)習(xí) Webpack 相關(guān)的原理,本文用80行代碼寫(xiě)一個(gè)Webpack插件并發(fā)布到npm,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

1. 前言

最近在學(xué)習(xí) Webpack 相關(guān)的原理,以前只知道 Webpack 的配置方法,但并不知道其內(nèi)部流程,經(jīng)過(guò)一輪的學(xué)習(xí),感覺(jué)獲益良多,為了鞏固學(xué)習(xí)的內(nèi)容,我決定嘗試自己動(dòng)手寫(xiě)一個(gè)插件。

這個(gè)插件實(shí)現(xiàn)的功能比較簡(jiǎn)單:

  • 默認(rèn)清除 js 代碼中的 console.log 的打印輸出;
  • 可通過(guò)傳入配置,實(shí)現(xiàn)移除 console 的其它方法,如 console.warnconsole.error 等;

2. Webpack 的構(gòu)建流程以及 plugin 的原理

2.1 Webpack 構(gòu)建流程

Webpack 的主要構(gòu)建流程,可以分為三個(gè)階段:

  • 初始化階段:?jiǎn)?dòng)構(gòu)建,讀取與合并配置參數(shù),加載 Plugin,實(shí)例化 Compiler
  • 編譯階段:從 Entry 發(fā)出,針對(duì)每個(gè) Module 串行調(diào)用對(duì)應(yīng)的 Loader 去翻譯文件內(nèi)容,再找到該 Module 依賴(lài)的 Module,遞歸地進(jìn)行編譯處理。
  • 生成階段:對(duì)編譯后的 Module 組合成 Chunk,把 Chunk 轉(zhuǎn)換成文件,輸出到文件系統(tǒng)。

如果 Webpack 打包生產(chǎn)環(huán)境文件時(shí),只會(huì)執(zhí)行一次構(gòu)建,以上階段會(huì)按順序執(zhí)行一遍。但是在開(kāi)啟監(jiān)聽(tīng)模式時(shí),如開(kāi)發(fā)環(huán)境,Webpack 會(huì)持續(xù)的進(jìn)行構(gòu)建。

2.2 plugin 原理

Webpack 插件通常是一個(gè)帶有 apply 函數(shù)的類(lèi),其中 constructor 可以接收傳入的配置項(xiàng)。插件被安裝時(shí),apply 函數(shù)會(huì)被調(diào)用一次,并接收 Compiler 對(duì)象,然后我們可以在 Compiler 對(duì)象上監(jiān)聽(tīng)不同的事件鉤子,從而進(jìn)行插件功能的開(kāi)發(fā)。

// 定義一個(gè)插件
class MyPlugin {
  // 構(gòu)造函數(shù),接收插件的配置項(xiàng) options 
  constructor(options) {
    // 獲取配置項(xiàng),初始化插件
  }

  // 插件安裝時(shí)會(huì)調(diào)用 apply,并傳入 compiler
  apply(compiler) {
    // 獲取 comolier 獨(dú)享,可以監(jiān)聽(tīng)事件鉤子
    // 功能開(kāi)發(fā) ... 
  }
}

2.3 compiler 和 compilation 對(duì)象

在開(kāi)發(fā) Plugin 過(guò)程中最常用的兩個(gè)對(duì)象就是 CompilerCompilation

  • Compiler 對(duì)象在 Webpack 啟動(dòng)時(shí)被實(shí)例化,該對(duì)象包含了 Webpack 環(huán)境所有的配置信息,包括 options、loadersplugins 等。在整個(gè) Webpack 構(gòu)建過(guò)程中,Compiler 對(duì)象是全局唯一的, 它提供了很多事件鉤子回調(diào)供插件使用。
  • Compilation 對(duì)象包含了當(dāng)前的模塊資源、編譯生成資源、變化的文件等。Compilation 對(duì)象在 Webpack 構(gòu)建過(guò)程中并不是唯一的,如果在開(kāi)發(fā)模式下 Webpack 開(kāi)啟了文件檢測(cè)功能,每當(dāng)文件變化時(shí),Webpack 會(huì)重新構(gòu)建,此時(shí)會(huì)生成一個(gè)新的 Compilation 對(duì)象。Compilation 對(duì)象也提供了很多事件回調(diào)供插件做擴(kuò)展。

3. 插件開(kāi)發(fā)

3.1 項(xiàng)目目錄

該插件實(shí)現(xiàn)的功能比較簡(jiǎn)單,文件目錄也不復(fù)雜。首先新建一個(gè)空文件夾 remove-console-Webpack-plugin,并在該文件夾目錄下運(yùn)行 npm init,根據(jù)提示來(lái)填寫(xiě) package.json 相關(guān)信息。然后再新建一個(gè) src 文件夾,插件主要代碼就放在 src/index.js 里面。如果你需要把項(xiàng)目放到 github 上,最好也添加一下 .gitignore、README.md 等文件。

// remove-console-Webpack-plugin
├─src
│  └─index.js  
├─.gitignore
├─package.json
└─README.md 

3.2 插件代碼

插件代碼邏輯也并不復(fù)雜,主要有幾點(diǎn):

  • 在構(gòu)造函數(shù)中接收配置參數(shù),并對(duì)參數(shù)進(jìn)行合并,得到需要清除的 console 函數(shù), 存放在 removed 數(shù)組中;
  • apply 函數(shù)中監(jiān)聽(tīng) compiler.hook.compilation 鉤子,該鉤子觸發(fā)后,拿到 compilation 后進(jìn)一步監(jiān)聽(tīng)它的鉤子,這里 Webpack4Webpack5 的鉤子不一樣,需要做兼容;
  • 定義 assetsHandler 方法來(lái)處理 js 文件,利用正則表達(dá)式清除 removed 中包括的 console 函數(shù);
class RemoveConsoleWebpackPlugin {
  // 構(gòu)造函數(shù)接受配置參數(shù)
  constructor(options) {
    let include = options && options.include;
    let removed = ['log']; // 默認(rèn)清除的方法

    if (include) {
      if (!Array.isArray(include)) {
        console.error('options.include must be an Array.');
      } else if (include.includes('*')) {
        // 傳入 * 表示清除所有 console 的方法
        removed = Object.keys(console).filter(fn => {
          return typeof console[fn] === 'function';
        })
      } else {
        removed = include; // 根據(jù)傳入配置覆蓋
      }
    }

    this.removed = removed;
  }

  // Webpack 會(huì)調(diào)用插件實(shí)例的 apply 方法,并傳入compiler 對(duì)象
  apply(compiler) {
    // js 資源代碼處理函數(shù)
    let assetsHandler = (assets, compilation) => {
      let removedStr = this.removed.reduce((a, b) => (a + '|' + b));

      let reDict = {
        1: [RegExp(`\\.console\\.(${removedStr})\\(\\)`, 'g'), ''],
        2: [RegExp(`\\.console\\.(${removedStr})\\(`, 'g'), ';('],
        3: [RegExp(`console\\.(${removedStr})\\(\\)`, 'g'), ''],
        4: [RegExp(`console\\.(${removedStr})\\(`, 'g'), '(']
      }

      Object.entries(assets).forEach(([filename, source]) => {
        // 匹配js文件
        if (/\.js$/.test(filename)) {
          // 處理前文件內(nèi)容
          let outputContent = source.source();

          Object.keys(reDict).forEach(i => {
            let [re, s] = reDict[i];
            outputContent = outputContent.replace(re, s);
          })

          compilation.assets[filename] = {
            // 返回文件內(nèi)容
            source: () => {
              return outputContent
            },
            // 返回文件大小
            size: () => {
              return Buffer.byteLength(outputContent, 'utf8')
            }
          }
        }
      })
    }

    /**
     * 通過(guò) compiler.hooks.compilation.tap 監(jiān)聽(tīng)事件
     * 在回調(diào)方法中獲取到 compilation 對(duì)象
     */
    compiler.hooks.compilation.tap('RemoveConsoleWebpackPlugin',
      compilation => {
        // Webpack 5
        if (compilation.hooks.processAssets) {
          compilation.hooks.processAssets.tap(
            { name: 'RemoveConsoleWebpackPlugin' },
            assets => assetsHandler(assets, compilation)
          );
        } else if (compilation.hooks.optimizeAssets) {
          // Webpack 4
          compilation.hooks.optimizeAssets.tap(
            'RemoveConsoleWebpackPlugin', 
            assets => assetsHandler(assets, compilation)
          );
        }
      })
  }
}

// export Plugin
module.exports = RemoveConsoleWebpackPlugin;

4. 發(fā)布到npm

希望別人能使用到你的插件,就需要把插件發(fā)布到 npm 上,發(fā)布的主要流程:

首先在 npm 官網(wǎng)上注冊(cè)賬號(hào),然后打開(kāi)命令行工具,在任意目錄下輸入 npm login 并按提示登錄;

登錄后可用 npm whoami 查看是否登錄成功;

發(fā)布前檢查一下根目錄下的 package.json 文件信息是否填寫(xiě)正確,主要字段:

  • name:決定用戶(hù)下載你的插件時(shí)用的名稱(chēng),不可與 npm 上已有的第三方包重名,否則無(wú)法發(fā)布;
  • main:插件主文件入口,Webpack 引入插件時(shí),就從該目錄導(dǎo)入;
  • version:每次更新發(fā)布時(shí),需要與上一版本的版本號(hào)不一樣,否則上傳不成功;
  • repository:如果你的插件代碼放在 githubgitee 等網(wǎng)站,可以填一下;
  • private:不能設(shè)置為 true,否則無(wú)法發(fā)布;

一切準(zhǔn)備就緒后,切換到插件所在的目錄下,運(yùn)行 npm publish 即可上傳插件;

上傳成功后,到 npm 官網(wǎng)上搜索,看看是否能搜到插件;

5. 結(jié)尾

到此這篇關(guān)于80行代碼寫(xiě)一個(gè)Webpack插件并發(fā)布到npm的文章就介紹到這了,更多相關(guān)Webpack插件發(fā)布到npm內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 滑動(dòng)門(mén),簡(jiǎn)潔,新手上路制作篇 (小鴿子系列)

    滑動(dòng)門(mén),簡(jiǎn)潔,新手上路制作篇 (小鴿子系列)

    滑動(dòng)門(mén),簡(jiǎn)潔,新手上路制作篇 (小鴿子系列)...
    2007-04-04
  • js 操作select與option(示例講解)

    js 操作select與option(示例講解)

    本篇文章主要是對(duì)js 操作select與option的示例進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助
    2013-12-12
  • javascript控制在光標(biāo)位置插入文字適合表情的插入

    javascript控制在光標(biāo)位置插入文字適合表情的插入

    使用javascript控制在光標(biāo)位置插入文字,在實(shí)現(xiàn)表情的插入時(shí)會(huì)用到的,需要的朋友可以參考下
    2014-06-06
  • 淺談js的異步執(zhí)行

    淺談js的異步執(zhí)行

    下面小編就為大家?guī)?lái)一篇淺談js的異步執(zhí)行。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-10-10
  • JavaScript中的閉包介紹

    JavaScript中的閉包介紹

    這篇文章主要介紹了JavaScript中的閉包介紹,本文講解了Javacript 閉包、Javscript 閉包與this、Javscript 閉包與讀寫(xiě)變量等內(nèi)容,需要的朋友可以參考下
    2015-03-03
  • javascript禁止超鏈接跳轉(zhuǎn)的方法

    javascript禁止超鏈接跳轉(zhuǎn)的方法

    這篇文章主要介紹了javascript禁止超鏈接跳轉(zhuǎn)的方法,結(jié)合實(shí)例分析了JavaScript事件機(jī)制與鼠標(biāo)事件的響應(yīng)操作技巧,需要的朋友可以參考下
    2016-02-02
  • 微信小程序中post方法與get方法的封裝

    微信小程序中post方法與get方法的封裝

    這篇文章主要介紹了微信小程序中post方法與get方法的封裝的相關(guān)資料,希望通過(guò)本文能幫助到大家,讓大家掌握如何封裝,需要的朋友可以參考下
    2017-09-09
  • JS控制偽元素的方法匯總

    JS控制偽元素的方法匯總

    本文給大家介紹js控制偽元素的方法匯總,本文涉及到獲取偽元素屬性值的方法,本文介紹的非常詳細(xì),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧
    2016-04-04
  • 詳解在HTTPS 項(xiàng)目中使用百度地圖 API

    詳解在HTTPS 項(xiàng)目中使用百度地圖 API

    這篇文章主要介紹了在HTTPS 項(xiàng)目中使用百度地圖 API,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 一個(gè)php+js實(shí)時(shí)顯示時(shí)間問(wèn)題

    一個(gè)php+js實(shí)時(shí)顯示時(shí)間問(wèn)題

    本文給大家分享的是解決的php+js實(shí)時(shí)顯示時(shí)間問(wèn)題,主要是自己當(dāng)時(shí)的理解有問(wèn)題,也許大家有和我一樣的情況,這里分享給大家
    2015-10-10

最新評(píng)論