node.js - expressj如何架构一个应用程序?

  显示原文与译文双语对照的内容

我正在使用 ExpressJS web框架进行 NodeJS 。

使用ExpressJS的人将他们的环境设置为( 开发,生产,测试。。),他们的路由。。 在 app.js. 上,我认为这不是一个很好的方法,因为当你有一个大的应用程序时,app.js 太大了 !

我想要这个结构目录:


| my-application
| -- app.js
| -- config/
 | -- environment.js
 | -- routes.js

我的代码如下:

app.js


var express = require('express');
var app = module.exports = express.createServer();

require('./config/environment.js')(app, express);
require('./config/routes.js')(app);

app.listen(3000);

的配置/环境。js


module.exports = function(app, express){
 app.configure(function() {
 app.use(express.logger());
 });

 app.configure('development', function() {
 app.use(express.errorHandler({
 dumpExceptions: true,
 showStack: true
 }));
 });

 app.configure('production', function() {
 app.use(express.errorHandler());
 });
};

的配置/路由。js


module.exports = function(app) {
 app.get('/', function(req, res) {
 res.send('Hello world!');
 });
};

我的代码工作正常,我认为目录的结构很漂亮。 但是,代码必须调整,我不确定它是好还是漂亮。

最好使用我的目录结构和修改代码,还是只使用一个文件( app.js )?

感谢你的建议 !

时间:

更新( 2013-10-29 ): 在这里topic,请参考我其他回答也它具有JavaScript而不是CoffeeScript通过广泛的需求以及有样板gitub回购和广泛的自述文件显示了我的最新 recommendations.

配置

你做的很好。 我喜欢在 top-level config.coffee 文件中设置自己的配置名称空间,这样嵌套的命名空间如下。


#Set the current environment to true in the env object
currentEnv = process.env.NODE_ENV or 'development'
exports.appName ="MyApp"
exports.env =
 production: false
 staging: false
 test: false
 development: false
exports.env[currentEnv] = true
exports.log =
 path: __dirname +"/var/log/app_#{currentEnv}.log"
exports.server =
 port: 9600
 #In staging and production, listen loopback. nginx listens on the network.
 ip: '127.0.0.1'
if currentEnv not in ['production', 'staging']
 exports.enableTests = true
 #Listen on all IPs in dev/test (for testing from other machines)
 exports.server.ip = '0.0.0.0'
exports.db =
 URL:"mongodb://localhost:27017/#{exports.appName.toLowerCase()}_#{currentEnv}"

这对系统管理员编辑很友好。 然后当我需要一些东西,比如数据库连接信息,it`s


require('./config').db.URL

径/控制器

我喜欢在我的控制器上留下我的路由,并在 app/controllers 子目录中组织它们。 然后我可以加载它们,让他们添加他们需要的任何路由。

在我的app/server.coffee coffeescript文件中:


[
 'api'
 'authorization'
 'authentication'
 'domains'
 'users'
 'stylesheets'
 'javascripts'
 'tests'
 'sales'
].map (controllerName) ->
 controller = require './controllers/' + controllerName
 controller.setup app

所以我有这样的文件:


app/controllers/api.coffee
app/controllers/authorization.coffee
app/controllers/authentication.coffee
app/controllers/domains.coffee

在我的域控制器中,我有一个 setup 函数,如下所示。


exports.setup = (app) ->
 controller = new exports.DomainController
 route = '/domains'
 app.post route, controller.create
 app.put route, api.needId
 app.delete route, api.needId
 route = '/domains/:id'
 app.put route, controller.loadDomain, controller.update
 app.del route, controller.loadDomain, exports.delete
 app.get route, controller.loadDomain, (req, res) ->
 res.sendJSON req.domain, status.OK

英镑视图

app/views 中放置视图正成为习惯的地方。 我把它像这样。


app/views/layout.jade
app/views/about.jade
app/views/user/EditUser.jade
app/views/domain/EditDomain.jade

静态文件

进入 public 子目录。

Github/Semver/NPM

将 README.md Markdown 文件放置在你的git仓库根目录中。

将 package.json 文件和语义版本的文件放在你的git仓库根目录中。

在Coffeescript中,按照你的要求通过几个莱昂斯others,以下是彼得则'回答逐字,移植到其他总线香草 js. peter的回答非常强大,任何在我的答案上投票的人都应该在他的his上投票。


配置

你所做的一切都很好。 我喜欢在 top-level config.js 文件中设置自己的配置命名空间,该名称空间类似于。


//Set the current environment to true in the env object
var currentEnv = process.env.NODE_ENV || 'development';
exports.appName ="MyApp";
exports.env = {
 production: false,
 staging: false,
 test: false,
 development: false
}; 
exports.env[currentEnv] = true;
exports.log = {
 path: __dirname +"/var/log/app_#{currentEnv}.log"
}; 
exports.server = {
 port: 9600,
//In staging and production, listen loopback. nginx listens on the network.
 ip: '127.0.0.1'
}; 
if (currentEnv!= 'production' && currentEnv!= 'staging') {
 exports.enableTests = true;
//Listen on all IPs in dev/test (for testing from other machines)
 exports.server.ip = '0.0.0.0';
};
exports.db {
 URL:"mongodb://localhost:27017/#{exports.appName.toLowerCase()}_#{currentEnv}"
};

这对系统管理员编辑很友好。 然后,当我需要一些东西,比如数据库连接信息,it`s


require('./config').db.URL

径/控制器

我喜欢在控制器中留下我的路由,并在 app/controllers 子目录中组织它们。 然后我可以加载它们,让他们添加他们需要的任何路由。

在我的app/server.js javascript文件中,我执行了以下操作:


[
 'api',
 'authorization',
 'authentication',
 'domains',
 'users',
 'stylesheets',
 'javascripts',
 'tests',
 'sales'
].map(function(controllerName){
 var controller = require('./controllers/' + controllerName);
 controller.setup(app);
});

所以我有这样的文件:


app/controllers/api.js
app/controllers/authorization.js
app/controllers/authentication.js
app/controllers/domains.js

在我的域控制器中,我有一个 setup 函数,如下所示。


exports.setup = function(app) {
 var controller = new exports.DomainController();
 var route = '/domains';
 app.post(route, controller.create);
 app.put(route, api.needId);
 app.delete(route, api.needId);
 route = '/domains/:id';
 app.put(route, controller.loadDomain, controller.update);
 app.del(route, controller.loadDomain, function(req, res){
 res.sendJSON(req.domain, status.OK);
 });
}

英镑视图

app/views 中放置视图正成为习惯的地方。 我把它像这样。


app/views/layout.jade
app/views/about.jade
app/views/user/EditUser.jade
app/views/domain/EditDomain.jade

静态文件

进入 public 子目录。

Github/Semver/NPM

将 README.md Markdown 文件放置在你的git仓库根目录中。

在你的git回购根对于npm,投入了 package.json 文件的一语义版本号码。

我的问题是在 2011年04月 中引入的,它是安静的。 在此期间,我可以改进我的Express.js 体验,以及如何使用这个库编写一个应用程序。 我在这里分享我的经验。

以下是我的目录结构:


├── app.js//main entry
├── config//The configuration of my applications (logger, global config,.. .)
├── models//The model data (e.g. Mongoose model)
├── public//The public directory (client-side code)
├── routes//The route definitions and implementations
├── services//The standalone services (Database service, Email service,.. .)
└── views//The view rendered by the server to the client (e.g. Jade, EJS,.. .)

app.js

app.js 文件的目标是 Bootstrap 应用程序。 它加载配置模块,日志模块,等待数据库连接。 ,并运行express服务器。


'use strict';
require('./config');
var database = require('./services/database');
var express = require('express');
var app = express();
module.exports = app;

function main() {
 var http = require('http');

//Configure the application.
 app.configure(function () {
//..... ... .
 });
 app.configure('production', function () {
//..... ... .
 });
 app.configure('development', function () {
//..... ... .
 });

 var server = http.createServer(app);

//Load all routes.
 require('./routes')(app);

//Listen on http port.
 server.listen(3000);
}

database.connect(function (err) {
 if (err) { 
//...
 }
 main();
});

英镑径/

路由目录有一个 index.js 文件。 它的目标是引入一个魔术来加载 routes/ 目录中的所有其他文件。 下面是实现:


/**
 * This module loads dynamically all routes modules located in the routes/
 * directory.
 */
'use strict';
var fs = require('fs');
var path = require('path');

module.exports = function (app) {
 fs.readdirSync('./routes').forEach(function (file) {
//Avoid to read this current file.
 if (file === path.basename(__filename)) { return; }

//Load the route file.
 require('./' + file)(app);
 });
};

使用这个模块,创建一个新的路由定义和实现非常简单。 例如 hello.js:


function hello(req, res) {
 res.send('Hello world');
}

module.exports = function (app) {
 app.get('/api/hello_world', hello);
};

每个路由模块都是独立的。

我不认为将路由添加到配置是一个好方法。 更好的结构可以是 smth:


application/
| - app.js
| - config.js
| - public/(assets - js, css, images)
| - views/(all your views files)
| - libraries/(you can also call it modules/or routes/)
 | - users.js
 | - products.js
 | - etc...

所以 products.js 和 users.js 将包含所有的路由,所有的逻辑都将在。

...