首页 文章

ExpressJS如何构建应用程序?

提问于
浏览
475

我正在使用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);

config/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());
    });
};

config/routes.js

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

我的代码运行良好,我认为目录的结构很漂亮 . 但是,代码必须进行调整,我不确定它是好还是漂亮 .

使用我的目录结构并调整代码或只使用一个文件(app.js)更好吗?

谢谢你的建议!

19 回答

  • 4

    UPDATE (2013-10-29) :请查看我的其他答案,其中包括JavaScript而非CoffeeScript受欢迎的需求以及样板github repo和详细的README详细说明了我对此主题的最新建议 .

    Config

    你做的很好 . 我喜欢在顶级 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}"
    

    这对系统管理员编辑很友好 . 然后当我需要某些东西时,比如DB连接信息,它就是

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

    Routes/Controllers

    我喜欢将我的路由留给我的控制器并将它们组织在 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
    

    Views

    app/views 中提出意见正在成为惯例 . 我把它像这样摆好 .

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

    Static Files

    进入 public 子目录 .

    Github/Semver/NPM

    在您的git repo root上放置一个README.md markdown文件,用于github .

    将一个带有semantic version数字的package.json文件放在你的git repo root中,用于NPM .

  • 14

    我给MVC风格的文件夹结构请找下面 .

    我们在大中型Web应用程序中使用了bellow文件夹结构 .

    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模块 .

    请找到下面的 Headers 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 appnodemon app

    vii)检查URL http://localhost:8042/signuphttp://yourip:8042/signup

  • 2

    这就是我的快递项目目录结构的大部分内容 .

    我通常做一个 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.jswww 中的这2个语句

    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 层次结构的情况下表达 .

  • 50

    我喜欢使用全局“app”,而不是导出函数等

  • 1

    我已经写了一篇关于此事的文章 . 它基本上使用了一个 routeRegistrar ,它遍历文件夹 /controllers 中的文件,调用它的函数 init . 函数 init 将express 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);
    
  • 5

    http://locomotivejs.org/提供了一种构建使用Node.js和Express构建的应用程序的方法 .

    来自网站:

    “Locomotive是Node.js的Web框架.Lotomotive支持MVC模式,RESTful路由和约定优于配置,同时与任何数据库和模板引擎无缝集成 . 机车以Express为基础,保留了您所拥有的强大功能和简单性期待Node . “

  • 41

    好的,已经有一段时间了,这是一个很受欢迎的问题,所以我继续创建了一个脚手架github存储库,其中包含JavaScript代码和一个关于我如何构建一个中型express.js应用程序的长README文件 .

    focusaurus/express_code_structure是具有最新代码的repo . 拉请求欢迎 .

    这是README的快照,因为stackoverflow不喜欢只是一个链接的答案 . 我将进行一些更新,因为这是一个我将继续更新的新项目,但最终github repo将成为此信息的最新位置 .


    快速代码结构

    该项目是如何组织中型express.js Web应用程序的示例 .

    Current to at least express v4.14 December 2016

    Build Status

    js-standard-style

    您的申请有多大?

    Web应用程序并不完全相同,在我看来,并不是单一的代码结构适用于所有express.js应用程序 .

    如果您的应用程序很小,则不需要这样的深层目录结构 . 只需保持简单,并在存储库的根目录中粘贴少量 .js 文件即可 . 瞧 .

    如果您的应用程序很大,那么在某些时候您需要将其分解为不同的npm包 . 一般来说,node.js方法似乎有利于许多小包,至少对于库而言,你应该使用几个npm包来构建你的应用程序,因为这开始有意义并证明开销是合理的 . 因此,当您的应用程序增长并且某些部分代码在应用程序之外变得清晰可重用或者是一个清晰的子系统时,将其移动到它自己的git存储库并将其转换为独立的npm包 .

    So 该项目的重点是说明中型应用程序的可行结构 .

    您的整体架构是什么?

    构建Web应用程序有很多方法,例如

    • 服务器端MVC和Ruby on Rails

    • 单页应用程序样式a MongoDB / Express / Angular / Node(MEAN)

    • 包含某些表单的基本网站

    • 型号/操作/视图/事件样式a la MVC is dead, it's time to MOVE on

    • 和其他许多当前和历史

    每个都很适合不同的目录结构 . 出于这个例子的目的,它只是脚手架而不是一个完全正常工作的应用程序,但我假设以下关键架构点:

    • 该网站有一些传统的静态页面/模板

    • 网站的"application"部分是作为单页应用程序样式开发的

    • 该应用程序向浏览器公开REST / JSON样式API

    • 该应用程序为一个简单的业务领域建模,在这种情况下,它是一个汽车经销商应用程序

    那么Ruby on Rails呢?

    这将是整个项目的一个主题,Ruby on Rails中体现的许多想法和他们采用的“约定优于配置”决策虽然被广泛接受和使用,但实际上并不是非常有用,有时与此存储库相反 . 建议 .

    我的主要观点是组织代码有基本原则,并且基于这些原则,Ruby on Rails约定(大多数)对Ruby on Rails社区有意义 . 然而,只是轻率地嘲笑那些惯例,忽略了这一点 . 一旦了解了基本原则,您的所有项目都将得到良好的组织和清晰:shell脚本,游戏,移动应用程序,企业项目,甚至是您的主目录 .

    对于Rails社区,他们希望能够有一个Rails开发人员从应用程序到应用程序切换到应用程序,并且每次都熟悉并熟悉它 . 如果您是37个信号或Pivotal Labs,这很有意义,并且有益处 . 在服务器端的JavaScript世界中,整体的风格是西方任何事情都变得越来越狂野,我们不知道如何滚动 . 我们're used to it. Even within express.js, it'是Sinatra的近亲,而不是Rails,从Rails获取约定通常没有任何帮助 . 我甚至会说 Principles over Convention over Configuration .

    基本原则和动机

    • 精神上可以管理

    • 大脑只能同时处理和思考少量相关事物 . 这就是我们使用目录的原因 . 它通过专注于小部分来帮助我们处理复杂性 .

    • 尺寸合适

    • Don 't create 437013 where there'只有1个文件,单独3个目录 . 您可以在Ansible Best Practices中看到这种情况,这会使小项目变得羞耻,创建10个目录以容纳10个文件,当1个目录中包含3个文件时更合适 . 你不是一个 Bus 车司机,但即使这样,你开着公共汽车去工作也不能工作),所以不要用他们里面的实际文件来证明这一点 .

    • 模块化但务实

    • 节点社区总体上支持小模块 . 任何可以完全从您的应用程序中分离出来的东西都应该提取到模块中供内部使用或在npm上公开发布 . 但是,对于此处作为范围的中型应用程序,此开销会增加您的工作流程,而不会产生相应的 Value . 因此,当你有一些代理被分解但不足以证明一个完全独立的npm模块的时候,只需将其视为“ proto-module ”,期望当它超过某个大小阈值时,它将被提取出来 .

    • 某些人如@hij1nx甚至包含一个 app/node_modules 目录,并在 proto-module 目录中有 package.json 个文件,以方便转换并作为提醒 .

    • 易于查找代码

    • 鉴于要构建的功能或要修复的错误,我们的目标是开发人员无需查找所涉及的源文件 .

    • 名称有意义且准确

    • crufty代码已完全删除,不会留在孤立文件中或只是注释掉

    • 对搜索友好

    • 所有第一方源代码都在 app 目录中,因此您可以在那里 cd 运行find / grep / xargs / ag / ack / etc,不要被第三方比赛分心

    • 使用简单明了的命名

    • npm现在似乎需要全小写的包名 . 我觉得这很可怕但是我必须跟随牛群,因此文件名应该使用 kebab-case ,即使JavaScript中的变量名必须是 camelCase ,因为 - 是JavaScript中的减号 .

    • 变量名称与模块路径的基本名称匹配,但 kebab-case 变换为 camelCase

    • 按耦合分组,而不是按功能分组

    • 这是与 app/viewsapp/controllersapp/models 等Ruby on Rails约定的主要背离

    • 功能被添加到完整堆栈,因此我想专注于与我的功能相关的完整堆栈文件 . 当我关心除用户控制器以外的任何控制器时,我不关心除用户模型之外的任何模型 .

    • 因此,不是编辑各自位于其自己目录中的6个文件而忽略这些目录中的大量其他文件,而是对此存储库进行组织,以便构建要素所需的所有文件都被共同定位
      _999_根据MVC的性质,用户视图耦合到耦合到用户模型的用户控制器 . 因此,当我更改用户模型时,这3个文件通常会一起更改,但交易控制器或客户控制器会解耦,因此不会涉及 . 通常也适用于非MVC设计 .

    • MVC或MOVE样式在哪些代码仍在鼓励哪个模块中进行解耦,但将MVC文件传播到兄弟目录中只是令人讨厌 .

    • 因此,我的每个路径文件都拥有它拥有的路径部分 . 如果您想要了解应用程序中所有路径的概述,那么rails样式的 routes.rb 文件很方便,但是在实际构建功能和修复错误时,您只关心与您正在更改的部分相关的路径 .

    • 在代码旁边存储测试

    • 这只是"group by coupling"的一个实例,但我想特别说出来 . 我已经开始将我的测试放在与其相应代码相同的目录中,我不会做任何事情来说服你,说服它更好 .

    • 减少与事件的交叉耦合

    • 很容易想到"OK, whenever a new Deal is created, I want to send an email to all the Salespeople",然后只是把代码发送到创建交易的路线中的那些电子邮件 .

    • 然而,这种耦合最终会将你的应用变成一个巨大的泥球 .

    • 相反,DealModel应该只触发"create"事件并且完全不知道系统可能做出的其他事情 .

    • 当您以这种方式编码时,将所有与用户相关的代码放入 app/users 变得更加可能,因为整个地方都有's not a rat'嵌套的业务逻辑嵌套污染了用户代码库的纯度 .

    • 代码流程可以跟随

    • Don 't do magic things. Don' t来自文件系统中魔术目录的自动加载文件 . 不要是Rails . 该应用程序从 app/server.js:1 开始,您可以按照代码查看它加载并执行的所有内容 .

    • 唐't make DSLs for your routes. Don'在没有被要求时做愚蠢的元编程 .

    • 如果你的应用程序如此之大,以至于对于超过3个基本的 app.getapp.putapp.del 来说,做 magicRESTRouter.route(somecontroller, {except: 'POST'}) 是一个很大的胜利,你可能正在构建一个太大而无法有效工作的单片应用程序 . 想要获得BIG胜利,而不是将3条简单线路转换为1条复杂线路 .

    • 使用lower-kebab-case文件名

    • 此格式可避免跨平台的文件系统区分大小写问题

    • npm禁止使用新包名称中的大写字母,这样做效果很好

    express.js具体细节

    • 不要使用 app.configure . 它's almost entirely useless and you just don'需要它 . 由于无意识的copypasta,它有很多样板 .

    • 快递事项中的中间件和路线的顺序!!!

    • 我在stackoverflow上看到的几乎每个路由问题都是无序的快速中间件

    • 一般情况下,您希望您的路线分离,而不是依赖订单那么多

    • 如果您真的只需要2条路线的中间件,请不要将 app.use 用于整个应用程序(我正在看着你, body-parser

    • 确保完成所有操作后,您确实已完成此订单:

    • 任何超级重要的应用程序范围的中间件

    • 所有路线和各种路线中间件

    • 那么错误处理程序

    • 可悲的是,受到sinatra的启发,express.js主要假设你所有的路线都在 server.js ,并且很清楚它们是如何订购的 . 对于中型应用程序,将事物分解为单独的路径模块是很好的,但它确实引入了无序中间件的危险

    app符号链接技巧

    社区在伟大的要点Better local require() paths for Node.js中详细介绍和讨论了许多方法 . 我可能很快就会选择"just deal with lots of ../../../.."或使用requireFrom modlue . 但是,目前,我一直在使用下面详述的符号链接技巧 .

    因此,一种避免项目内需求的方法与令人讨厌的相对路径如 require("../../../config") 是使用以下技巧:

    • 为您的应用在node_modules下创建符号链接

    • cd node_modules && ln -nsf ../app

    • just the node_modules/app symlink itself ,而不是整个node_modules文件夹添加到git

    • git add -f node_modules / app

    • 是的,你的 .gitignore 文件中仍然应该有"node_modules"

    • 不,你不应该将"node_modules"放入你的git仓库 . 有些人会建议你这样做 . 他们是不正确的 .

    • 现在您可以使用此前缀来要求项目内模块

    • var config = require("app/config");

    • var DealModel = require("app/deals/deal-model") ;

    • 基本上,这使得项目内部需要的工作与外部npm模块的需求非常相似 .

    • 抱歉,对于Windows用户,您需要坚持使用父目录相对路径 .

    配置

    通常代码模块和类只需要传入基本的JavaScript options 对象 . 只有 app/server.js 才能加载 app/config.js 模块 . 从那里它可以合成小的 options 对象来根据需要配置子系统,但是将每个子系统耦合到一个充满额外信息的大型全局配置模块是错误的耦合 .

    尝试集中创建数据库连接并将其传递到子系统,而不是传递连接参数并让子系统自己进行传出连接 .

    NODE_ENV

    这是Rails带来的又一个诱人而又可怕的想法 . 您的应用中应该只有一个地方 app/config.js ,它会查看 NODE_ENV 环境变量 . 其他所有内容都应该作为类构造函数参数或模块配置参数使用显式选项 .

    如果电子邮件模块有关于如何传递电子邮件的选项(SMTP,登录到stdout,放入队列等),它应该采用像 {deliver: 'stdout'} 这样的选项,但它绝对不应该检查 NODE_ENV .

    测试

    我现在将我的测试文件保存在与其相应代码相同的目录中,并使用文件扩展名命名约定来区分测试和 生产环境 代码 .

    • foo.js 有模块"foo"的代码

    • foo.tape.js 具有基于节点的foo测试并且位于同一个目录中

    • foo.btape.js 可用于需要在浏览器环境中执行的测试

    我使用filesystem globs和 find . -name '*.tape.js' 命令来根据需要访问我的所有测试 .

    如何在每个.js模块文件中组织代码

    这个项目的范围主要是关于文件和目录的位置,我不想添加很多其他范围,但我只是提到我将代码组织成3个不同的部分 .

    • CommonJS的开放块需要调用状态依赖项

    • 纯JavaScript的主要代码块 . 这里没有CommonJS污染 . 不要引用导出,模块或要求 .

    • 关闭CommonJS块以设置导出

  • 6

    这可能是有意义的:

    https://github.com/flatiron/nconf

    具有文件,环境变量,命令行参数和原子对象合并的分层node.js配置 .

  • 266

    我不认为将路由添加到配置是一个好方法 . 更好的结构可能是这样的:

    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将包含所有逻辑内的所有逻辑 .

  • 154

    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 . 功能强大而简单 .

  • 5

    现在是 End of 2015 ,经过3年的发展和小型和大型项目 . 结论?

    Do not do one large MVC, but separate it in modules

    所以...

    Why?

    • 通常可以在一个模块(例如产品)上工作,您可以单独更改 .

    • 您可以重用模块

    • 您可以分开测试它

    • 您可以分开更换它

    • 他们有清晰(稳定)的接口

    • 最新的,如果有多个开发人员在工作,模块分离会有所帮助

    nodebootstrap项目与我的最终结构有类似的方法 . (github

    How does this structure look like?

    • Small, capsulated modules ,每个都有单独的MVC

    • Each module 有一个package.json

    • Testing 作为结构的一部分(在每个模块中)

    • Global configuration ,图书馆和服务

    • 集成Docker,集群,永远

    Folderoverview(参见模块的lib文件夹):

    nodebootstrap structure

  • 17

    以下是Peter Lyons的回答,按照其他几个人的要求从Coffeescript移植到香草JS . 彼得的答案很有能力,任何对我的答案投票的人都应该投票给他 .


    Config

    你做的很好 . 我喜欢在顶级 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}"
    };
    

    这对系统管理员编辑很友好 . 然后,当我需要一些东西,比如DB连接信息,它的

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

    Routes/Controllers

    我喜欢用我的控制器留下我的路线并将它们组织在一个 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);
      });
    }
    

    Views

    将观点放在 app/views 正在成为习惯的地方 . 我把它像这样摆好 .

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

    Static Files

    进入 public 子目录 .

    Github/Semver/NPM

    在您的git repo root上放置一个README.md markdown文件,用于github .

    将一个带有semantic version数字的package.json文件放在你的git repo root中,用于NPM .

  • 1

    我最近将模块视为独立的迷你应用程序 .

    |-- 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和资产彼此相邻 . 子模块路由在父 . #js中设置,另外两行

    router.use('/module2', opt_middleware_check, require('./module2/#'));
    router.use(express.static(path.join(__dirname, 'www')));
    

    这样甚至子子模块都是可能的 .

    不要忘记将视图设置为src目录

    app.set('views', path.join(__dirname, 'src'));
    
  • 7

    我的结构表达了4. https://github.com/odirleiborgert/borgert-express-boilerplate

    Packages

    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
    

    Structure

    |-- app
        |-- controllers
        |-- helpers
        |-- middlewares
        |-- models
        |-- routes
        |-- services
    |-- bin
    |-- logs
    |-- node_modules
    |-- public
        |-- components
        |-- images
        |-- javascripts
        |-- stylesheets
    |-- views
    |-- .env
    |-- .env-example
    |-- app.js
    |-- README.md
    
  • 4

    一种简单的结构你表达app的方法:

    • 在主index.js中,应保持以下顺序 .

    所有app.set应该是第一个 . 所有应用程序应该是第二个 . 其他apis及其功能或路由 - 继续在其他文件Exapmle app.use(“/ password”,passwordApi); app.use(“/ user”,userApi); app.post(“/ token”,passport.createToken); app.post(“/ logout”,passport.logout)

  • 7

    好吧,我把我的路由作为json文件,我在开头阅读,并在app.js的for循环中设置路由 . route.json包括应该调用的视图,以及将发送到路由的值的键 .
    这适用于许多简单的情况,但我必须为特殊情况手动创建一些路由 .

  • 0

    我的问题是在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应用程序 . 它加载配置模块, Logger 模块,等待数据库连接,...,并运行快速服务器 .

    '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/

    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);
    };
    

    每个路由模块都是 standalone .

  • 6

    自问题的最后一个答案以来已经有一段时间了,Express最近也发布了第4版,它为组织应用程序结构添加了一些有用的东西 .

    以下是关于如何构建Express应用程序的最佳实践的最新博客文章 . http://www.terlici.com/2014/08/25/best-practices-express-structure.html

    还有一个GitHub存储库应用了本文中的建议 . 它始终与最新的Express版本保持同步 .
    https://github.com/terlici/base-express

  • 18

    我认为这是一个很好的方式 . 不仅限于表达,但我在github上看到了很多相同的node.js项目 . 他们取出配置参数,将较小的模块(在某些情况下,每个URI)分解为单独的文件 .

    我建议在github上通过特定于快递的项目来获得一个想法 . IMO你的方式是正确的 .

相关问题