webpack 4.xモジュール化浅析-CommunJS

14425 ワード

まずwebpack公式文書のモジュールについて説明します.
モジュール化プログラミングでは、開発者はプログラムを離散機能ブロックに分解し、モジュールと呼ぶ.
各モジュールは、検査、調整、テストが簡単にできるように、完全なプログラムより小さな接触面を持っています.念入りに編纂したモジュールは信頼できる抽象とパッケージの限界を提供しており、アプリケーションの各モジュールが明確な設計と明確な目的を持つようにしている.
webpackの核心概念の一つはすべてのモジュールです.webpackはプロジェクトの中での役割は、JavaScriptモジュールと他のブラウザが直接に実行できない拡張言語(less、scss、typescript)を見つけて、ブラウザに適した形式で包装して使用します.これはプロジェクトの主なファイルから始まります.これらのファイルを処理して、ブラウザで直接使用できないファイルをコンパイルして、一つ以上のブラウザで識別できるJavaScriptファイルに包装します.
この記事はwebpackの構築プロセスを詳しく説明しません.公式サイトでは詳細に説明されています.ここでは主にwebpackを梱包したファイルを分析して、ファイルをどのように包装し、モジュールをどのように使うかを分析しています.webpackが最初にサポートしていたコードモジュール化方式はCommunJSであり、後はES 6、AMDなどを徐々にサポートしています.どのような方式を使ってもwebpackは解析と包装ができます.この例ではCommunJS仕様を使用しています.より多くの規範を紹介しています.公式文書を見ることができます.

後の説明を便利にするために、まず一つのプロジェクトを作成します.つまり、先に一つのフォルダwebpack-testを作成して、webpack-testフォルダの中でコマンド初期化を使って、一つのpackge.jsonファイルを作成して、npmの説明をします.
npm init
命令を実行したら、いくつかの問題を聞きます.途中で車を返してもいいです.webpackの依存パッケージをインストールし、次のコマンドを実行します.
npm install --save-dev webpack
もういくつかのファイルを新規作成します.1、プロジェクトのルートディレクトリの下に新しいフォルダアプリを作成して、業務コード、フォルダpublicを保存して包装したファイルを保存します.2、appに入口ファイルを新規作成します.3、アプリに機能モジュールhello.jsを新規作成し、bye.js、to.js.4、プロジェクトのルートディレクトリの下で、index.ファイルを作成する.
これらの書類に順番に来て、それぞれ以下の内容を記入します.
// webpack-test/app/hello.js
const to = require('./to.js');
module.exports = function() {
  var hello = document.createElement('div');
  hello.textContent = "Say Hello to " + to.name;
  return hello;
};
// webpack-test/app/bye.js
const to = require('./to.js');
module.exports = function() {
  var bye = document.createElement('div');
  bye.textContent = "Say Bye to " + to.name;
  return bye;
};
// webpack-test/app/to.js
module.exports = {name: "  "};
// webpack-test/app/main.js
const hello = require('./hello.js');
const bye = require('./bye.js');

document.querySelector("#root").appendChild(hello()).appendChild(bye());;
// webpack-test/index.html


  
    
    Webpack Test Project
  
  
    
// bundle.js app
モジュールhello.jsとbye.jsはそれぞれの を い、 に のファイルto.jsを しました.メインファイルのmain.jsでモジュールhello.jsとbye.jsを して しました.index.ファイルはmain.jsパッケージの ファイルのbundle.jsを しました.
する
に を います.まずwebpackは にインストールされていることを してください.そうでないと にwebpackのパスを します. えば4.0 のバージョンでnode_を します.modules/.bin/webpack./ap/mail.js./public/bundle.js;webpack 4.0+を っていたら、webpack./ap/main.js./public/bundle.jsコマンドを って、 のエラーを するかもしれません.
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/

ERROR in multi ./app/main.js ./public/bundle.js
Module not found: Error: Can't resolve './public/bundle.js' in '/Users/zhaohaipeng/soyoung-project/webpack-test'
 @ multi ./app/main.js ./public/bundle.js main[1]
webpack 4.0+の 、 のエラーに して、 を する があります. のエラーは、プロファイルを して するのではなく、 するコマンドで されたパッケージ ですので、 ファイルを する があります. 、 しい は の りです.
webpack app/main.js --output public/bundle.js --mode development
:
➜  webpack-test webpack app/main.js --output public/bundle.js --mode development
Hash: a4e2f9ecc51b64891624
Version: webpack 4.25.1
Time: 90ms
Built at: 2018-11-08 17:11:01
    Asset      Size  Chunks             Chunk Names
bundle.js  5.16 KiB    main  [emitted]  main
Entrypoint main = bundle.js
[./app/bye.js] 165 bytes {main} [built]
[./app/hello.js] 173 bytes {main} [built]
[./app/main.js] 144 bytes {main} [built]
[./app/to.js] 30 bytes {main} [built]
➜  webpack-test
ブラウザでindex.ファイルを くと、 が されます.
Say Hello to
Say Bye to
しかし、webpackは たちの の しさと いやすいツールとして、 らかに のようにたくさんのコマンドをたたいて するのは です.だから、 ファイルを ってもう ます.
ルートディレクトリはwebpack.co nfig.jsファイルを し、パッケージの り と を します.
// webpack-test/webpack.config.js
module.exports = {
    mode: "development",//webpack.0        
    entry:  __dirname + "/app/main.js",//      
    output: {
        path: __dirname + "/public",//          
        filename: "bundle.js"//        
    }
}
する はコマンドwebpackだけでいいです.webpackは の のwebpack.co-fig.jsファイルをデフォルトで みます.
にパッケージされたbundle.jsファイルは、 なコメントを し、コードフォーマットを しました. は の りです.
//      ,          ,   key:value,key    
(function(modules) { // webpackBootstrap
    //         ,         ,          ,    
    var installedModules = {};

    // webpack    require          (  ConmmonJS reqiure()),           id        ,       ,  ,  ,  exports
    function __webpack_require__(moduleId) {
       // moduleId      
        //          ,            
        if(installedModules[moduleId]) {
            return installedModules[moduleId].exports;
        }
        //          ,  ,     
        var module = installedModules[moduleId] = {
            i: moduleId,
            l: false,
            exports: {}
        };

        //        exports  ,              ,     
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

        //         
        module.l = true;

        //          
        return module.exports;
    }


    //     ,    (__webpack_modules__)
    __webpack_require__.m = modules;

    //     ,      
    __webpack_require__.c = installedModules;

    //        ,     
    //   exports     getter   
    __webpack_require__.d = function(exports, name, getter) {
        //   name            ,        ,    exports          name   ,       getter   
        if(!__webpack_require__.o(exports, name)) {
            Object.defineProperty(exports, name, { enumerable: true, get: getter });
        }
    };

    //  exports    
    //   exports     __esModule,  key Symbol   ( __webpack_require__.t    )
    // define __esModule on exports
    __webpack_require__.r = function(exports) {
        if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
            //       Module   
            Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
        }
        //    exports     __esModule
        Object.defineProperty(exports, '__esModule', { value: true });
    };

    //        ,     
    //             
    // create a fake namespace object
    // mode & 1: value is a module id, require it
    // mode & 2: merge all properties of value into the ns
    // mode & 4: return value when already ns object
    // mode & 8|1: behave like require
    __webpack_require__.t = function(value, mode) {
        if(mode & 1) value = __webpack_require__(value);
        if(mode & 8) return value;
        if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
        var ns = Object.create(null);
        __webpack_require__.r(ns);
        Object.defineProperty(ns, 'default', { enumerable: true, value: value });
        if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
        return ns;
    };

    //        ,     
    // 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 = "";


    //        main.js ,   exports,           ,      ,          
    return __webpack_require__(__webpack_require__.s = "./app/main.js");
})({

    "./app/bye.js": (function(module, exports, __webpack_require__) {

        eval("const to = __webpack_require__(/*! ./to.js */ \"./app/to.js\");
module.exports = function() {
var bye = document.createElement('div');
bye.textContent = \"Say Bye to \" + to.name;
return bye;
};

//# sourceURL=webpack:///./app/bye.js?"); }), "./app/hello.js": (function(module, exports) { eval("module.exports = function() {
var hello = document.createElement('div');
hello.textContent = \"Say Hello!\";
return hello;
};

//# sourceURL=webpack:///./app/hello.js?"); }), "./app/main.js": (function(module, exports, __webpack_require__) { eval("const hello = __webpack_require__(/*! ./hello.js */ \"./app/hello.js\");
const bye = __webpack_require__(/*! ./bye.js */ \"./app/bye.js\");

document.querySelector(\"#root\").appendChild(hello()).appendChild(bye());;

//# sourceURL=webpack:///./app/main.js?"); }), "./app/to.js": (function(module, exports) { eval("module.exports = {name: \" \"};

//# sourceURL=webpack:///./app/to.js?"); }) });

webpackの は、 パラメータを み み、プラグインを し、モジュール (loader)を い、パッケージファイルを します. の では、JavaScriptの だけで、プラグインやCSS、less、ピクチャなどのようなloader が なモジュールは されていませんので、 の では、プロセスは を み り、 り と モジュールを し、いくつかのステップを して、 なbundle.jsファイルを します.
このプロセスでwebpackの フローを に します.プロファイルで り を み り、pluginsパラメータが されているなら、この もプラグインの とフック のバインディングを います.モジュール 、すなわち、loaderが した で、 ファイルから のモジュールに する に じて、プロファイルに して なる のファイルに されるloader(キャリア )について します.これらのモジュールを したり、 したり、あるいは したりして、ブラウザが できる を します. にモジュールを して、 したファイルを します. のコードの で、すでにbundle.jsの に して の を いました. にbundle.jsの を します.
1、
の のファイルbundle.jsはJavaScriptファイルです.それ は です.
(function(  ){})(  )。
2、パラメータ
のパラメータはすべてのモジュールからなる で、keyは モジュールのパスで、 モジュールの の コードとして があり、パラメータ のコードを し、パッケージ のソースコードと して、すべてのrequireは__u u 0026 quot;になっていることが かります.webpack_リキュールこのwebpackカスタムモジュールの び し は、ソースの なパスも に されるファイルの なパスになります.
{

    "./app/bye.js": (function(module, exports, __webpack_require__) {

        eval("const to = __webpack_require__(/*! ./to.js */ \"./app/to.js\");
module.exports = function() {
var bye = document.createElement('div');
bye.textContent = \"Say Bye to \" + to.name;
return bye;
};

//# sourceURL=webpack:///./app/bye.js?"); }), "./app/hello.js": (function(module, exports) { eval("module.exports = function() {
var hello = document.createElement('div');
hello.textContent = \"Say Hello!\";
return hello;
};

//# sourceURL=webpack:///./app/hello.js?"); }), "./app/main.js": (function(module, exports, __webpack_require__) { eval("const hello = __webpack_require__(/*! ./hello.js */ \"./app/hello.js\");
const bye = __webpack_require__(/*! ./bye.js */ \"./app/bye.js\");

document.querySelector(\"#root\").appendChild(hello()).appendChild(bye());;

//# sourceURL=webpack:///./app/main.js?"); }), "./app/to.js": (function(module, exports) { eval("module.exports = {name: \" \"};

//# sourceURL=webpack:///./app/to.js?"); }) }
3、 する
(1) ファイルの 、 の までは、まず り ファイルから み みを します.
return __webpack_require__(__webpack_require__.s = "./app/main.js");
(2)グウwebpack_リキュール が び され、パラメータが ります.
function __webpack_require__(moduleId) {
        // moduleId   ./app/main.js
        //     ,   ,       
        if(installedModules[moduleId]) {
            return installedModules[moduleId].exports;
        }
        //    ./app/main.js   ,     
        var module = installedModules[moduleId] = {
            i: moduleId,
            l: false,
            exports: {}
        };

        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

        //         
        module.l = true;

        //        
        return module.exports;
    }
この の ではmodules[moduleId].call(module.export,module,module.export,__webpackurequire_)を します.という のモジュールで のコードを します.
(function(module, exports, __webpack_require__) {

        eval("const hello = __webpack_require__(/*! ./hello.js */ \"./app/hello.js\");
const bye = __webpack_require__(/*! ./bye.js */ \"./app/bye.js\");

document.querySelector(\"#root\").appendChild(hello()).appendChild(bye());;

//# sourceURL=webpack:///./app/main.js?"); })()
により、 は の_u uを します.webpack_リキュールメソッドは、モジュールパスをそれぞれ します./app/hello.jsと./app/bye.js;
(3) の_u u_uを するwebpack_リキュールプロセスは、パラメータの い、 モジュールの いを いて、 のステップとほぼ しています.モジュールT.jsに して び び します.webpack_require_
"./app/hello.js": (function(module, exports, __webpack_require__) {

    eval("const to = __webpack_require__(/*! ./to.js */ \"./app/to.js\");
module.exports = function() {
var hello = document.createElement('div');
hello.textContent = \"Say Hello to \" + to.name;
return hello;
};

//# sourceURL=webpack:///./app/hello.js?"); }),
(4)2 の_u u_を するwebpack_リキュールで、bye.jsでto.jsに する を つけましたので、 き きコールします.webpack_リキュール は、ただの のみとなりました.
"./app/bye.js": (function(module, exports, __webpack_require__) {

        eval("const to = __webpack_require__(/*! ./to.js */ \"./app/to.js\");
module.exports = function() {
var bye = document.createElement('div');
bye.textContent = \"Say Bye to \" + to.name;
return bye;
};

//# sourceURL=webpack:///./app/bye.js?"); })
(5)この で、 ファイルからの モジュールに する はすでに し、すべてのjsコードも みで、bundle.jsに れました.
め りをつける
ここまで ることができます.webpackはjsの に して、 の としてパッケージ しています.これらの に する によって、モジュール の があります.パッケージ の は、これらの を 、 、パッケージ する で、 の は に ています. から し、 の に って「require」 を します.そして、この が き りに るまで、 を す です.nodeのシングルスレッドのため、プロジェクトが かモジュール に して になると、webpack はもっと がかかります.
はwebpack4.xの でjsモジュールの に する な で、 に の と のファイルの に づいて、ソースは みにくいです.ES 6、AMDのモジュール 、コード などについては、 で します.
に があれば、ご ください.