Node.JS
Node.js最佳实践(3)
前面两个章节介绍了Node的代码风格和开发流程上一些约定,遵循这些Node社区成熟经验模式,可以让你用Node.js支撑更加大型的应用系统开发,也会帮助你成为一个真正的Node.js高手。下面继续介绍这方面的最佳实践。
一致风格
前面章节推荐了:Javascript风格编程指南 ,当开发更大型的Javacript项目时,开发团队也比较大,这个时候最重要的是创建统一的大家都能接受的编码标准,但是这仅仅是第一步,在你们形成标准以后,你的团队所有成员还必须使用一致风格编写代码,这就引入了JSCS。
JSCS是一种Javascript的代码风格检查器,将JSCS增加到你的项目对于项目管理是有好处的:
npm install jscs --save-dev
下面一部是在package.json文件中激活它,这是通过增加下面定制脚本实现的:
scripts: {
"jscs": "jscs index.js"
}
当然你可以加入多个用来被检查的文件和目录,但是为什么我们要在package.json中增加定制脚本呢?我们安装jscs仅仅作为本地依赖,这样我们可以有一个应用系统的多个版本,这些会正常工作,因为NPM将把node_modules/.bin目录放入PATH路径中。
你能在.jscs文件中设置定制自己的校验规则,你能在这里here发现预设的样本,可以通过--preset=[PRESET_NAME]使用它们。
实施JSHint / JSCS规则
你可以将JSHint和JSCS链接起来,但是在开发者机器上运行pre-commit checks也许是个好主意:
非常容易使用pre-commit NPM包:
npm install --save-dev pre-commit
在你的package.json文件中配置它:
pre-commit": [
"jshint",
"jscs"
],
请注意,pre-commit将在你的package.json的脚本section段落寻找可执行的脚本,通过这样激活,每次在提交commit之前都会运行。
配置使用JS优先于JSON
通常我们看到大量项目使用JSON文件作为配置格式,但是JS文件提供更加灵活的实现,鼓励你使用config.js文件:
var url = require('url');
var config = module.exports = {};
var redisToGoConfig;
config.server = {
host: '0.0.0.0',
port: process.env.PORT || 3000
};
// look, a comment in the config file! // would be tricky in a JSON ;)
config.redis = {
host: 'localhost',
port: 6379,
options: {
}
};
if (process.env.REDISTOGO_URL) {
redisToGoConfig = url.parse(process.env.REDISTOGO_URL);
config.redis.port = redisToGoConfig.port;
config.redis.host = redisToGoConfig.hostname;
config.redis.options.auth_pass = redisToGoConfig.auth.split(':')[1];
}
使用NODE_PATH
你是否碰到过如下情况:
var myModule = require('../../../../lib/myModule');
myModule.doSomething(function (err) {
});
当你碰到一个非常复杂的项目结构时,需要的模块非常多而混乱,为了解决这个问题有两个选择:
- 链接你的模块到node_modules目录
- 使用NODE_PATH
设置NODE_PATH
假设有如下项目目录:
这里我们不使用相对路径,而是使用NODE_PATH,指向lib目录,这是在package.json的start脚本中设置的,如下,然后通过npm start运行应用。
{
"name": "node_path",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "NODE_PATH=lib node index.js"
},
"author": "",
"license": "ISC"
}
假设lib/model/Car.js的内容是:
console.log('I am a Car!');
在index.js引用这个Car.js直接使用:
var Car = require('model/Car');
依赖注入
依赖注入是将一个或多个依赖注入或通过引用传递给需要的对象中,依赖注入对于测试是非常有帮助的,你能使用模拟对象注入到被测试的业务场景中,从而摆脱对数据库等生产环境的依赖进行测试。
假设User.js内容如下:
function userModel (options) {
var db;
if (!options.db) {
throw new Error('Options.db is required');
}
db = options.db;
return {
create: function (done) {
db.query('INSERT ...', done);
}
}
}
module.exports = userModel;
该User.js中对Db依赖,在生产环境我们可以加入真正的Db:
var db = require('db');
// do some init here, or connect
db.init();
var userModel = require('User')({
db: db
});
userModel.create(function (err, user) {
});
而在测试test.js中我们可以模拟一个Db的实现fakeDb:
var test = require('tape');
var userModel = require('User');
test('it creates a user with id', function (t) {
var user = {
id: 1
};
var fakeDb = {
query: function (done) {
done(null, user);
}
}
userModel({
db: fakeDb
}).create(function (err, user) {
t.equal(user.id, 1, 'User id should match');
t.end();
})
});
上面案例有两个不同db,在index.js中有真实的db,而在第二个是创建的fake,我们可以通过注入fake到模块中进行测试。