webpack打包原理

webpack只是一個打包模塊的機制,只是把依賴的模塊轉化成能夠表明這些包的靜態文件。並非什麼commonjs或者amd之類的模塊化規範。webpack就是識別你的 入口文件。識別你的模塊依賴,來打包你的代碼。至於你的代碼使用的是commonjs仍是amd或者es6的import。webpack都會對其進行分析。來獲取代碼的依賴。webpack作的就是分析代碼。轉換代碼,編譯代碼,輸出代碼。webpack自己是一個node的模塊,因此webpack.config.js是以commonjs形式書寫的(node中的模塊化是commonjs規範的)
webpack中每一個模塊有一個惟一的id,是從0開始遞增的。整個打包後的bundle.js是一個匿名函數自執行。參數則爲一個數組。數組的每一項都爲個function。function的內容則爲每一個模塊的內容,並按照require的順序排列。css

// webpack.config.js
module.exports = {
  entry:'./a.js',
  output:{
    filename:'bundle.js'
  }
};
// a.js
var b = require('./b.js');

console.log('a');

b.b1();
// b.js
exports.b1 = function () {
  console.log('b1')
};

exports.b2 = function () {
  console.log('b2')
};

以上代碼咱們打包處理的js爲node

// bundle.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] = {
/******/            exports: {},
/******/            id: moduleId,
/******/            loaded: false
/******/        };

/******/        // Execute the module function
/******/        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/        // Flag the module as loaded
/******/        module.loaded = 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;

/******/    // __webpack_public_path__
/******/    __webpack_require__.p = "";

/******/    // Load entry module and return exports
/******/    return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

    var b = __webpack_require__(1);

    console.log('a');

    b.b1();


/***/ },
/* 1 */
/***/ function(module, exports) {

    exports.b1 = function () {
      console.log('b1')
    };

    exports.b2 = function () {
      console.log('b2')
    };

/***/ }
/******/ ]);

咱們看到_webpack_require是模塊加載函數,接收模塊id(對,webpack中每一個模塊都會有一個獨一無二的id,其實也就是在IIFE傳參數組中的索引值(0,1,2…)
a依賴b,因此在a中調用webpack加載模塊的函數webpack

上面是使用的commonjs規範書寫的
webpack2是如何對實現es6 modules的
webpack模塊化原理-ES module
不管什麼模塊規範書寫。咱們的webpack進行識別後打包的內容不會相差不少,webpack有優秀的語法分析能力,支持 CommonJs AMD 等規範。
webpack爲何能把任何形式的資源都視做模塊呢?由於loader機制。不一樣的資源採用不一樣的loader進行轉換。CMD、AMD 、import、css 、等都有相應的loader去進行轉換。那爲何咱們平時寫的es6的模塊機制,不用增長import的loader呢。由於咱們使用了babel把import轉換成了require。而且Webpack 2 將增長對 ES6 模塊的原生支持而且混用 ES六、AMD 和 CommonJS 模塊。這意味着 Webpack 如今能夠識別 import 和 export 了,不須要先把它們轉換成 CommonJS 模塊的格式:Webpack 2 有哪些新東西webpack對於es模塊的實現,也是基於本身實現的webpack_require 和webpack_exports ,裝換成相似於commonjs的形式。es6 module是靜態的依賴,因此在運行前進行代碼轉換,這裏的實現是將全部導出項做爲一個對象的屬性,在入口文件執行時,去遞歸的加載模塊。
如何實現一個簡單的webpackes6

讀取文件分析模塊依賴
對模塊進行解析執行(深度遍歷)
針對不一樣的模塊使用相應的loader
編譯模塊,生成抽象語法樹AST。
循環遍歷AST樹,拼接輸出js。
webpack 源碼解析
細說 webpack 之流程篇
如何實現一個簡單的webpackweb

loader原理
在解析對於文件,會自動去調用響應的loaderloader 本質上是一個函數,輸入參數是一個字符串,輸出參數也是一個字符串。固然,輸出的參數會被當成是 JS 代碼,從而被 esprima 解析成 AST,觸發進一步的依賴解析。webpack會按照從右到左的順序執行loader。
Webpack——使人困惑的地方數組

相關文章
相關標籤/搜索