1. CommonJS,SeaJS,KissY
  2. AMD,requireJS
  3. ES Module
  4. Webpack

模块Module

  1. 一个模块本质是一个模块对象,通过 module.exports对外暴露接口
    1. exports 只是 module.exports 的一个引用
  2. internal/bootstrap/loaders.jsinternal/modules/cjs/loader 都是 Loader
    1. bootstrap/loaders.js 加载 node Native模块
    2. cjs/loader 加载自定义的 JS 模块
  3. node 里面 require('./index') 的依赖查找有后缀名的优先级,分别是 .js > .json > .node
    1. 一个模块的入口文件路径,是在 package.json 的 main 里面定义
    2. node 里面依赖的模块统一在 node_modules 下面管理
  4. node 里的 modules 已经不再是严格意义的 CommonJS
    1. 前端模块的变革 https://www.cyj.me/programming/2018/05/22/about-module-i/
  1. exports.router = router
  2. module.exports = router
  3. module.exports = { router: router }

console.log(Module)

  1. {
  2. id: '.',
  3. parent: null,
  4. loaded: false,
  5. exports: { steps: '|..........》' },
  6. filename: '/Users/c/d/node-10.x/demo/race.js',
  7. children: [ Module {
  8. id: '/Users/c/d/node-10.x/demo/step.js',
  9. exports: [Object], parent: [Circular],
  10. loaded: true, children: [], paths: [Array]
  11. filename: '/Users/c/d/node-10.x/demo/step.js'
  12. ],
  13. paths: [ '.../node_modules' ]
  14. }
  1. parent 引用它的父亲模块的信息
  2. children 引用了别的接口的模块
  3. 一个模块既可以被引用,也可以引用别人

实现 module

  1. Node 的模块机制
  2. 拿到代码后的第一件事就是:对代码包裹一个函数表达式,传入一些变量
  1. function Module(id, parent) {
  2. this.id = id;
  3. this.exports = {};
  4. }
  5. Module.wrap = function(script) {
  6. return Module.wrapper[0] + script + Module.wrapper[1];
  7. };
  8. Module.wrapper = [
  9. '(function (exports, require, module, __filename, __dirname) { ',
  10. '\n});'
  11. ];
  12. Module.runMain = function() {
  13. Module._load(process.argv[1], null, true);
  14. };
  15. Module._load = function(request, parent, isMain) {
  16. var module = new Module(filename, parent);
  17. tryModuleLoad(module, filename);
  18. };
  19. function tryModuleLoad(module, filename) {
  20. module.load(filename);
  21. }
  22. Module.prototype.load = function(filename) {
  23. Module._extensions['.js'](this, filename);
  24. };
  25. Module._extensions['.js'] = function(module, filename) {
  26. var content = fs.readFileSync(filename, 'utf8');
  27. module._compile(stripBOM(content), filename);
  28. };
  29. Module.prototype._compile = function(content, filename) {
  30. var wrapper = Module.wrap(content);
  31. var compiledWrapper = vm.runInThisContext(wrapper, {
  32. filename: filename,
  33. lineOffset: 0,
  34. displayErrors: true
  35. });
  36. var require = makeRequireFunction(this);
  37. compiledWrapper.call(this.exports, this.exports, require, this, filename, dirname);
  38. };
  39. Module.prototype.require = function(id) {
  40. return Module._load(id, this, /* isMain */ false);
  41. };
  42. Module._resolveFilename = function(request, parent, isMain, options) {};
  1. 在 node 命令行模式下,输入:来查看包裹的方法
    1. require('module').wrap.toString()
    2. require('module').wrapper

webpack

  1. // ChunkRenderError.js
  2. const WebpackError = require('./WebpackError')
  3. class ChunkRenderError extends WebpackError {
  4. constructor(chunk, file, error) {
  5. super()
  6. this.name = 'ChunkRenderError'
  7. this.error = error
  8. this.message = error.message
  9. this.details = error.stack
  10. this.file = file
  11. this.chunk = chunk
  12. Error.captureStackTrace(this, this.constructor)
  13. }
  14. }
  15. module.exports = ChunkRenderError

node module

  1. (function (exports, require, module, __filename, __dirname) {
  2. const WebpackError = require('./WebpackError')
  3. class ChunkRenderError extends WebpackError {
  4. constructor(chunk, file, error) {
  5. super()
  6. this.name = 'ChunkRenderError'
  7. this.error = error
  8. this.message = error.message
  9. this.details = error.stack
  10. this.file = file
  11. this.chunk = chunk
  12. Error.captureStackTrace(this, this.constructor)
  13. }
  14. }
  15. module.exports = ChunkRenderError
  16. })

commonJS规范

  1. CommonJS 的前身是 ServerJS
  2. CommonJS 是一套模块规范:约定了模块如何定义、加载与执行等

node启动流程

  1. Node 源码有一坨依赖,大部分是 C/C++ 底层
  2. Node 启动入口是 node_main.cc 的 main 函数
  3. 入口函数找到 node.cc 的 3 个 Start,依次调用
  4. node.cc 的第一个 Start 初始化了 v8,调用第二个 Start
  5. 第二个 Start 让 v8 准备了引擎实例,调用第三个 Start
  6. 第三个 Start
    1. 首先准备了 v8 的上下文 Context
    2. 其次准备了 Node 的启动环境,对各种需要的变量做整理
    3. 再把 Node 原生模块和我们的 JS 代码都加载进来运行
    4. 最后把主持人 libuv 请上场,执行 JS 里的各种任务
  7. libuv 没活干了,就一层层来退出进程、收拾场地,退出程序

webpack编译的 commonJS规范

  1. console.log('this is module');
  2. exports.geekbang = { 'hello': 'haha' }
  3. exports.tencent = function () {
  4. console.log('good')
  5. }
  6. module.exports = function () {
  7. console.log('hello geekbang');
  8. }

index.js webpack编译后的结果

  1. /******/ (function(modules) { // webpackBootstrap
  2. /******/ // The module cache
  3. /******/ var installedModules = {};
  4. /******/
  5. /******/ // The require function
  6. /******/ function __webpack_require__(moduleId) {
  7. /******/
  8. /******/ // Check if module is in cache
  9. /******/ if(installedModules[moduleId]) {
  10. /******/ return installedModules[moduleId].exports;
  11. /******/ }
  12. /******/ // Create a new module (and put it into the cache)
  13. /******/ var module = installedModules[moduleId] = {
  14. /******/ i: moduleId,
  15. /******/ l: false,
  16. /******/ exports: {}
  17. /******/ };
  18. /******/
  19. /******/ // Execute the module function
  20. /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  21. /******/
  22. /******/ // Flag the module as loaded
  23. /******/ module.l = true;
  24. /******/
  25. /******/ // Return the exports of the module
  26. /******/ return module.exports;
  27. /******/ }
  28. /******/
  29. /******/
  30. /******/ // expose the modules object (__webpack_modules__)
  31. /******/ __webpack_require__.m = modules;
  32. /******/
  33. /******/ // expose the module cache
  34. /******/ __webpack_require__.c = installedModules;
  35. /******/
  36. /******/ // define getter function for harmony exports
  37. /******/ __webpack_require__.d = function(exports, name, getter) {
  38. /******/ if(!__webpack_require__.o(exports, name)) {
  39. /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
  40. /******/ }
  41. /******/ };
  42. /******/
  43. /******/ // define __esModule on exports
  44. /******/ __webpack_require__.r = function(exports) {
  45. /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  46. /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  47. /******/ }
  48. /******/ Object.defineProperty(exports, '__esModule', { value: true });
  49. /******/ };
  50. /******/
  51. /******/ // create a fake namespace object
  52. /******/ // mode & 1: value is a module id, require it
  53. /******/ // mode & 2: merge all properties of value into the ns
  54. /******/ // mode & 4: return value when already ns object
  55. /******/ // mode & 8|1: behave like require
  56. /******/ __webpack_require__.t = function(value, mode) {
  57. /******/ if(mode & 1) value = __webpack_require__(value);
  58. /******/ if(mode & 8) return value;
  59. /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
  60. /******/ var ns = Object.create(null);
  61. /******/ __webpack_require__.r(ns);
  62. /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
  63. /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
  64. /******/ return ns;
  65. /******/ };
  66. /******/
  67. /******/ // getDefaultExport function for compatibility with non-harmony modules
  68. /******/ __webpack_require__.n = function(module) {
  69. /******/ var getter = module && module.__esModule ?
  70. /******/ function getDefault() { return module['default']; } :
  71. /******/ function getModuleExports() { return module; };
  72. /******/ __webpack_require__.d(getter, 'a', getter);
  73. /******/ return getter;
  74. /******/ };
  75. /******/
  76. /******/ // Object.prototype.hasOwnProperty.call
  77. /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
  78. /******/
  79. /******/ // __webpack_public_path__
  80. /******/ __webpack_require__.p = "";
  81. /******/
  82. /******/
  83. /******/ // Load entry module and return exports
  84. /******/ return __webpack_require__(__webpack_require__.s = "./index.js");
  85. /******/ })
  86. /************************************************************************/
  87. /******/ ({
  88. /***/ "./index.js":
  89. /*! no static exports found */
  90. /***/ (function(module, exports, __webpack_require__) {
  91. console.log('start require');
  92. __webpack_require__(/*! ./lib */ "./lib.js")
  93. console.log('end require');
  94. /***/ }),
  95. /***/ "./lib.js":
  96. /*! no static exports found */
  97. /***/ (function(module, exports) {
  98. console.log('this is module');
  99. exports.geekbang = { 'hello': 'haha' }
  100. exports.tencent = function () {
  101. console.log('good')
  102. }
  103. module.exports = function () {
  104. console.log('hello geekbang');
  105. }
  106. })
  107. });