CommonJS规范

研究了一下CommonJS规范,用webpack打包之后,得到源码进行分析,只要分析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)
  })
});

分析一下结构

1、 './src/core.js'与'./src/index.js'是两个脚本路径,每个参数指向一个函数,每个模块相当于一个作用域,js使用函数创建作用域。
2、打包之后就是个自执行函数,参数就是每个模块的对应的函数

(function (modules) {})({模块1, 模块2,...})

3、installedModules 储存每个模块初始化,判断是否已经初始化,在调用入口文件
4、可以看出来./src/core.jsmodule.exports是被重新赋值,而./src/core.js内部的module.exports内被保留在函数内部

var module = installedModules[moduleId] = {
  i: moduleId,
  l: false,
  exports: {} // 重新赋值
};
return module.exports// 返回结果
modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

关于webpack打包的原理 AST preset-env loader plugins entry output等有兴趣可以了解一下,我只是简单介绍CommonJS规范引入nodeJS是怎么引用的,以及exports的作用域

你可能感兴趣的:(CommonJS规范)