我正在使用NodeJS的ExpressJS Web框架。
使用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);
配置/ environment.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());
});
};
配置/ routes.js
module.exports = function(app) {
app.get('/', function(req, res) {
res.send('Hello world !');
});
};
我的代码效果很好,我认为目录的结构很漂亮。但是,代码必须进行调整,我不确定它是好还是漂亮。
使用我的目录结构并调整代码或只使用一个文件(app.js)会更好吗?
感谢您的建议!
答案 0 :(得分:155)
更新(2013-10-29):请参阅我的其他答案,其中包含JavaScript而不是CoffeeScript的热门需求以及样板github repo和详细的README详细说明我的最新建议关于这个话题。
<强>配置强>
你做得很好。我喜欢在顶级config.coffee
文件中设置我自己的config命名空间,并使用嵌套的命名空间。
#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}"
这对系统管理员编辑很友好。然后当我需要某些东西时,比如数据库连接信息,它就是
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降价文件放在你的git repo root用于github。
将一个带有semantic version号码的package.json文件放在你的git repo root中,用于NPM。
答案 1 :(得分:50)
以下是Peter Lyons的逐字回答,按照其他几个人的要求从Coffeescript移植到香草JS。彼得的答案很有能力,任何对我的答案投票的人都应该投票给他。
<强>配置强>
你做得很好。我喜欢在顶级config.js
文件中设置我自己的config命名空间,并使用嵌套的命名空间。
// 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}"
};
这对系统管理员编辑很友好。然后当我需要某些东西时,比如数据库连接信息,它就是
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降价文件放在你的git repo root用于github。
将一个带有semantic version号码的package.json文件放在你的git repo root中,用于NPM。
答案 2 :(得分:42)
我的问题是在2011年4月推出的,它很安静。在此期间,我可以改善使用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
文件的目标是引导expressjs应用程序。它加载配置模块,记录器模块,等待数据库连接,...,并运行快速服务器。
'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();
});
<强>路由/ 强>
routes目录有一个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);
};
每个路线模块独立。
答案 3 :(得分:18)
我喜欢使用全局“app”,而不是导出函数等
答案 4 :(得分:17)
我认为这是一个很好的方式。不仅限于表达,但我在github上看到了很多相同的node.js项目。他们取出配置参数+较小的模块(在某些情况下,每个URI)都被分解在不同的文件中。
我建议在github上通过特定于快递的项目来获得一个想法。 IMO你的方式是正确的。
答案 5 :(得分:14)
现在 2015年底,经过3年的开发和小型和大型项目。结论
不要做一个大型MVC,而是将其分开模块
因此...
<强>为什么吗
通常可以在一个模块(例如产品)上工作,您可以单独更改。
您可以重复使用模块
您可以分开测试
您可以分开更换
他们有明确的(稳定的)接口
- 最近,如果有多个开发人员在工作,模块分离有帮助
nodebootstrap项目与我的最终结构有类似的方法。 (github)
此结构如何?
答案 6 :(得分:7)
我认为将路由添加到配置是一种不错的方法。更好的结构可能是这样的:
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将包含你所有逻辑内的所有路径。
答案 7 :(得分:7)
我给MVC风格的文件夹结构请在下面找。
我们在大中型网络应用程序中使用了波纹管文件夹结构。
myapp
|
|
|____app
| |____controllers
| | |____home.js
| |
| |____models
| | |___home.js
| |
| |____views
| |___404.ejs
| |___error.ejs
| |___index.ejs
| |___login.ejs
| |___signup.ejs
|
|
|_____config
| |___auth.js
| |___constants.js
| |___database.js
| |___passport.js
| |___routes.js
|
|
|____lib
| |___email.js
|
|____node_modules
|
|
|____public.js
| |____css
| | |__style.css
| |
| |____js
| | |__script.js
| |
| |____img
| | |__img.jpg
| |
| |
| |____uploads
| |__img.jpg
|
|
|
|_____app.js
|
|
|
|_____package.json
我为generation express mvc文件夹结构创建了一个npm模块。
请找到下面的https://www.npmjs.com/package/express-mvc-generator
生成和使用此模块的简单步骤。
i)安装模块npm install express-mvc-generator -g
ii)检查选项express -h
iii)生成明确的mvc结构express myapp
iv)安装依赖项:npm install
:
v)打开你的config / database.js,请配置你的mongo db。
vi)运行应用程序node app
或nodemon app
vii)检查网址http://localhost:8042/signup或http://yourip:8042/signup
答案 8 :(得分:7)
自问题的最后一个答案以来已经有一段时间了,Express最近还发布了第4版,它为组织应用程序结构添加了一些有用的东西。
以下是一篇关于如何构建Express应用程序的最佳实践的最新博客文章。 http://www.terlici.com/2014/08/25/best-practices-express-structure.html
还有一个GitHub存储库应用了本文中的建议。它始终与最新的Express版本保持同步 https://github.com/terlici/base-express
答案 9 :(得分:6)
好吧,我将我的路由作为json文件,我在开头读取,并在app.js中的for循环中设置路由。 route.json包括应该调用的视图,以及将发送到路由中的值的键 这适用于许多简单的情况,但我必须为特殊情况手动创建一些路径。
答案 10 :(得分:6)
我已经写了一篇关于此事的文章。它基本上使用routeRegistrar
来遍历调用其函数/controllers
的文件夹init
中的文件。函数init
将快速app
变量作为参数,以便您可以按照自己的方式注册路线。
var fs = require("fs");
var express = require("express");
var app = express();
var controllersFolderPath = __dirname + "/controllers/";
fs.readdirSync(controllersFolderPath).forEach(function(controllerName){
if(controllerName.indexOf("Controller.js") !== -1){
var controller = require(controllersFolderPath + controllerName);
controller.init(app);
}
});
app.listen(3000);
答案 11 :(得分:5)
答案 12 :(得分:4)
http://locomotivejs.org/提供了一种构建使用Node.js和Express构建的应用程序的方法。
来自网站:
&#34;机车是Node.js的Web框架。机车支持MVC 模式,RESTful路由和约定优于配置 与任何数据库和模板引擎无缝集成。 机车以Express为基础,保留了动力和简洁性 你对Node有所期待。&#34;
答案 13 :(得分:4)
1)您的Express项目文件系统可能如下:
/ ...
/lib
/node_modules
/public
/views
app.js
config.json
package.json
app.js - 您是全球应用容器
2)模块主文件(lib / mymodule / index.js):
var express = require('express');
var app = module.exports = express();
// and load module dependencies ...
// this place to set module settings
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');
// then do module staff
app.get('/mymodule/route/',function(req,res){ res.send('module works!') });
3)在主app.js中连接模块
...
var mymodule = require('mymodule');
app.use(mymodule);
4)示例逻辑
lib/login
lib/db
lib/config
lib/users
lib/verify
lib/
/api/
...
lib/
/admin/
/users/
/settings/
/groups/
...
tj说/在Vimeo上展示有趣的想法如何模块化表达应用 - Modular web applications with Node.js and Express。功能强大而简单。
答案 14 :(得分:2)
我最近将模块视为独立的迷你应用程序。
|-- src
|--module1
|--module2
|--www
|--img
|--js
|--css
|--#.js
|--index.ejs
|--module3
|--www
|--bower_components
|--img
|--js
|--css
|--#.js
|--header.ejs
|--index.ejs
|--footer.ejs
现在,对于任何模块路由(#.js),视图(* .ejs),js,css和资产彼此相邻。 子模块路由在父#Riz中设置,并带有两行额外的行
router.use('/module2', opt_middleware_check, require('./module2/#'));
router.use(express.static(path.join(__dirname, 'www')));
这样甚至可以使用子子模块。
不要忘记将视图设置为src目录
app.set('views', path.join(__dirname, 'src'));
答案 15 :(得分:1)
这就是我的大部分快递项目目录结构的外观。
我通常做一个express dirname
初始化项目,原谅我的懒惰,但它非常灵活和可扩展。 PS - 你需要获得express-generator
(对于那些正在寻找它的人sudo npm install -g express-generator
,sudo因为你在全球安装它)
|-- bin
|-- www //what we start with "forever"
|-- bower_components
|-- models
|-- database.js
|-- model1.js //not this exact name ofcourse.
|-- .
|-- node_modules
|-- public
|-- images
|-- javascripts
|-- controllers
|-- directives
|-- services
|-- app.js
|-- init.js //contains config and used for initializing everything, I work with angular a lot.
|-- stylesheets
|-- routes
|-- some
|-- hierarchy
.
.
|-- views
|-- partials
|-- content
|-- .env
|-- .env.template
|-- app.js
|-- README.md
你一定想知道为什么.env文件?因为他们工作!我在我的项目中使用dotenv
模块(最近很多)并且它有效!在app.js
或www
var dotenv = require('dotenv');
dotenv.config({path: path.join(__dirname + "/.env")});
另一行快速设置/bower_components
以在资源/ext
下提供静态内容
app.use('/ext', express.static(path.join(__dirname, 'bower_components')));
它可能适合那些希望一起使用Express和Angular的人,或者只是在没有javascripts
层次结构的情况下表达。
答案 16 :(得分:1)
我的结构表达4。 https://github.com/odirleiborgert/borgert-express-boilerplate
<强>包强>
View engine: twig
Security: helmet
Flash: express-flash
Session: express-session
Encrypt: bcryptjs
Modules: express-load
Database: MongoDB
ORM: Mongoose
Mongoose Paginate
Mongoose Validator
Logs: winston + winston-daily-rotate-file
Nodemon
CSS: stylus
Eslint + Husky
<强>结构强>
|-- app
|-- controllers
|-- helpers
|-- middlewares
|-- models
|-- routes
|-- services
|-- bin
|-- logs
|-- node_modules
|-- public
|-- components
|-- images
|-- javascripts
|-- stylesheets
|-- views
|-- .env
|-- .env-example
|-- app.js
|-- README.md
答案 17 :(得分:1)
Sails.js结构对我来说看起来很干净整洁,所以我在快递项目中使用MVC样式结构,类似于sails.js。
project_root
|
|_ _ app
|_ _ |_ _ controllers
|_ _ |_ _ |_ _ UserController.js
|_ _ |_ _ middlewares
|_ _ |_ _ |_ _ error.js
|_ _ |_ _ |_ _ logger.js
|_ _ |_ _ models
|_ _ |_ _ |_ _ User.js
|_ _ |_ _ services
|_ _ |_ _ |_ _ DatabaseService.js
|
|_ _ config
|_ _ |_ _ constants.js
|_ _ |_ _ index.js
|_ _ |_ _ routes.js
|
|_ _ public
|_ _ |_ _ css
|_ _ |_ _ images
|_ _ |_ _ js
|
|_ _ views
|_ _ |_ _ user
|_ _ |_ _ |_ _ index.ejs
应用文件夹-包含应用的整体登录信息。
配置文件夹-包含应用配置,常量,路由。
公共文件夹-包含样式,图像,脚本等。
视图文件夹-包含每种模型的视图(如果有)
样板项目可以在这里找到,
https://github.com/abdulmoiz251/node-express-rest-api-boilerplate
答案 18 :(得分:0)
构建ur express应用的简单方法:
在main index.js中,应保持以下顺序。
所有 app.set 应该是第一个。
所有 app.use 应该排第二。
其他api及其功能或在其他文件中继续路由
示例
app.use(“ / password”,passwordApi);
app.use(“ / user”,userApi);
app.post(“ / token”,护照.createToken);
app.post(“ /登出”,护照。登出)
答案 19 :(得分:0)
使用车把和Passportjs的ExpressJs项目的MVC结构的最佳方法
>>>"War" in "Love is War"
true
>>>"War" in "LoveIsWar"
true
>>>"Warfalse" in "Love is War"
false