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を動的に導入し,実行する.
    __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];
                 }
             }
    }     
    ....    

    以上の機能を実現するには、次のような必要があります.
  • parseモジュール:切断ポイントを位置決めし、非同期ロードファイルを組み立てるために必要な依存関係.
  • chunksモジュール:各chunkはmoduleモジュールの集合を含み、ファイルツリー内のモジュールの依存関係によって生成される.
  • writeChunksモジュール:chunksに従ってファイルストリームを介してファイルに書き込まれます.

  • require('d');
    
    function a() {
        require.ensure(['./a'], function () {
            require('c');
        });
    }
    
    require.ensure(['./b'], function () {
        require('./m');
    });
    
    require('./e');
    

    インプリメンテーション
    parseモジュール
    実現構想:
  • は、再帰的であり、ファイルツリーの特徴によってrequire.ensure
  • に位置決めされる.
  • argumentsの1番目のパラメータの配列、2番目のパラメータの関数内をrequireを再帰的に検索し、配列asyncs内に格納し、
  • に再帰する
    データ構造は次のとおりです.
    {
        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が含まれています.
    実現構想:
  • 入口mainPathを介してmodulesの入口mainModule
  • を見つける
  • mainModuleのrequiresを巡回し、値を本chunkのmodulesに戻し、asyncsを巡回し、chunkを順次新規作成し、親chunkを関連付け、以上の2つを順次巡回する.
  • が最終的に生成された後、各非ルートノードのchunkを遍歴し、依存するmodulesを比較親ノードのchunkを遍歴する.
    データ構造は次のとおりです.
    { '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モジュール
    実現構想:
  • は、導入されたテンプレートを区別するために、複数のchunkがあるか否かを判断する.chunksの個数が1を超える場合、エントリchunkはwebpackJsonp,を含むロードを含む.webpack_require__.eなどjsonp関数をサポートするテンプレートは、超えなければロードが簡単なものは__のみを含むwebpack_require__のテンプレート
  • は入口chunkを区別し、入口/非入口chunkは異なるヘッダをロードする.
  • webpackJsonpのパラメータは、moduleIdをkeyとするオブジェクトの配列の2つです.配列の場合は[,,modlue]などで順序
  • を保証する必要がある.
    次のようになります.
    コード実装
    本人の簡易版webpack実現simple-webpack
    (完)