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