webpackのrequire.com textを深く理解する.


前言
require.co nteeは実はとても実用的なapiです.しかし3~4年が過ぎましたが、まだ多くの人がどうやって使うか分かりません.
このアプリは主に私達のためにどんなことをしますか?それは私たちが欲しいファイルを動的にロードするのに役立ちます.非常に柔軟で強力です.importではできないことができます.今日は皆さんと一緒に分析してみます.webpackのrequire.contextはどうやって実現されたのですか?
準備工作
このアプリを分析する前に、一番簡単なファイルを調べてみます.webpackはどのようにコンパイルされますか?
-- src
    -- index.ts
// index.ts
console.log(123)
コンパイルしたら、webpackは下記のコードにコンパイルされます.
//    https://github.com/MeCKodo/require-context-sourece/blob/master/simple-dist/bundle-only-index.js
 (function(modules) { // webpackBootstrap
     // The module cache
     var installedModules = {};
     // The require function
     function __webpack_require__(moduleId) {
         // Check if module is in cache
         if(installedModules[moduleId]) {
             return installedModules[moduleId].exports;
         }
         // Create a new module (and put it into the cache)
         var module = installedModules[moduleId] = {
             i: moduleId,
             l: false,
             exports: {}
         };
         // Execute the module function
         modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
         // Flag the module as loaded
         module.l = true;
         // Return the exports of the module
         return module.exports;
     }
     // expose the modules object (__webpack_modules__)
     __webpack_require__.m = modules;
     // expose the module cache
     __webpack_require__.c = installedModules;
     // define getter function for harmony exports
     __webpack_require__.d = function(exports, name, getter) {
         if(!__webpack_require__.o(exports, name)) {
             Object.defineProperty(exports, name, {
                 configurable: false,
                 enumerable: true,
                 get: getter
             });
         }
     };
     // define __esModule on exports
     __webpack_require__.r = function(exports) {
         Object.defineProperty(exports, '__esModule', { value: true });
     };
     // getDefaultExport function for compatibility with non-harmony modules
     __webpack_require__.n = function(module) {
         var getter = module && module.__esModule ?
             function getDefault() { return module['default']; } :
             function getModuleExports() { return module; };
         __webpack_require__.d(getter, 'a', getter);
         return getter;
     };
     // Object.prototype.hasOwnProperty.call
     __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
     // __webpack_public_path__
     __webpack_require__.p = "";
     // Load entry module and return exports
     return __webpack_require__(__webpack_require__.s = "./src/index.ts");
 })
 ({
 "./src/index.ts": (function(module, exports) {
      console.log('123');
    })
 });
初めて見ると散らかっていますので、構造を整理するために、本文と関係のないものを取り除いてあげます.実は主要な構造はこのようにします.コードは多くないです.後の理解のために、各ラインをよく見てください.
//      https://github.com/MeCKodo/require-context-sourece/blob/master/simple-dist/webpack-main.js

(function(modules) {
  //            (  )
  var installedModules = {};
  //   (  )    moduleId         
  function __webpack_require__(moduleId) {
    //   cache
    if (installedModules[moduleId]) {
      return installedModules[moduleId].exports;
    }
    // Create a new module (and put it into the cache)       
    var module = (installedModules[moduleId] = {
      i: moduleId,
      l: false,
      exports: {}
    });
    //        (  )      ./src/index.ts      3    
    modules[moduleId].call(
      module.exports,
      module,
      module.exports,
      __webpack_require__
    );
    // Flag the module as loaded       
    module.l = true;
    // Return the exports of the module       
    return module.exports;
  }
  //         
  return __webpack_require__((__webpack_require__.s = './src/index.ts'));
})({
  './src/index.ts': function(module, exports, __webpack_require__) {
    console.log('123');
  }
});
__webpack_require__はモジュール搭載器です.私たちのモジュールはすべて対象として読み込まれます.
modules = {
    './src/index.ts': function(module, exports, __webpack_require__) {
       console.log('123');
    }
}
このような構造をとりあえず と呼びます.
正面の映画
本体構造を理解したら、効果を見にrequire.contextの部分を書くことができます.私たちは先に2つのtsファイルを追加して、私たちのindex.tsを修正して、私たちのダイナミックローディングをテストしやすいです.
--- src
    --- demos
        --- demo1.ts
        --- demo2.ts
    index.ts
// index.ts
//                 
function importAll(contextLoader: __WebpackModuleApi.RequireContext) {
  contextLoader.keys().forEach(id => console.log(contextLoader(id)));
}

const contextLoader = require.context('./demos', true, /\.ts/);
importAll(contextLoader);
コンパイルしたソースコードを見てください.このようなブロックが多いことが分かりました. です.
//         https://github.com/MeCKodo/require-context-sourece/blob/master/simple-dist/contex-sync.js#L82-L113
{
'./src/demos sync recursive \\.ts': function(module, exports, __webpack_require__) {
  var map = {
    './demo1.ts': './src/demos/demo1.ts',
    './demo2.ts': './src/demos/demo2.ts'
  };

  // context    ,               (  ) 
  function webpackContext(req) {
    var id = webpackContextResolve(req);
    var module = __webpack_require__(id);
    return module;
  }
  
  //    moduleId     (  )    
  //         webpack          ,moduleId        request
  function webpackContextResolve(req) {
    // id         
    var id = map[req];
    //           ,      webpack      0.js 1.js                   error
    if (!(id + 1)) {
      // check for number or string
      var e = new Error('Cannot find module "' + req + '".');
      e.code = 'MODULE_NOT_FOUND';
      throw e;
    }
    return id;
  }
  
  //        moduleId
  webpackContext.keys = function webpackContextKeys() {
    return Object.keys(map);
  };
  //           
  webpackContext.resolve = webpackContextResolve;
  //           context    
  module.exports = webpackContext;
  //      moduleId    __webpack_require__      
  webpackContext.id = './src/demos sync recursive \\.ts';
}
ソースに詳しいコメントを書きました.このコードを見たら、ドキュメントの中で言っているrequire.contextが3つのAPIを持つ関数を返します.
続いてコンパイルを見てみます.index.tsのソースコードです.
'./src/index.ts': function(module, exports, __webpack_require__) {
  function importAll(contextLoader) {
    contextLoader.keys().forEach(function(id) {
      //      moduleId,    context            
      return console.log(contextLoader(id));
    });
  }
  var contextLoader = __webpack_require__(
    './src/demos sync recursive \\.ts'
  );
  importAll(contextLoader);
}
簡単には、require.context__webpack_require__のキャリアをコンパイルし、ID ./src/demos sync recursive \\.tsのモジュールをロードしていることが分かります.syncは、これらのモジュールを同期してローディングしていることを示しています.これから、webpackがどのようにすべてのモジュールを構築し、動的にロードされているかがよく分かります.
階段を進み、webpackのソースコードを深く探究する.
私たちはwebpackが2.6バージョンの後、モジュールをロードする時、recursiveモジュールローディングモードを指定できます.私たちはいくつかの方法を使って、私たちがロードするモジュールを制御できます.一般的に使用されるmodeは、webpackMode sync lazy lazy-once 142
だから、require.comでは、同じように適用されています.eagerを調べてみたら、4番目のパラメータがあります.
かいつまんで言えば
  • @types/webpack-envは、現在のファイルに直接包装し、同期してロードし、
  • を実行する.
  • sync遅延負荷は、個別のchunkファイル
  • から分離されます.
  • lazy遅延負荷は、個別のchunkファイルから分離され、次に直接メモリ内のコードをロードする.
  • lazy-onceは別々のchunkファイルを分離しませんが、promiseに戻ります.プロミセを呼び出してコードを実行するだけです.コードを先にロードしたと理解できますが、遅延を制御してこのコードを実行することができます.
  • 文書はここにありますhttps://webpack.docschina.org....
    この部分の文書はとても晦渋で、文書グループが追いついていないかもしれません.だから、webpackのソースコードを見に行くと、本当に6種類のmodeがあることが分かります.
    modeタイプ定義
    https://github.com/webpack/we...
    私たちの書類を再帰的に取得できるようにするにはどうすればいいですか?先ほどのソースの住所からこのような行のコードが見つかりました.
    これは私たちが必要なモジュールを探しに行くことです.ですから、私たちはこの行に従って具体的なソースコードを調べます.
    これはrequire.co ntectが私たちのファイルにどのようにロードされるかの具体的な論理です.実はeagerだけです.最後にファイルを取得した後、contextキャリアによってモジュール構造オブジェクトを生成します.例えば、このようなコードはfs.readdirタイプのcontextキャリアの生成を担当しています.他の5つのタイプを具体的に見ることができます.
    6種類のタイプは論理をロードして、contextキャリアを生成するモジュール構造オブジェクトです.
    https://github.com/webpack/we...
    締め括りをつける
    1.webpackはどのようにモジュールをロードするかを学習し、webpackのキャリアはどのように動作し、最後にコンパイルされたコードを生成しますか?
    2.もともとはsyncがどのように実現したのかを知りたいだけですが、第3のパラメータは6つのモードがあることが分かりました.この部分もwebpack文書にはないです.
    3.実用的なAPIから、アプリの実現原理を探って、webpackのソースコードの一部を一緒に読みました.
    4.本質を探ることは、APIの演算子になるよりもはるかに重要です.あなたが絶えず本質を探してこそ、世界の神秘を発見することができます.
    最後にレンガを投げて玉を引いて、このような構想によって更にその他の6種類のmodeのコンパイルした後のコードを学ぶことができます.
    文章でコンパイルしたコードは全部ここにあります.https://github.com/MeCKodo/re...
    個人サイト>>http://www.meckodo.com
    最後の一年中求人
    厦門RingCentral外資企業、福利待遇は厦門のトップクラスです.
    5時半に退勤します.5時半に退勤します.5時半に退勤します.
    アイデアがあります.abcdefghijklmnoKodを追加してください.