MR шаблон для написания сервисов на Node.js

в 3:47, , рубрики: node.js, метки:

image
Суть таква: node.js не дает готового решения для создания проекта. Первый мой проект на node.js состоял из одного coffeescript файла и run.js для запуска из IDE. Когда роутов было пять штук все было замечательно, но когда проект оброс моделями и роутерами это превратилось в ад. Решают эту проблему разными способами, кто-то используй hub, кто-то global, кто-то все в один фаил заносит.

Внимание: решение не претендует быть единственным правильным и вообще правильным. Просто решил поделиться. Срач на тему node.js vs erlang прошу не разводить, они в разных категориях.

Для не терпеливых есть проект на гитхабе.

MR — Model Route, View я опускаю потому, что res.json это не view, а сервису большего и не надо.

Структура проекта:

├── app.coffee
├── config.coffee
├── models
│   └── example.coffee

├── package.json
├── public
│   ├── images
│   ├── javascripts
│   └── stylesheets
├── routes
│   ├── index.coffee
│   └── root.coffee
├── run-cluster.js
└── run.js

app.coffee

В этом это точка входа в приложение.

exports.start = () ->
  log     = require('logule') # Удобный логер
  log.debug "Spawning new worker"
  require 'coffee-script' # нужно для того, чтобы нода переваривала .coffee файлы в require
  ###
     Basic dependencies
  ###
  express       = require 'express'
  app           = module.exports = express.createServer()
  app.__        = require 'underscore' # на всякий случай
  app.mongoose  = require 'mongoose' # ODM для MongoDb, and yes, it's web scale
  app.log       = log # костыль
  config        = require('./config.coffee')(app,express) # конфигурация приложения 

  models        = {} # Сюда складываются все модели
  models.example= require('./models/example')(app.mongoose).model # Пример модели

  require('./routes/index.coffee')(app, models) # Фаил в котором прописаны все маршруты
  port = process.env.PORT || 5000 # Для Heroku и других схем деплоя
  app.listen port
  log.info "Express server listening on port #{port}"

config.coffee

module.exports = (app, express) ->
  config = this
  app.configure ->
    app.use express.bodyParser()
    app.use express.methodOverride()
    app.use app.router
    app.use express.static(__dirname + '/public')
  app.configure 'development', () ->
    app.use express.errorHandler({dumpExveption: true, showStack: true}) # "полезный" дамп стека
    app.mongoose.connect process.env.MONGOLAB_URI || "mongodb://localhost/skel" # Для heroku 
  app.configure 'production', () ->
    app.use express.errorHandler()
    app.mongoose.connect "mongodb://localhost/production"
  return config

models/example.coffee

module.exports = (mongoose) ->
  Schema    = mongoose.Schema
  ObjectId  = Schema.ObjectId
  #Comment   = mogoose.model('Comment') # пример того как получить модель которая уже ассоциирована с mongoose.
  PostSchema = new Schema {
    author  : { type:ObjectId, index:true }
    date    : Date,
    content : String
    #, comments : [Comment] # пример того как ее использовать
  }
  this.model = mongoose.model('Post', PostSchema) # ассоциирование
  
  return this

package.json

engines секция это для Heroku, все остальное понятно.

{
    "name": "mr-skel"
  , "version": "0.0.1"
  , "private": true
  , "engines": {
      "node": "0.6.x",
      "npm":  "1.x.x"
  }
  , "dependencies": {
      "express": "2.5.x"
    , "mongoose": "2.6.x"
    , "mongoose-types": "*"
    , "underscore": "*"
    , "coffee-script": "*"
    , "logule": "0.x.x"
  },
  "devDependencies": {
      "forever": "*"
    , "mocha": "*"
    , "should": "*"
  }
}

routes/index.coffee

В этом файле хранятся все роуты которые есть в приложении.

routes = {}
routes.root = require('./root.coffee')
module.exports = (app, models) ->
  app.get '/', routes.root.getIndex(models) # Насамом деле это костыль, я не смогу придумать как сделать models доступной для всех роутов из root.cofee

routes/root.coffee

exports.getIndex = (models) ->
  (req, res) ->
    Post  = models.example
    Post.find {}, (err, posts) ->
      if err?
        return res.send 500
      res.json { status: 'Ba dum tssh', meta: posts }

run-cluster.js

Запуск приложения при помощи Cluster API. На Heroku не работает, однако, на своей vps я запускаю приложение именно так.

cluster = require('cluster');
log     = require('logule');
require('coffee-script');

if (cluster.isMaster) {
  log.info("Master have just started");
  # i = кол-во ядер
  for (i = 1; i <= 2; i++) {
    cluster.fork();
  }
  cluster.on('death', function(worker) {
    log.error("Worker " + worker.pid + " died!");
    return cluster.fork();
  });
} else {
  app = require('./app.coffee');
  app.start()
}

run.js

require('coffee-script');

app = require('./app.coffee');
app.start();

Автор: Zelgadis

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js