1. 程式人生 > >webpack程式碼分割-使用require.ensure

webpack程式碼分割-使用require.ensure

1.背景

    webpack是一款很好用的模組打包機,當我們開發單頁應用時,很常見的需求是把一堆模組打包成一個檔案,這時webpack就派上用場了。但是在一些場景下,我們可能有這樣的需求:一方面需要把一系列的檔案打包成一個檔案,另一方面還有一些模組是需要按需載入的(比如一個網站有多個頁面,可以一開始載入主頁,然後根據使用者的操作再請求相應的其他頁面),這時候就需要用到webpack提供的程式碼分割的功能。

2.簡介

    如果我們想要做到按需載入,那麼就需要webpack按需分割。webpack需要做的工作有兩方面:第一是要把各個需要按需載入的模組切片成不同的檔案(每個模組存在一個檔案裡,這個檔案叫做一個切片)而不是打包到一個檔案裡。第二是在我們需要時引入。這樣,相應地,就需要我們做兩方面工作:第一是告訴webpack切片檔案存放的位置。第二就是告訴webpack什麼時候引入切片。下面說明一下我們怎麼進行這兩方面的工作。

3.切片位置配置

    webpack的配置檔案中,有一個module.exports物件,其中有一個屬性output,我們在這個屬性下配置切片放置位置,詳情參見webpack文件

4.何時引入切片檔案

    對於webpack來說,是何時引入切片檔案,對於我們來說,是如何引入模組。我們通過require.ensure來進行模組的非同步引用。語法為:

require.ensure(dependencies: String[], callback: function(require), chunkName: String)。

第一個引數是需要引入的模組所依賴的其他模組的列表,第二個引數是是載入完依賴模組後的回撥函式,第三個引數是切片名字(這個切片的名字是幹什麼用的暫時還沒搞明白)。
舉例如下:
require.ensure(['./a.js'], function(require) {
    require('./b.js');
});

我們是在第二個引數,即載入依賴完成的回撥函式中進行模組的非同步載入的。上述示例程式碼直接就引入了b.js。我們當然也可以在適當的時機引入:
require.ensure(['./a.js'], function(require) {

    setTimeout(function () {

        require('./b.js');

    }, 1000);
});

5.說明

    webpack對於require.ensure是如何執行的呢?它會首先靜態解析require.ensure語句,把其中回撥函式中引入的模組連同它依賴的模組打包成一個切片檔案。這樣,當我們需要引入相應的模組時,就會使用jsonp引入這個切片檔案。一種很常見的做法是在依賴完成回撥函式中返回一個promise的工廠函式,這個promise會resolve我們想要的依賴模組,然後我們就可以在需要引入模組時resolve一下,就可以在promise成功的回撥中進行相應的處理了。

// a.js
window.a = 'a';

// b.js
window.b = 'b';

var test = require.ensure(['./a.js'], function () {
	return function () {
		var promise = new Promise (function (resolve, reject) {
			resolve(require('./b.js'));
		});
	}
}, 'test');

// 開始非同步載入
test()
.then(function (data) {
	console.log(window.a); // 'a'
	console.log(window.b); // 'b'
});