Node.js动态读取模块
动态读取模块解决了什么问题?
以下是截取cnodejs社区源码的片段
https://github.com/cnodejs/nodeclub/blob/master/web_router.js
var sign = require('./controllers/sign');
var site = require('./controllers/site');
var user = require('./controllers/user');
var message = require('./controllers/message');
var topic = require('./controllers/topic');
var reply = require('./controllers/reply');
var rss = require('./controllers/rss');
var staticController = require('./controllers/static');
var auth = require('./middlewares/auth');
var limit = require('./middlewares/limit');
var github = require('./controllers/github');
var search = require('./controllers/search');
topic
,user
和reply
都是controller下的路由函数,当我们需要创建多一个路由函数的时候,开发者总是需要require多一个模块进来,当路由的规模越来越大的时候,文件里面,总会有十几行路由引用,在本人看来,这是非常糟糕的开发体验,那么有没有一种方法,可以按需加载,我们需要什么东西就引用什么,不用主动去require进来。好吧,不傲娇了,本文正是为了解决问题。
先看看本文的最终解法
load_dir.js
var fs = require('fs');
var path = require('path');
var load = function(path, name) {
if (name) {
return require(path + name);
}
return require(path)
};
module.exports = function (dir) {
patcher = {}
fs.readdirSync(__dirname + '/' + dir).forEach(function (filename) {
if (!/\.js$/.test(filename)) {
return;
}
var name = path.basename(filename, '.js');
var _load = load.bind(null, './' + dir + '/', name);
patcher.__defineGetter__(name, _load);
});
return patcher;
module/a.js
module.exports = function () {
console.log('module a');
}
module/b.js
module.exports = function () {
console.log('module a');
}
index.js
module.exports = function () {
console.log('module b');
}
var loadDir = require('./load_dir');
var Module = loadDir('module');
Module.a(); // print module a
Module.b(); // print module b
在上述代码当中,可以看到通过loadDir
函数导出的Module
,Module
可以动态读取module文件夹下的js模块,只要通过Module.a() 或者 Module.b()就可以方便进行调用,因此loadDir
函数是实现动态读取模块的关键。
loadDir的实现细节
读取指定目录下的js文件,并将js文件通过node.js的require方法进行导入,并存放在patcher
变量下,利用__defineGetter__
方法重新定义了了patcher
的getter方法,当我们patcher.xx的时候,就会调用require的方法,动态读取对应目录下的模块。
应用动态读取模块倒cnodejs社区源码
var loadDir = require('./load_dir');
var Router = loadDir('router');
router.post('/signout', Router.sign.signout);
代码是不是已经变得 更加好维护了。
最后,出了路由可以使用动态加载外,moogose的模型也可以,只要你想动态加载的模块,通通都可以这样处理,是不是觉得很方便,如果还是不是很了解的同学,可以参考我的示例项目。
https://github.com/youyudehexie/nodejs-cookbook/tree/master/dynamic_module