Webpackソース分析の2:code-splitting
4353 ワード
前言
code-splittingはwebpackで最も注目されている特性の一つであり、この特性はコードを異なるbundleファイルに分離する.公式サイトcode-splitを詳しく紹介し、今回の実現は筆者の前回のファイルパッケージの上で開発した.
きのうぶんせき
公式サイトでは3つの方法で実現されていますエントリ開始点:entryオプションを使用してコードを手動で分離します. 繰り返し防止:CommonsChunkPluginを使用してchunkを除去および分離します. 動的インポート:モジュールのインライン関数呼び出しによってコードを分離します.
1本質は複数のエントリのchunkであり,2はcommon.jsをエントリファイルとし,マルチエントリのchunkをカットファイル別に切り出し,jsonpによりロードする.ここで筆者は最も複雑な3の実現を紹介します.
Webpackの切断ファイルの導入の本質はjsonpであり,所定のフォーマットのjsを動的に導入し,実行する.
切断ファイルの注釈は次のとおりです.
一方,エントリファイルのwebpackJsonpCallback関数では,切断されたファイルに含まれるmodulesをmodulesに順次格納する.
以上の機能を実現するには、次のような必要があります. parseモジュール:切断ポイントを位置決めし、非同期ロードファイルを組み立てるために必要な依存関係. chunksモジュール:各chunkはmoduleモジュールの集合を含み、ファイルツリー内のモジュールの依存関係によって生成される. writeChunksモジュール:chunksに従ってファイルストリームを介してファイルに書き込まれます.
例
インプリメンテーション
parseモジュール
実現構想:は、再帰的であり、ファイルツリーの特徴によってrequire.ensure に位置決めされる. argumentsの1番目のパラメータの配列、2番目のパラメータの関数内をrequireを再帰的に検索し、配列asyncs内に格納し、 に再帰する
データ構造は次のとおりです.
chunksモジュール
各依存ファイルのソースコードはmodluesに含まれているため、chunksには特定の各切断ファイルに必要なmoduleのmoduleIdが含まれています.
実現構想:入口mainPathを介してmodulesの入口mainModule を見つける mainModuleのrequiresを巡回し、値を本chunkのmodulesに戻し、asyncsを巡回し、chunkを順次新規作成し、親chunkを関連付け、以上の2つを順次巡回する. が最終的に生成された後、各非ルートノードのchunkを遍歴し、依存するmodulesを比較親ノードのchunkを遍歴する.
データ構造は次のとおりです.
writeChunksモジュール
実現構想: は、導入されたテンプレートを区別するために、複数のchunkがあるか否かを判断する.chunksの個数が1を超える場合、エントリchunkはwebpackJsonp,を含むロードを含む.webpack_require__.eなどjsonp関数をサポートするテンプレートは、超えなければロードが簡単なものは__のみを含むwebpack_require__のテンプレート は入口chunkを区別し、入口/非入口chunkは異なるヘッダをロードする. webpackJsonpのパラメータは、moduleIdをkeyとするオブジェクトの配列の2つです.配列の場合は[,,modlue]などで順序 を保証する必要がある.
次のようになります.
コード実装
本人の簡易版webpack実現simple-webpack
(完)
code-splittingはwebpackで最も注目されている特性の一つであり、この特性はコードを異なるbundleファイルに分離する.公式サイトcode-splitを詳しく紹介し、今回の実現は筆者の前回のファイルパッケージの上で開発した.
きのうぶんせき
公式サイトでは3つの方法で実現されています
1本質は複数のエントリのchunkであり,2はcommon.jsをエントリファイルとし,マルチエントリのchunkをカットファイル別に切り出し,jsonpによりロードする.ここで筆者は最も複雑な3の実現を紹介します.
Webpackの切断ファイルの導入の本質はjsonpであり,所定のフォーマットのjsを動的に導入し,実行する.
__webpack_require__.e = function requireEnsure(chunkId) {
....
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.src = __webpack_require__.p + "" + chunkId + ".bundle.js";
head.appendChild(script);
....
}
切断ファイルの注釈は次のとおりです.
webpackJsonp([1],[function(){},function(){}])
一方,エントリファイルのwebpackJsonpCallback関数では,切断されたファイルに含まれるmodulesをmodulesに順次格納する.
function webpackJsonpCallback(chunkIds, moreModules){
....
for(moduleId in moreModules) {
if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
modules[moduleId] = moreModules[moduleId];
}
}
}
....
以上の機能を実現するには、次のような必要があります.
例
require('d');
function a() {
require.ensure(['./a'], function () {
require('c');
});
}
require.ensure(['./b'], function () {
require('./m');
});
require('./e');
インプリメンテーション
parseモジュール
実現構想:
データ構造は次のとおりです.
{
filename: '/Users/zhujian/Documents/workspace/webpack/simple-webpack/example/main.js',
id: 0,
requires: [{
name: 'd',
range: [8, 11],
id: 1
}],
rangeRequires: [[0, 7]],
asyncs: [{
requires: [{
name: './a',
id: 2
}, {
name: 'c',
range: [88, 91],
id: 3
}],
asyncs: [],
rangeRequires: [80, 87],
ensureRequires: [34, 58]
},
{
requires: [{
name: './b',
id: 4
}, {
name: './m',
range: [156, 161],
id: 5
}],
asyncs: [],
rangeRequires: [148, 155],
ensureRequires: [106, 130]
}],
}
chunksモジュール
各依存ファイルのソースコードはmodluesに含まれているため、chunksには特定の各切断ファイルに必要なmoduleのmoduleIdが含まれています.
実現構想:
データ構造は次のとおりです.
{ '0':
{ id: 0,
modules: { '0': 'include', '1': 'include', '2': 'include' } },
'1':
{ id: 1,
modules:
{ '1': 'in-parent',
'3': 'include',
'4': 'include',
'5': 'include',
'6': 'include' },
parentId: 0 },
'2':
{ id: 2,
modules: { '5': 'include', '6': 'include' },
parentId: 0
}
}
writeChunksモジュール
実現構想:
次のようになります.
コード実装
本人の簡易版webpack実現simple-webpack
(完)