前端工程化之webpack核心功能

前言

在前端工程化對世界中,掌握webpack配置基本是咱們每一個前端工程師須要掌握的,在vue/react/angular發展初期,他們但腳手架還不夠完善,許多但配置都須要開發者本身來,但隨着腳手架工具但完善,項目但總體架構已無需開發人員考慮太多,因此如今許多新入行的前端開發者會以爲前端開發毫無難度,這種也沒錯,若是你僅僅知足於完成業務功能開發,那我自無話可說。但做爲一個有追求的前端,確定不能僅僅知足於霧裏看花,知其然,知其因此然。本文就來詳細分析下webpack的工做流程,以及工做原理。css

webpack工做流程

  • webpack基本流程簡單明瞭,初始化 => 編譯 => 輸出。但在開發階段咱們須要 熱更新,那這樣就成了一個循環,初始化 => 編譯 => 輸出(每次修改文件) => 編譯 => 輸出 .....。而這三個流程中會有webpack會有不少工做要作,本小節分析下這三個過程當中webpack的實際工做機制。html

  • Webpack功能流程實現的核心模塊tapable,在webpack工做流程中,Compiler 和負責建立 bundles 的 Compilation 都是tapable構造函數的實例, 它的工做流程就是將各個插件串聯起來,而實現這一切的核心就是 tapable。前端

注:本節主要來了解webpack工做流程中相當重要的兩個功能,loader功能和plugin功能。vue

loader的實現

做用:Loader 就像是一個翻譯員,能把源文件通過轉化後輸出新的結果,而且一個文件還能夠鏈式的通過多個翻譯員翻譯。node

目的:將源文件轉換瀏覽器可以識別的文件。 //webpack中loader配置react

module: {
    rules: [
      {
      //匹配文件到正則
        test: /\.scss$/,
        //用於處理到插件
        use: [
          'style-loader',
          {
            loader:'css-loader',
            // 給 css-loader 傳入配置項
            options:{
              minimize:true, 
            }
          },
          'sass-loader'],
      },
    ]
    //use的數組順序表示了loader的執行順序,越在數組後則越先執行
  }
複製代碼
  • 特色1:單一職責性,一個loader只能完成一種轉換。
  • 特色2:按鏈式順序執行,上一個處理後的結果會傳遞給下一個。
  • 一些loader內部經常使用的上下文(具體解釋見):this.context this.callback this.async this.cacheable this.loaders this.target this.sourceMap
  • 自定義loader步驟:定義loader函數 =》獲取配置文件參數 =》導出=》導入webpack配置文件。
  • 引用:webpack中module使用時能夠上傳到npm包經過loader直接使用。能夠經過resolveLoader找到loader文件路徑來引用

//自定義loader demowebpack

//將輸入的文件處理後再返回
const loaderUtils = require('loader-utils');

module.exports = function(source){
    ....
    //webpack 的工具loader-utils
    let options = loaderUtils.getOptions(this)
    //關閉緩存功能
    this.cacheable(false);
    return source
}

複製代碼

分析結論: 當webpack肯定好入口文件後,此時webpack調用全部的loader對模塊進行編譯。web

plugin實現

Plugin 機制讓webpack的執行其更加靈活,能夠適應各類應用場景。 在 Webpack 運行過程是一個事件流,在不一樣的生命週期會觸發相應的事件,而Plugin 能夠監聽這些事件,在合適的時機經過 Webpack 提供的 API 改變輸出結果。npm

做用:plugin能夠監聽webpack生命週期的相關事件,在合適的時機經過webpack提供的API改變輸出結果,這也是webpack成爲當今前端構建工具的緣由之一(plugin使webpack不只僅是打包壓縮代碼的工具)。前端工程化

目的:在於解決loader解決不了到事情,例如:自動生成hash的html,在本地開啓的web服務等等

自定義基本plugin:

  • 命名函數
  • apply
  • 綁定webpack鉤子函數
  • 內部實例的特定數據
  • 回調函數
//命名一個獨一無二的函數名
function DemoPlugin(options) {
  // 使用 options 設置插件實例……
}
//定義apply函數
DemoPlugin.prototype.apply = function(compiler) {
//將apply綁定到webpack自身到事件鉤子
  compiler.plugin('run', function(compilation//內部實例的特定數據,callback) {
    console.log('Hello World!');
    //執行完成後的回調函數
    callback()
  });
};

module.exports = DemoPlugin;
複製代碼

webpack中執行流程:

  • webpack啓動後,在讀取配置的過程當中會執行new MyPlugin初始化一個plugin獲取其實 例
  • 在webpack初始化compiler後,能夠經過compiler.plugin(事件名稱,回調函數)監聽到webpack廣播出來的事件
  • 此時能夠經過compiler對象去操做webpack 注:要想深刻的瞭解plugin,那必須去掌握webpack Compiler 和 Compilation的 相關內容

resolve實現

做用:用於幫助找到模塊的絕對路徑。一個模塊能夠做爲另外一個模塊的依賴模塊,而後被後者引用。

目的:爲了方便找到完整的文件路徑信息。

經常使用到到功能:

  • 自動擴展文件名
//可以使用戶在引入模塊時不帶擴展
extensions:['.js','.jsx','.css','.less']
複製代碼
  • 是利用resolve定義路徑別名
//webpack.config.js的resolve模塊定義
alias: {
  demo: path.resolve(__dirname, 'src/demo/'),
}
//爲定義resolve前
import demo from '../../demo/utility';
//定義resolve後
import demo from 'demo/utility';
複製代碼
  • 利用reslove定義modules解析路徑和順序
//定義modules在解析路徑時先從src目錄下開始尋找 而後在到node_modules
modules: [path.resolve(__dirname, "src"), "node_modules"]
複製代碼

總結

寫完這篇文章感受不少webpack核心原理都沒有理解透徹,只是大概明白了webpack到核心功能,以及如何去使用這些功能。後續的文章我以爲應該會從一個個webpack的要點出發去深刻理解他的每個點。在此先給本身定個下篇文章的內容:本身動手實現一個webpack插件功能。文章中若是有所不當之處,請各位批評指針。相互進步是咱們寫文章和看文章的目的,相互交流則是促使咱們更進一步的階梯。

參考文檔:

相關文章
相關標籤/搜索