• [译]我是怎么构建Node.js程序的


    原文: http://blog.ragingflame.co.za/2015/4/1/how-i-build-nodejs-applications

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

    开发步骤

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

    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 开发.

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

    /
     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信息

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

    /**
     *  Routes
    **/
    GET  /items     - get a collection of items
    GET  /items/:id - get one item
    POST /items     - save an item
    

    ./models

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

    ./models/mymodel.js

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

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

    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

    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.

    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:

    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. 例如:

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

    ./public

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

    ./views

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

    ./test

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

    ./.gitignore

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

    *.zip
    *.psd
    *~
    node_modules/
    bower_components/
    build/
    temp/
    

    ./.jshintrc

    .jshintrc 是 jshint 的配置文件

    {
      "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. 

    例子:

    {
        ...
        "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, 格式化日期

     

  • 相关阅读:
    SQLSERVER2008数据库增量备份还原方式
    使用VS2003遇到“无法显示进程。没有正确安装调试器。请运行安装程序安装或修复调试器。”的解决方法
    IIS7下配置最大上传附件大小需要注意的事项
    运行常用指令
    跨库查询推荐使用的方法
    获取客户端IP需要注意的一个问题
    如何判断一个表是否建立索引约束等信息的SQL语句
    SQLServer2005重建索引前后对比
    一个鼠标滚轮控制大小的缩放类。
    全兼容的纯CSS级联菜单
  • 原文地址:https://www.cnblogs.com/irocker/p/how-i-build-nodejs-applications.html
Copyright © 2020-2023  润新知