研究了一下CommonJS規(guī)范,用webpack打包之后,得到源碼進(jìn)行分析躲查,只要分析webpack_require與打包的過程它浅。webpack打包的命令(webpack --devtool none --mode development --target node ./src/index.js --output-path='./CommonJS'
)
- webpack的用法自行百度,我只展示打包后的代碼(把注釋刪掉了)
源碼
// core.js
console.log('core js')
exports.name = 'Jack'
exports.old = '18'
exports.play = function() {
console.log('play game')
}
module.exports = function() {
console.log('module')
}
// index.js
const Core = require('./core.js')
console.log(Core.name)
console.log(Core.old)
console.log(Core.paly)
console.log(Core)
(function (modules) {
var installedModules = {};
function __webpack_require__(moduleId) {
if (installedModules[moduleId]) {
return installedModules[moduleId].exports;
}
var module = installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {}
};
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
module.l = true;
return module.exports;
}
__webpack_require__.m = modules;
__webpack_require__.c = installedModules;
__webpack_require__.d = function (exports, name, getter) {
if (!__webpack_require__.o(exports, name)) {
Object.defineProperty(exports, name, { enumerable: true, get: getter });
}
};
__webpack_require__.r = function (exports) {
if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
}
Object.defineProperty(exports, '__esModule', { value: true });
};
__webpack_require__.t = function (value, mode) {
if (mode & 1) value = __webpack_require__(value);
if (mode & 8) return value;
if ((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
var ns = Object.create(null);
__webpack_require__.r(ns);
Object.defineProperty(ns, 'default', { enumerable: true, value: value });
if (mode & 2 && typeof value != 'string') for (var key in value) __webpack_require__.d(ns, key, function (key) { return value[key]; }.bind(null, key));
return ns;
};
__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;
};
__webpack_require__.o = function (object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
__webpack_require__.p = "";
return __webpack_require__(__webpack_require__.s = "./src/index.js");
})({
"./src/core.js": (function (module, exports) {
console.log('core js')
exports.name = 'Jack'
exports.old = '18'
exports.play = function () {
console.log('play game')
}
module.exports = function () {
console.log('module')
}
}),
"./src/index.js": (function (module, exports, __webpack_require__) {
const Core = __webpack_require__(/*! ./core.js */ "./src/core.js")
console.log(Core.name)
console.log(Core.old)
console.log(Core.paly)
console.log(Core)
})
});
分析一下結(jié)構(gòu)
1镣煮、 './src/core.js'與'./src/index.js'是兩個腳本路徑姐霍,每個參數(shù)指向一個函數(shù),每個模塊相當(dāng)于一個作用域,js使用函數(shù)創(chuàng)建作用域镊折。
2胯府、打包之后就是個自執(zhí)行函數(shù),參數(shù)就是每個模塊的對應(yīng)的函數(shù)
(function (modules) {})({模塊1恨胚, 模塊2骂因,...})
3、installedModules 儲存每個模塊初始化赃泡,判斷是否已經(jīng)初始化侣签,在調(diào)用入口文件
4、可以看出來./src/core.js
中module.exports
是被重新賦值急迂,而./src/core.js
內(nèi)部的module.exports
內(nèi)被保留在函數(shù)內(nèi)部
var module = installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {} // 重新賦值
};
return module.exports// 返回結(jié)果
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
關(guān)于webpack打包的原理 AST preset-env loader plugins entry output等有興趣可以了解一下影所,我只是簡單介紹CommonJS規(guī)范引入nodeJS是怎么引用的,以及exports的作用域