webpack模块加载原理

webpack admin 暂无评论

webpack是如何实现module的?

我们从最后的文件分析 
我们先创建两个文件

a.js
let a = 1
const b = 2
export function log(val) {
 console.log(val)
}
export default{
 a:a,
 b:b
}
app.js
import tt from './a'
import {log} from './a'
console.log(tt.b)
log(tt.b)

然后在webpack中设置app.js为入口,打包一下…

webpack 会根据入口文件的依赖读入所有依赖的js,最后生成一个文件(默认配置),在文件中具体的看下面

ps:最后打包好都是在一个文件中,这里先拿出其中一部分分析

先看a.js在打包文件中是什么样子

function(module, __webpack_exports__, __webpack_require__) {
 "use strict";
 /* harmony export (immutable) */ __webpack_exports__["b"] = log;
 let a = 1
 const b = 2
 function log(val) {
   console.log(val)
 }
 /* harmony default export */ __webpack_exports__["a"] = {
   a:a,
   b:b
 };
}

可以看到webpack首先将整个文件包裹了起来,添加了三个变量,然后将export的属性都绑定到了webpack_exports

再看app.js

function(module, __webpack_exports__, __webpack_require__) {
 "use strict";
 Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
 /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__a__ = __webpack_require__(0);
 console.log(__WEBPACK_IMPORTED_MODULE_0__a__["a" /* default */].b)
 __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__a__["b" /* log */])(__WEBPACK_IMPORTED_MODULE_0__a__["a" /* default */].b)
 /***/ }

对比原app.js

import tt from './a'
import {log} from './a'
console.log(tt.b)
log(tt.b)

webpack_require(0)就是返回模块export的模块

可以看到,import 在这里就是创了一个含有导入模块export的对象,在下面调用模块时,去这个对象中调用.

下面来看webpack_require

(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: {}
 };
 // 执行了导入的module,把export的值都放到module.exports中
 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;
// identity function for calling harmony imports with the correct context
__webpack_require__.i = function(value) { return value; };
// 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
   });
 }
};
// 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 = 1);
})
 /************************************************************************/
([
 /* 0 */
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 "use strict";
 /* harmony export (immutable) */ __webpack_exports__["b"] = log;
 let a = 1
 const b = 2
 function log(val) {
   console.log(val)
 }
 /* harmony default export */ __webpack_exports__["a"] = {
   a:a,
   b:b
 };
 /***/ }),
 /* 1 */
 /***/ (function(module, __webpack_exports__, __webpack_require__) {
 "use strict";
 Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
 /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__a__ = __webpack_require__(0);
 console.log(__WEBPACK_IMPORTED_MODULE_0__a__["a" /* default */].b)
 __webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__a__["b" /* log */])(__WEBPACK_IMPORTED_MODULE_0__a__["a" /* default */].b)
 /***/ })
]);

这里用了一个立即执行函数,把所有的模块做为一个数组传了进去,在初始化之后,调用了入口模块return __webpack_require__(__webpack_require__.s = 1); 1就是入口模块所在的数组index,然后在调用入口模块时,递归的加载入口模块调用的模块,比如: 在入口模块中

/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__a__ = __webpack_require__(0); 
这就会去加载其他的模块,将其他模块中的export变量导入到入口模块中,供给模块内部使用.

总结

es6 module是静态的依赖,所以在运行前进行代码转换,这里的实现是将所有导出项作为一个对象的属性,在入口文件执行时,去递归的加载模块


转载请注明: Vue教程中文网 - 打造国内领先的vue学习网站-vue视频,vue教程,vue学习,vue培训 » webpack模块加载原理

喜欢 ()or分享