webpack核心概念之入口設定(entry)

2022-08-09 22:00:20
在一切流程的最開始,我們需要指定一個或多個入口(entry),也就是告訴Webpack具體從原始碼目錄下的哪個檔案開始打包。下面本篇文章就來帶大家深入瞭解一下webpack核心概念中的入口設定(entry),希望對大家有所幫助!

如果把工程中各個模組的依賴關係當作一棵樹,那麼入口(entry)就是這棵依賴樹的根

ff76ccfbc2839d8803123ecef15ddaf.png

這些存在依賴關係的模組會在打包時被封裝為一個chunk。那chunk是什麼呢?

chunk字面的意思是程式碼塊,在Webpack中可以理解成被抽象和包裝過後的一些模組。它就像一個裝著很多檔案的檔案袋,裡面的檔案就是各個模組,Webpack在外面加了一層包裹,從而形成了chunk:

001649b831e29eb431f6e8af358d939.png

根據具體設定不同,一個工程打包時可能會產生一個或多個chunk。

工程中可以定義多個入口,每一個入口都會產生一個結果資源

比如我們工程中有兩個入口src/index.jssrc/lib.js,在一般情形下會打包生成dist/index.jsdist/lib.js

d2ab1f6aac20cf96356a0558583785d.png

在一些特殊情況下,一個入口也可能產生多個chunk並最終生成多個bundle

入口(entry)


引數:Entry

  • entry 是設定模組的入口,可抽象成輸入,Webpack 執行構建的第一步將從入口開始搜尋及遞迴解析出所有入口依賴的模組
  • entry 設定是必填的,若不填則將導致 Webpack 報錯退出
module.exports = {
	entry:'./src/index.js', //表示入口檔案,即從index.js進入我們的專案
};

①Entry 型別

型別例子含義
string‘./app/entry’入口模組的檔案路徑,可以是相對路徑
array[’./app/entry1’, ‘./app/entry2’]入口模組的檔案路徑,可以是相對路徑
object{ a: ‘./app/entry-a’, b: [’./app/entry-b1’, ‘./app/entry-b2’]}設定多個入口,每個入口生成一個 Chunk

如果是 array 型別,則搭配 output.library 設定項使用時,只有陣列裡的最後一個入口檔案的模組會被匯出

②Chunk 名稱

Webpack 會為每個生成的 Chunk 取一個名稱,Chunk 的名稱和 Entry 的設定有關:

  • 如果 entry 是一個 string 或 array ,就只會生成一個 Chunk,這時 Chunk 的名稱是 main ;
  • 如果 entry 是一個 object ,就可能會出現多個 Chunk,這時 Chunk 的名稱是 object 鍵值對裡鍵的名稱

③Entry 設定動態

假如專案裡有多個頁面需要為每個頁面的入口設定一個 Entry ,但這些頁面的數量可能會不斷增長,則這時 Entry 的設定會受到到其他因素的影響導致不能寫成靜態的值。其解決方法是把 Entry 設定成一個函數去動態返回上面所說的設定,程式碼如下:

// 同步函數
entry: () => {
  return {
    a:'./pages/a',
    b:'./pages/b',
  }
};
// 非同步函數
entry: () => {
  return new Promise((resolve)=>{
    resolve({
       a:'./pages/a',
       b:'./pages/b',
    });
  });
};

引數:context

Webpack 在尋找相對路徑的檔案時會以 context 為根目錄,context 預設為執行啟動 Webpack 時所在的當前工作目錄。 如果想改變 context 的預設設定,則可以在組態檔裡這樣設定它:

module.exports = {
	context: path.resolve(__dirname, 'app')
}

注意, context 必須是一個絕對路徑的字串。 除此之外,還可以通過在啟動 Webpack 時帶上引數 webpack --context 來設定 context

單個入口檔案設定


用法:entry:string|Array<string>

1、簡寫語法

webpack.config.js

//由於是單個,所以可以簡寫成:
module.exports = {
  entry: './main.js'
};

上面的入口設定寫法其實是下面的簡寫

module.exports = {
  entry: {
    main: './main.js'
  }
};

2、陣列語法

module.exports = {
  entry: {
    main:['./main.js','./main2.js']
  }
};

傳入一個陣列的作用是將多個資源預先合併,在打包時Webpack會將陣列中的最後一個元素作為實際的入口路徑

在使用字串或陣列定義單入口時,並沒有辦法更改chunk name,只能為預設的「main」。

多個入口檔案設定


用法:entry: {[entryChunkName: string]: string|Array}

物件語法

module.exports = {
  entry: {
    app: './src/app.js',
    vendors: './src/vendors.js'
  }
};

這會比較繁瑣。然而這是應用程式中定義入口的最可延伸的方式。

「可延伸的 webpack 設定」:可重用並且可以與其他設定組合使用。這是一種流行的技術,用於將關注點從環境(environment)、構建目標(build target)、執行時(runtime)中分離。然後使用專門的工具(如 webpack-merge)將它們合併。

應用場景


1、單頁應用

無論是框架、庫,還是各個頁面的模組,都由app.js單一的入口進行參照。這樣做的好處是只會產生一個JS檔案,依賴關係清晰

module.exports = {
  entry: './src/app.js'
};

這種做法也有弊端,即所有模組都打包到一起,當應用的規模上升到一定程度之後會導致產生的資源體積過大,降低使用者的頁面渲染速度

在Webpack預設設定中,當一個bundle大於250kB時(壓縮前)會認為這個bundle已經過大了,在打包時會發生警告,如圖:

7cd4894c640a51e80385a65ac753472.png

2、分離第三方庫(vendor)

為解決上方的問題,可以提取第三方庫(vender)

vendor的意思是「供應商」,在Webpack中vendor一般指的是工程所使用的庫、框架等第三方模組集中打包而產生的bundle

module.exports = {
  entry: {
    app: './src/app.js',
    vendors: ['react','react-dom','react-router'],
  }
};

基於但也應用的例子,我們新增了一個新的chunk name為vendor的入口,並通過陣列的形式把工程所依賴的第三方模組放了進去

我們並沒有為vendor設定入口路徑,Webpack要如何打包呢?

這時我們可以使用CommonsChunkPlugin(在Webpack 4之後CommonsChunkPlugin已被廢棄,可以採用optimization.splitChunks)將app與vendor這兩個chunk中的公共模組提取出來

通過這樣的設定,app.js產生的bundle將只包含業務模組,其依賴的第三方模組將會被抽取出來生成一個新的bundle,這也就達到了我們提取vendor的目標

由於vendor僅僅包含第三方模組,這部分不會經常變動。因此可以有效地利用使用者端快取,在使用者後續請求頁面時會加快整體的渲染速度。

CommonsChunkPlugin主要是用來提取第三方庫和公共模組,避免首屏載入的bundle檔案或者按需載入的bundle檔案體積過大,從而導致載入時間過長。

3、多頁應用

對於多頁應用的場景,為了儘可能減小資源的體積,我們希望每個頁面都只載入各自必要的邏輯,而不是將所有頁面打包到同一個bundle中。因此每個頁面都需要有一個獨立的bundle,這種情形我們使用多入口來實現。請看下面的例子:

module.exports = {
  entry: {
    pageOne: './src/pageOne/index.js',
    pageTwo: './src/pageTwo/index.js',
    pageThree: './src/pageThree/index.js'
  }
};

上面的設定告訴webpack 需要 3 個獨立分離的依賴圖,此時入口與頁面是一一對應的,這樣每個HTML只要引入各自的JS就可以載入其所需要的模組

更多程式設計相關知識,請存取:!!

以上就是webpack核心概念之入口設定(entry)的詳細內容,更多請關注TW511.COM其它相關文章!