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——使人困惑的地方數組