簡體   English   中英

Webpack 2 - 代碼拆分頂級依賴項

[英]Webpack 2 - Code splitting top-level dependencies

最終編輯

tl; dr決議這是不可能的。 雖然下面的最佳答案確實有一些很好的信息。


contacts.js考慮下面的代碼。 這是一個動態加載的模塊,在代碼中的其他地方使用System.import按需加載。

如果SharedUtil1也被用於在其中也動態加載與其它模塊System.import ,我將如何去了解有SharedUtility1 所有這些模塊的排除 ,只有按需加載第一次它的需要?

SharedUtil1頂級System.import將無法工作,因為我的導出依賴於它:導出只能放在模塊代碼的頂層,而不能放在任何類型的回調中。

Webpack可以實現嗎? 我的版本是2.0.7測試版。

import SharedUtil1 from '../../SharedUtilities/SharedUtility1';

class Contacts{
    constructor(data){
        this.data = data;
        this.sharedUtil1 = new SharedUtil1();
    }
}

export default Contacts;

更新1

我認為捆綁加載器是我想要的,但是沒有,它將你導入的模塊轉換為一個不同的函數,一旦它完成異步加載,你就可以通過回調來訪問實際的模塊。 這意味着你不能透明地使模塊X異步加載而不對代碼進行重大更改,更不用說你回到最初描述的問題,如果你的頂級模塊依賴於現在的異步加載依賴,沒有辦法導出它,因為導出必須在頂層。

Webpack中是否有辦法表示依賴加載依賴關系X(如果需要),並且有任何導入模塊導入它以透明地等待導入過程? 我認為這個用例對於任何遠程大型應用程序都是必不可少的 ,所以我不得不認為我只是遺漏了一些東西。

更新2

根據彼得的回答,我試圖讓重復數據刪除工作,因為commonChunk插件與端點之間共享代碼有關,正如他所提到的,並且由於require.ensure將加載的代碼放入回調中,從而阻止您從ES6 export任何代碼取決於它。

就重復數據刪除而言, contacts.jstasks.js都像這樣加載相同的sharedUtil

import SharedUtil1 from '../../sharedUtilities/sharedUtility1';

我試過運行webpack

webpack --optimize-dedupe

並且還通過添加

plugins: [
    new webpack.optimize.DedupePlugin()
]

到webpack.config。 在這兩種情況下,雖然sharedUtil代碼仍然放在聯系人和任務包中。

閱讀完博客文章后,我終於明白了你的意圖。 我對“頂級依賴”這個詞感到有些困惑。

您有兩個模塊( async-aasync-b ),它們可以從任何地方(這里是模塊main )按需加載,並且都有共享模塊的引用( shared )。

- - -> on-demand-loading (i. e. System.import)
---> sync loading (i. e. import)

main - - -> async-a ---> shared
main - - -> async-b ---> shared

默認情況下,webpack會創建一個這樣的塊樹:

---> chunk uses other chunk (child-parent-relationship)

entry chunk [main] ---> on-demand chunk 1 [async-a, shared]
entry chunk [main] ---> on-demand chunk 2 [async-b, shared]

shared < async-a/b或同一用戶使用async-aasync-b的概率很低時,這很好。 這是默認值,因為它是最簡單的行為,可能是您所期望的:一個System.import =>一個塊。 在我看來,這也是最常見的情況。

但是如果shared > = async-a/b並且用戶加載async-aasync-b的概率很高,則有一個更有效的分塊選項:(有點難以可視化):

entry chunk [main] ---> on-demand chunk 1 [async-a]
entry chunk [main] ---> on-demand chunk 2 [async-b]
entry chunk [main] ---> on-demand chunk 3 [shared]

When main requests async-a: chunk 1 and 3 is loaded in parallel
When main requests async-b: chunk 2 and 3 is loaded in parallel
(chunks are only loaded if not already loaded)

這不是默認行為,但有一個插件可以將其歸檔:異步模式下的CommonChunkPlugin 它在一堆塊中找到公共/共享模塊,並創建一個包含共享模塊的新塊。 在異步模式下,它會將新塊與原始(但現在更小)的塊並行加載。

new CommonsChunkPlugin({
    async: true
})

// This does: (pseudo code)
foreach chunk in application.chunks
  var shared = getSharedModules(chunks: chunk.children, options)
  if shared.length > 0
    var commonsChunk = new Chunk(modules: shared, parent: chunk)
    foreach child in chunk.children where child.containsAny(shared)
      child.removeAll(shared)
      foreach dependency in chunk.getAsyncDepenendenciesTo(child)
        dependeny.addChunk(commonsChunk)

請記住,CommonsChunkPlugin有一個minChunks選項來定義模塊何時作為shared線程化(隨意提供一個自定義函數來選擇模塊)。

下面是一個詳細說明設置和輸出的示例: https//github.com/webpack/webpack/tree/master/examples/extra-async-chunk

另一個配置更多: https//github.com/webpack/webpack/tree/master/examples/extra-async-chunk-advanced

如果我已經正確理解了您,那么當不同的代碼塊將其聲明為依賴項時,您希望防止多次加載相同的依賴項。

是的,這是可能的; 如何做到這取決於您的應用程序中的上下文以及它是在ES6還是ES5中。

ECMA腳本5

Webpack 1是在ECMA Script 5中構建的,通常使用CommonJS或RequireJS語法進行模塊導出和導入。 使用此語法時,可以使用以下功能來防止重復的代碼:

  • 重復數據刪除通過創建duplciate函數的副本而不是重新定義它們來防止重復文件包含在已編譯的代碼中。
  • 命名的Chunks允許將塊聲明為依賴項但不立即計算; 所有出現的相同塊都將使用相同的實例。
  • CommonsChunkPlugin允許在多個入口點共享塊(僅適用於多個頁面網站)。

重復數據刪除

webpack文檔

如果您使用一些具有很酷依賴樹的庫,則可能會出現某些文件相同的情況。 Webpack可以找到這些文件並對其進行重復數據刪除。 這可以防止在包中包含重復的代碼,而是在運行時應用該函數的副本。 它不會影響語義。

重點是我的,而不是來源

如文檔所述,代碼拆分保持不變; 需要sharedUtil1每個模塊sharedUtil1應該將require聲明為正常。 為了防止多次加載相同的依賴項,啟用了webpack設置,該設置使webpack在運行時包含它們之前顯式檢查文件是否有重復。

使用--optimize-dedupe resp啟用此選項。 new webpack.optimize.DedupePlugin()

命名大塊

webpack文檔

require.ensure函數接受另外的第3個參數。 這必須是一個字符串。 如果兩個分割點傳遞相同的字符串,則它們使用相同的塊...如果模塊位於多個子塊中,則require.include可能很有用。 require.include中的require.include將包含模塊,子塊中的模塊實例將消失。

簡而言之,模塊的加載被延遲到編譯后期。 這允許在包含重復定義之前將其刪除。 該文檔提供了示例。

常見的塊插件

webpack文檔

CommonsChunkPlugin可以將多個條目塊中出現的模塊移動到新的條目塊(公共塊)。 運行時也會移動到commons塊。 這意味着舊的條目塊現在是初始塊。

這非常特定於在多個頁面之間共享塊,這在其他情況下是不相關的。

ECMA腳本6

對高級模塊導入功能的支持是......正在進行的工作。 要了解事物的位置,請參閱以下鏈接:

以下是ES6模塊和webpack的一個很好的總結: 帶有TypeScript和Webpack的ES6模塊

以上信息很可能會過時。

建議

為了你自己的理智,我建議:

如果優化很重要 :當Webpack 2穩定並發布時,恢復為CommonJS / RequireJS語法並升級到ECMA Script 6。

如果ECMA Script 6語法很重要 :使用標准ECMA Script 6導入導出格式並在可用時添加優化功能。

嘗試在sill不穩定的webpack中使用高級模塊加載功能有太多的變化2.等待事情穩定下來,一些非常好的插件在嘗試之前變得可用。

根據Webpack創建者,這是不可能的。 干凈利落。 有關Webpack和ES6的大量其他有用信息,請參閱Peter的答案。

粘貼的圖像是誤解的結果。 請參閱上面相同的用戶答案。

在此輸入圖像描述

System.import已在Webpack中棄用。 Webpack現在支持import() ,這需要使用polyfill來實現承諾。

代碼拆分 - 使用import()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM