本文地址:http://www.cnblogs.com/jasonxuli/p/4381747.html

nodejs的非核心模块(core module)加载主要使用的就是module.js。

项目主模块(index.js/main.js等)加载使用的应该是module.js中的runMain(),其他js模块加载流程基本上是:

1,获取js文件信息;

2,new Module();

3,读取js文件内容,封装到一个function中,同时注入module本身,module.exports,包装过的require函数等变量;

4,在某个上下文环境中执行这个封装后的function;

5,返回module.exports;

下面是摘出的主要代码

module.js:

// Loads a module at the given file path. Returns that module's
// `exports` property.
Module.prototype.require = function(path) {
assert(path, 'missing path');
assert(util.isString(path), 'path must be a string');
return Module._load(path, this);
}; // Check the cache for the requested file.
// 1. If a module already exists in the cache: return its exports object.
// 2. If the module is native: call `NativeModule.require()` with the
// filename and return the result.
// 3. Otherwise, create a new module for the file and save it to the cache.
// Then have it load the file contents before returning its exports
// object.
Module._load(filename, this){
If(fileName in Module._cache)
Return Module._cache[filename];
  var module = new Module(filename, parent);
  Module._cache[filename] = module;
  Module.load(filename);
  // 先把模块放到缓存然后再去加载内容,可以解决循环依赖的问题。
  // 参见https://nodejs.org/api/modules.html的Cycles部分。
  return module.exports;
} Module.prototype.load(filename){
var extension = path.extname(filename) || ‘.js’;
Module._extensions[extension](this, filename){
var content = fs.readFileSync(filename, ‘utf-8’);
module._compile(content, filename);
  }
} // Run the file contents in the correct scope or sandbox. Expose
// the correct helper variables (require, module, exports) to
// the file.
// Returns exception, if any.
Module.prototype._compile = function(content, filename) {
function require(path) {
return self.require(path);
  }   require.main = process.mainModule;   // Enable support to add extra extension types
  require.extensions = Module._extensions;
  require.cache = Module._cache;   // TODO: 每个模块加载到自己的context中会有什么不同?
  // Set the environ variable NODE_MODULE_CONTEXTS=1 to make node load all modules in their own context.
  // Module._contextLoad = (+process.env['NODE_MODULE_CONTEXTS'] > 0);
  // if (Module._contextLoad) { .... }   // create wrapper function
  var wrapper = NativeModule.wrap(content);
  // wrapper = '(function (exports, require, module, __filename, __dirname) { ' + content + '\n});'   // runInThisContext()可以认为是在某个上下文环境中执行的eval()。
  // compiledWrapper相当于eval(‘(function(){....})’)的结果,也就是真正的Function。
  var compiledWrapper = runInThisContext(wrapper, { filename: filename });   // module.exports 和 exports 的区别:
  // 这里只传递了exports的引用;而上面Module._load()返回的是module.exports,因此给module.exports赋值后,
  // exports仍然指向之前的module.exports。
  var args = [self.exports, require, self, filename, dirname];   // 真正执行compiledWrapper这个function,也就是执行了filename.js的内容。
  return compiledWrapper.apply(self.exports, args);
}

runInThisContext()就是vm.js里的runInThisContext(),vm.runInThisContext()调用了src/node_contextify.cc中的RunInThisContext()。

https://github.com/joyent/node/blob/master/lib/vm.js

https://github.com/joyent/node/blob/master/src/node_contextify.cc

扩展:

https://github.com/brianmcd/contextify

The main difference between Contextify and Node's vm methods is that Contextify allows asynchronous functions to continue executing in the Contextified object's context.

nodejs js模块加载的更多相关文章

  1. js模块化/js模块加载器/js模块打包器

    之前对这几个概念一直记得很模糊,也无法用自己的语言表达出来,今天看了大神的文章,尝试根据自己的理解总结一下,算是一篇读后感. 大神的文章:http://www.css88.com/archives/7 ...

  2. js模块加载之AMD和CMD

    当我写这篇文章的时候,sea.js已经逐渐退出历史的舞台,详细链接.不过任何新事物的出现都是对旧事物的取其精华,去其糟粕,所以了解一下以前模块的加载也是一件好事. js模块化的原因自不比多说,看看HU ...

  3. sea.js模块加载工具

    seajs的使用 seajs是一个jS模块加载器,由淘宝前端架构师玉伯开发,它可以解决命名空间污染,文件依赖的问题.可以在一个js文件中引入另外一个js.require('a.js') 1.安装 np ...

  4. 实现简单的 JS 模块加载器

    实现简单的 JS 模块加载器 1. 背景介绍 按需加载是前端性能优化的一个重要手段,按需加载的本质是从远程服务器加载一段JS代码(这里主要讨论JS,CSS或者其他资源大同小异),该JS代码就是一个模块 ...

  5. 【 js 模块加载 】深入学习模块化加载(node.js 模块源码)

    一.模块规范 说到模块化加载,就不得先说一说模块规范.模块规范是用来约束每个模块,让其必须按照一定的格式编写.AMD,CMD,CommonJS 是目前最常用的三种模块化书写规范.  1.AMD(Asy ...

  6. nodejs之模块加载机制

    nodejs模块加载原理 node加载模块步骤: 1) 路径分析 (如判断是不是核心模块.是绝对路径还是相对路径等) 2) 文件定位 (文件扩展名分析, 目录和包处理等细节) 3) 编译执行 原生模块 ...

  7. 【 js 模块加载 】【源码学习】深入学习模块化加载(node.js 模块源码)

    文章提纲: 第一部分:介绍模块规范及之间区别 第二部分:以 node.js 实现模块化规范 源码,深入学习. 一.模块规范 说到模块化加载,就不得先说一说模块规范.模块规范是用来约束每个模块,让其必须 ...

  8. 第三课:sea.js模块加载原理

    模块加载,其实就是把js分成很多个模块,便于开发和维护.因此加载很多js模块的时候,需要动态的加载,以便提高用户体验. 在介绍模块加载库之前,先介绍一个方法. 动态加载js方法: function l ...

  9. JS模块加载器加载原理是怎么样的?

    路人一: 原理一:id即路径 原则.通常我们的入口是这样的: require( [ 'a', 'b' ], callback ) .这里的 'a'.'b' 都是 ModuleId.通过 id 和路径的 ...

随机推荐

  1. session 重写进入redis测试

    在实际业务中,当session存储过多 或者操作频繁,业务逐渐扩展的时候,文件存储已经无法满足session操作速度和需求,可以考虑用数据库或者nosql的redis来存储session,本文讲解如何 ...

  2. JS单词形式的运算符

    1.void 运算表达式并忽略其返回值,比如void (1+2),void (0) <html> <head> <meta http-equiv="conten ...

  3. CentOS 6.5 下载地址

    CentOS 6.5 主要改动 Precision Time Protocol(精确时间协议)—— 原先是项技术预览 —— 现在已获全面支持.以下驱动程序支持网络时间戳印:bnx2x.tg3.e100 ...

  4. HadoopDB:混合分布式系统

    HadoopDB 是一个 Mapreduce 和传统关系型数据库的结合方案,以充分利用 RDBMS 的性能和 Hadoop 的容错.分布特性.2009 年被 Yale 大学教授 Abadi 提出,继而 ...

  5. 通过Wifi调试Android应用

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  6. 通过IP控制登录系统

    项目中有这么一个需求,就是系统仅仅能在指定ip下登录,能够理解为内部系统,仅仅能够在公司訪问 我的代码是这样写的:入不入流不知道,但能解决这个问题. 获得訪问IP代码: String ip = req ...

  7. [AngularJS + cryptoJS + Gravatar] Provider vs factory

    Configurable Bits Need a Provider We want to be able to configure the characterLength before Tweetab ...

  8. js上传文件获取客户端地址

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. android132 360 05 手机定位

    .网络定位:根据ip地址定位,根据ip地址在实际地址数据库中查询实际地址. 缺点:动态ip导致地址不准确. .基站定位:3个基站就可以确定实际位置,定位范围是几百米到几公里不等. .GPS定位:美国卫 ...

  10. 文件和目录之umask函数

    本篇博文内容摘自<UNIX环境高级编程>(第二版),仅作个人学习记录所用.关于本书可参考:http://www.apuebook.com/. umask函数为进程设置文件模式创建屏蔽字,并 ...