十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
nodejs的非核心模块(core module)加载主要使用的就是module.js。
10余年的松原网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。网络营销推广的优势是能够根据用户设备显示端的尺寸不同,自动调整松原建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。成都创新互联从事“松原网站设计”,“松原网站推广”以来,每个客户项目都认真落实执行。项目主模块(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(fileNamein 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 allmodules 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 + '
});' // 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.
博客地址:http://www.cnblogs.com/jasonxuli/