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模块加载原理