开发框架搭建

"保持简单, 保持模块化."

开发步骤

通常是从画一个项目的草图开始. :

  1. 分析项目的草图, 理解需要的Domain
  2. 创建项目的README文件
  3. 基于草图, 在文档中写出路由和 API 
  4. 创建领域模型
  5. 选择软件堆栈和要依赖的Module
  6. 设置项目的仓储
  7. 写出数据库scheme, 创建数据库
  8. 开始编码,写Models 和 Collections
  9. 写单元测试
  10. 写Controllers 和类库
  11. 创建路由
  12. 写集成测试
  13. 创建API
  14. Review代码, 有必要的话进行调整

架构

我的应用受MVC的影响比较大. MVC 架构非常适合Node.js 开发.

下面是我的典型的目录结构.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/
  api/
  bin/
  collections/
  config/
  controllers/
  env/
  lib/
  models/
  public/
  routes/
  test/
  views/
  .gitignore
  .jshintrc
  app.js
  package .json
  README.md

 

下面我们描述下每个文件夹和文件在我们项目目录里的用处.

Documentation (./README.md)

README.md是我项目里非常重要的一个文件.

我的 README.md 文件包含下面的信息:

  1. 项目名和描述
  2. 软件要求
  3. 依赖
  4. Getting started instructions
  5. 需求配置
  6. 任务命令
  7. 风格指南
  8. 应用架构
  9. 路由/API
  10. License信息

 下面的例子是我怎么描述我的路由的:

1
2
3
4
5
6
/**
  *  Routes
**/
GET  /items     - get a collection of items
GET  /items/:id - get one item
POST /items     - save an item

./models

在软件应用中, model通常代表一个数据库表的记录.

./models/mymodel.js

1
2
3
4
5
6
7
8
9
10
// get config
var config = require( '../config' );
// connect to the database
var Bookshelf = require( '../lib/dbconnect' )(config);
// define model
var myModel = Bookshelf.Model.extend({
   tableName: 'items'
});
// export collection module
module.exports = myModel;

./collections

Collections 像表一样的一组model. 一个collection 通常代表一个完整的数据库表.

./collections/mycollection.js

1
2
3
4
5
6
7
8
//require the model for this collection
var myModel = require( '../models/mymodel' );
// define collection
var myCollection = Bookshelf.Collection.extend({
   model: myModel
});
// export collection module
module.exports = myCollection;

./controllers

Controllers, 和其他的典型的 MVC 一样, 负责应用的业务逻辑. 我们的controllers根据路由处理数据、查询数据库.

./controllers/items.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
var myModel = require( '../models/mymodel' );
var myCollection = require( '../collections/mycollection' );
module.exports = {
   // GET /items/:id
   getItem: function (req, res, next) {
     var id = req.params.id;
     myModel.forge({id: id})
     .fetch()
     .then( function (model) {
       res.json(model.toJSON());
     })
     .otherwise( function (error) {
       res.status(500).json({msg: error.message});
     });
   },
   // GET /items
   getItems: function (req, res, next) {
     var id = req.params.id;
     myCollection.forge()
     .fetch()
     .then( function (collection) {
       res.json(collection.toJSON());
     })
     .otherwise( function (error) {
       res.status(500).json({msg: error.message});
     });
   },
   // POST /items
   // (Don't forget to validate and sanitize all user input)
   saveItem: function (req, res, next) {
     myModel.forge(req.body)
     .save()
     .then( function (model) {
       res.json(model.toJSON());
     })
     .otherwise( function (error) {
       res.status(500).json({msg: error.message});
     });
   }
};

./routes

存放路由.

./routes/items.js

1
2
3
4
5
6
7
8
9
var express = require( 'express' );
var itemsController = require( '../controllers/items' );
module.exports = function () {
   var router = express.Router();
   router.get( '/items' , itemsController.getItems);
   router.get( '/items/:id' , itemsController.getItem);
   router.post( '/items' , itemsController.saveItem);
   return router;
};

./config

当我们创建model的时候我们需要config module. config的唯一目的是检查环境类型从env文件夹加载适当的config文件. config目录只有一个文件 index.js.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module.exports = ( function (env) {
   var config = {};
   switch (env) {
     case 'production' :
       config = require( '../env/production' );
       break ;
     case 'development' :
       config = require( '../env/development' );
       break ;
     case 'testing' :
       config = require( '../env/testing' );
       break ;
     case 'staging' :
       config = require( '../env/staging' );
       break ;
     default :
       console.error( 'NODE_ENV environment variable not set' );
       process.exit(1);
   }
   return config;
})(process.env.NODE_ENV);

./env

env 目录包含了对应不同环境模式的config文件: development.jsproduction.jstest.js, and staging.js.

Here is an example of one file:

1
2
3
4
5
6
7
8
9
10
11
12
13
module.exports = {
   pg: {
     host: '127.0.0.1' ,
     database: 'test' ,
     user: 'test' ,
     password: 'test' ,
     charset: 'utf8'
   },
   mongodb: {
     url: 'mongodb://localhost:27017/test'
   },
   sessionSecret: 'ninja_cat'
};

注意了: 别在config文件中包含敏感数据, 敏感数据放到环境变量中去

./api

api 文件夹包含应用的api文件. 我用创建controller一样的方法创建api文件, 唯一不同的是controller会加载一个视图文件.

./lib

lib 文件夹在Node modules中非常普遍. 如果你的应用使用了特别的算法或helpers lib目录适合放他们. 在大多数情况下controller需要一个lib 文件来执行一些特定的任务.

./bin

bin包含我自己的command-line scripts. 例如:

1
2
#!/usr/bin/env node
console.log( 'I am an executable file' );

./public

public 文件夹包含一些客户端的静态文件, 例如images, css, 前端JavaScript, fonts 等

./views

我所有的视图模板都放在这.

./test

test 目录包含了所有的测试用例.

./.gitignore

.gitignore 文件用来告诉GIT那些文件或者目录不要版本控制.

1
2
3
4
5
6
7
*.zip
*.psd
*~
node_modules/
bower_components/
build/
temp/

./.jshintrc

.jshintrc 是 jshint 的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
   "curly" : false ,
   "eqeqeq" : true ,
   "immed" : true ,
   "latedef" : false ,
   "newcap" : true ,
   "noarg" : true ,
   "sub" : true ,
   "undef" : true ,
   "boss" : true ,
   "eqnull" : true ,
   "node" : true ,
   "browser" : true ,
   "globals" : {
     "jQuery" : true ,
     "define" : true ,
     "requirejs" : true ,
     "require" : true ,
     "describe" : true ,
     "it" : true ,
     "beforeEach" : true ,
     "before" : true
   }
}

./package.json

package.json 是一个标准的npm文件, 列出了所有应用的 dependencies 和 metadata. 

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
     ...
     "scripts" : {
       "start" : "node app.js" ,
       "dev" : "nodemon app" ,
       "jshint" : "jshint api collections config controllers env lib models public/javascripts routes test app.js" ,
       "test" : "npm run jshint && mocha test" ,
       "precommit" : "npm test" ,
       "prepush" : "npm shrinkwrap && npm test" ,
       "postmerge" : "npm install"
     }
     ...
}

一些我经常用的 modules

  • Express - App frameworks
  • Bookshelf - Postgres 和 MySQL 的 ORM
  • lodash - 工具类库
  • passport - 验证
  • mongoose - MongoDB ODM
  • when.js - promises library
  • moment - 分析, 验证, manipulating, 格式化日期
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值