- CommonJS,SeaJS,KissY
 - AMD,requireJS
 - ES Module
 - Webpack
 
模块Module
- 一个模块本质是一个模块对象,通过 module.exports对外暴露接口
- exports 只是 module.exports 的一个引用
 
 internal/bootstrap/loaders.js和internal/modules/cjs/loader都是 Loader- bootstrap/loaders.js 加载 node Native模块
 - cjs/loader 加载自定义的 JS 模块
 
- node 里面 
require('./index')的依赖查找有后缀名的优先级,分别是 .js > .json > .node- 一个模块的入口文件路径,是在 package.json 的 main 里面定义
 - node 里面依赖的模块统一在 node_modules 下面管理
 
 - node 里的 modules 已经不再是严格意义的 CommonJS
 
exports.router = routermodule.exports = routermodule.exports = { router: router }
console.log(Module)
{id: '.',parent: null,loaded: false,exports: { steps: '|..........》' },filename: '/Users/c/d/node-10.x/demo/race.js',children: [ Module {id: '/Users/c/d/node-10.x/demo/step.js',exports: [Object], parent: [Circular],loaded: true, children: [], paths: [Array]filename: '/Users/c/d/node-10.x/demo/step.js'],paths: [ '.../node_modules' ]}
- parent 引用它的父亲模块的信息
 - children 引用了别的接口的模块
 - 一个模块既可以被引用,也可以引用别人
 
实现 module
- Node 的模块机制
 - 拿到代码后的第一件事就是:对代码包裹一个函数表达式,传入一些变量
 
function Module(id, parent) {this.id = id;this.exports = {};}Module.wrap = function(script) {return Module.wrapper[0] + script + Module.wrapper[1];};Module.wrapper = ['(function (exports, require, module, __filename, __dirname) { ','\n});'];Module.runMain = function() {Module._load(process.argv[1], null, true);};Module._load = function(request, parent, isMain) {var module = new Module(filename, parent);tryModuleLoad(module, filename);};function tryModuleLoad(module, filename) {module.load(filename);}Module.prototype.load = function(filename) {Module._extensions['.js'](this, filename);};Module._extensions['.js'] = function(module, filename) {var content = fs.readFileSync(filename, 'utf8');module._compile(stripBOM(content), filename);};Module.prototype._compile = function(content, filename) {var wrapper = Module.wrap(content);var compiledWrapper = vm.runInThisContext(wrapper, {filename: filename,lineOffset: 0,displayErrors: true});var require = makeRequireFunction(this);compiledWrapper.call(this.exports, this.exports, require, this, filename, dirname);};Module.prototype.require = function(id) {return Module._load(id, this, /* isMain */ false);};Module._resolveFilename = function(request, parent, isMain, options) {};
- 在 node 命令行模式下,输入:来查看包裹的方法
require('module').wrap.toString()require('module').wrapper
 
webpack
// ChunkRenderError.jsconst WebpackError = require('./WebpackError')class ChunkRenderError extends WebpackError {constructor(chunk, file, error) {super()this.name = 'ChunkRenderError'this.error = errorthis.message = error.messagethis.details = error.stackthis.file = filethis.chunk = chunkError.captureStackTrace(this, this.constructor)}}module.exports = ChunkRenderError
node module
(function (exports, require, module, __filename, __dirname) {const WebpackError = require('./WebpackError')class ChunkRenderError extends WebpackError {constructor(chunk, file, error) {super()this.name = 'ChunkRenderError'this.error = errorthis.message = error.messagethis.details = error.stackthis.file = filethis.chunk = chunkError.captureStackTrace(this, this.constructor)}}module.exports = ChunkRenderError})
commonJS规范
- CommonJS 的前身是 ServerJS
 - CommonJS 是一套模块规范:约定了模块如何定义、加载与执行等
 
node启动流程
- Node 源码有一坨依赖,大部分是 C/C++ 底层
 - Node 启动入口是 node_main.cc 的 main 函数
 - 入口函数找到 node.cc 的 3 个 Start,依次调用
 - node.cc 的第一个 Start 初始化了 v8,调用第二个 Start
 - 第二个 Start 让 v8 准备了引擎实例,调用第三个 Start
 - 第三个 Start
- 首先准备了 v8 的上下文 Context
 - 其次准备了 Node 的启动环境,对各种需要的变量做整理
 - 再把 Node 原生模块和我们的 JS 代码都加载进来运行
 - 最后把主持人 libuv 请上场,执行 JS 里的各种任务
 
 - libuv 没活干了,就一层层来退出进程、收拾场地,退出程序
 
webpack编译的 commonJS规范
console.log('this is module');exports.geekbang = { 'hello': 'haha' }exports.tencent = function () {console.log('good')}module.exports = function () {console.log('hello geekbang');}
index.js webpack编译后的结果
/******/ (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: {}/******/ };/******//******/ // Execute the module function/******/ 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;/******//******/ // define getter function for harmony exports/******/ __webpack_require__.d = function(exports, name, getter) {/******/ if(!__webpack_require__.o(exports, name)) {/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });/******/ }/******/ };/******//******/ // define __esModule on exports/******/ __webpack_require__.r = function(exports) {/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });/******/ }/******/ Object.defineProperty(exports, '__esModule', { value: true });/******/ };/******//******/ // create a fake namespace object/******/ // mode & 1: value is a module id, require it/******/ // mode & 2: merge all properties of value into the ns/******/ // mode & 4: return value when already ns object/******/ // mode & 8|1: behave like require/******/ __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;/******/ };/******//******/ // 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 = "./index.js");/******/ })/************************************************************************//******/ ({/***/ "./index.js":/*! no static exports found *//***/ (function(module, exports, __webpack_require__) {console.log('start require');__webpack_require__(/*! ./lib */ "./lib.js")console.log('end require');/***/ }),/***/ "./lib.js":/*! no static exports found *//***/ (function(module, exports) {console.log('this is module');exports.geekbang = { 'hello': 'haha' }exports.tencent = function () {console.log('good')}module.exports = function () {console.log('hello geekbang');}})});
