文档章节

Nodejs框架演进之路

i5ting
 i5ting
发布于 2015/12/26 14:25
字数 2160
阅读 209
收藏 7
点赞 0
评论 0

Nodejs框架演进之路

大部分框架的演进之路大体都是一样的

  • 实现(土方法)
  • 实践(项目实操)
  • 看齐最佳实践
  • 不断封装、造轮子
  • 走出自己的特色

下面简单的介绍一下moajs的演进之路

什么是Moajs?

moajs是我司开发的开源nodejs web框架。

https://github.com/moajs

目前主要

  • moa-api
  • moa-frontend
  • moa-h5
  • mongoosedao
  • res.api
  • mount-routes

moa是作为名词是恐鸟(一种新西兰无翼大鸟,现已灭绝) https://en.wikipedia.org/wiki/Moa

阶段0:原始的Expressjs

最开始的时候都是使用express-generator生成的项目骨架

➜  test  express express-test

   create : express-test
   create : express-test/package.json
   create : express-test/app.js
   create : express-test/public
   create : express-test/public/javascripts
   create : express-test/views
   create : express-test/views/index.jade
   create : express-test/views/layout.jade
   create : express-test/views/error.jade
   create : express-test/public/stylesheets
   create : express-test/public/stylesheets/style.css
   create : express-test/routes
   create : express-test/routes/index.js
   create : express-test/routes/users.js
   create : express-test/public/images
   create : express-test/bin
   create : express-test/bin/www

   install dependencies:
     $ cd express-test && npm install

   run the app:
     $ DEBUG=express-test:* npm start

➜  test  cd express-test 
➜  express-test  tree . -L 1 -d
.
├── bin
├── public
├── routes
└── views

4 directories

express是遵循小而美的原则,所以只有routes和views层,不足以在项目里使用的。

阶段1:抽象config和controller、model、middleware等

$ tree . -L 1 -d
.
├── actions
├── config
├── cron_later
├── doc
├── middleware
├── migrate
├── models
├── node_modules
├── public
├── queues
├── routes
├── test
├── tmp
├── uploads
└── views

说明

  • 继承express-generator的结构(routes和views)
  • actions即controller控制器层
  • models即模型层
  • config是配置项目录
  • middleware中间件层
  • migrate是我们处理数据的,跟rails的migrate不完全一样
  • test是测试目录
  • queues是队列
  • cron_later是调度
  • doc文档
  • uploads是上传自动创建的目录

这阶段仅仅是用,算是基于express抽象了一点业务、配置相关的东西而已,目录多了依然蛋疼

阶段2:向rails看齐

目录结构

➜  moa-api git:(master) ✗ tree . -L 2 -d
.
├── app
│   ├── controllers
│   ├── middlewares
│   ├── models
│   ├── routes
│   ├── services
│   └── views
├── bin
├── config
├── doc
├── logs
├── migrate
├── public
└── test
    └── controller

42 directories

说明

  • 使用app作为代码管理目录,归类可变代码都放到app下面
  • 其他沿用【阶段1】的设计

具体看一下app目录下的分类

├── app
│   ├── controllers
│   ├── middlewares
│   ├── models
│   ├── routes
│   ├── services
│   └── views

说明

  • mvc和rails的都一样
  • middlewares是express的概念,放这里比较合适,如果像rails一样设置plugin也可以考虑,不如放到此处更容易理解
  • services层实际是java里面喜欢用的概念,多个模型dao的操作,看成是一个业务,所以复杂业务场景下,services层有它的好处

你看不到的优化

  • 使用mongoosedao把mongoose的crud、分页等封装了dao操作
  • 使用mount-routes自动挂载路由,让你只关系路由内容,而不必关系url地址,这样也算coc的一种(约定大于配置)
  • 使用res.api约定api返回数据

至此,moajs的0.x版本,特性已经足够了。

其实moajs还提供脚手架scaffold和插件机制

脚手架scaffold

moag order product_name:string product_count:string all_price:string status:string delivery_num:string pay_num:string activity_id:string  owner_id:string contact_id:string

生成目录如下

➜  moa-scaffold  tree .
.
└── app
    ├── controllers
    │   └── orders_controller.js
    ├── models
    │   └── order.js
    ├── routes
    │   ├── api
    │   │   └── orders.js
    │   └── orders.js
    └── views
        └── orders
            ├── edit.jade
            ├── index.jade
            ├── new.jade
            ├── order.jade
            └── show.jade

7 directories, 9 files

这个生成器的原理是我们参考rails的脚手架,代码结构,mvc都非常方便

需要说明的是

  • 先有结构
  • 然后才有脚手架

插件机制

大家都知道express基于connect,有middleware中间件的概念,它本身遵循小而美的设计哲学,导致它非常精简

从express@generator来看,它就只能做点小打小闹的东西,如果要设计一个复杂的大系统,就免不了和代码结构,模块,组件等战斗

从我的角度讲,这些东西都可以理解成是业务插件,比如对于一个框架来说,用户管理就应该像ruby里的devise一样,以一个gem的形式存在,如果代码里引用,调用就好了。

gem + rails plugin机制可以做,那么express + npm也是可以的,但是我们缺少的plugin机制,先说利用npm的回调实现它的可能性

比如在一个boilerplate项目里,我们安装插件

npm install --save moa-plugin-user

安装完成之后,我们需要对项目里的文件或配置也好做一个插件登记,这些东西是否可以放到postinstall里呢?

剩下的就都是nodejs代码了,大家写就好了。

moajs里0.x版本使用软连接创建插件

  • nmm用于插件管理和初始化
  • 使用npm的postinstall hook完成安装工作
  • 使用软连接的方式创建插件(简单粗暴法)

这其实有很多痛苦,每次升级插件都需要在主库里更新,以后还是要放到目录里,按照php的做法走。

总结

总结一下moajs的特性

  • 配置化
  • 目录和rails类似
  • 脚手架scaffold
  • 插件机制
  • 一些我们总结的最佳实践

具体

  • 自动加载路由
  • 支持mongodb配置
  • 集成mongoosedao,快速写crud等dao接口
  • 自带用户管理
  • 使用jsonwebtoken做用户鉴权
  • 支持migrate测试
  • 支持mocha测试
  • 默认集成res.api,便于写接口
  • 集成supervisor,代码变动,自动重载
  • gulp自动监控文件变动,跑测试
  • gulp routes生成路由说明
  • 使用log4js记录日志
  • 集成kue队列[需要使用mount-queues插件]

阶段3:走自己的路

上一个阶段【阶段2:向rails看齐】其实还是基于express的最佳实践而已。代码里处处都是express的影子,所以moajs 0.x版本真的只是基于express的最佳实践。

但是技术的演进步伐非常快

  • es6和7来了
  • async/generator也来了
  • koa来了
  • typescript来了
  • ...

这些对我们来说都是要思考的

前后端分离

  • 前端:moa-frontendmoa-h5
    • public下面的采用nginx做反向代理
    • 其他的采用express+jade精简代码(ajax与后端交互)
  • 后端:moa-api

微内核base2

之前使用express,各种配置都在app.js里,恶心的要死,而且没有app的生命周期管控

于是写了base2,它是一个高度可配置的带有应用生命周期管控的 nodejs web 微框架(同时支持express和koa)

https://github.com/base-n/base2-core

Usages

var app = require('base2')({
  // debug: true,
  root:__dirname,
  "views": "views",
  "routes": "routes2",
  "public": "public",
})

app.start(3019);
  • 如果有views目录就可以显示视图
  • 如果有routes目录,就可以自动挂载路由
  • 如果有public就有静态server,目录随便指就好了

简单吧,下面讲讲为啥这样设计。

我们对项目的认知

  • framework(框架选项)
    • express
    • koa
  • env(环境,参考rails的环境说明)
    • production
    • development
    • test
  • type(类型,我们对项目分类,有的是带视图的,有的是api的,有的rpc服务的,all即所有)
    • normal
    • api
    • all
    • service

这些其实对express和koa的中间件分类的维度。也就是说不同场景,我们加载不通的中间价。

那么我们什么时候加载呢?你想可配置,可高度配置,你就一定得留出足够的点,让之前可以完成功能也能很好的集成进来。

于是引出app的生命周期,我们可以反思一下app.js里都做了什么?

  • 设置
  • 全局中间件
  • 路由

其他都指出去了。

那么我们就可以抽象一下了

  • config.pre
  • settings
    • config.before_settings
    • config.after_settings
  • global_middlewares
    • config.before_global_middlewares
    • config.after_global_middlewares
  • routes
    • config.before_routes
    • config.after_routes
  • config.post

实际上也是之前app做的事儿,但是要放到配置项里,按需采用。

举个例子,moa-api里的app.js 改写后

require('./init')
require('./db')

var log4js        = require('log4js'); 
var res_api       = require('res.api');
var log           = log4js.getLogger("moa-api");

var app = require('base2')({
  // debug: true,
  root:__dirname,
  "pre": function(app) {
    app.use(res_api);
  },
  "views": "app/views",
  "routes": "app/routes",
  "public": "public"
})

res_api是一个中间件,如果想在路由里直接使用res.api方法,就必须先挂载。

这里选了pre这个最早执行的生命周期方法。其实也可以routes前面的所有生命周期都可以。

兼容koa和express

噱头而已,其实兼容与否并不重要,base2给我们提供了这种可能,我们用就好了

通过koa-generator大家可以体验一下koa1和koa2的写法和express的差别。

另外我组织了大家《一起学koa》

http://base-n.github.io/koa-generator-examples

欢迎参与

Next

moajs在设计、实践上都是不错的,不过目前还不够完善,希望大家可以多多参与

下一步还在做

未来路还很远。。。但很美好

全文完

欢迎关注我的公众号【node全栈】

node全栈.png

© 著作权归作者所有

共有 人打赏支持
i5ting
粉丝 189
博文 68
码字总数 98509
作品 3
东城
昨天直播的微信小程序讲义

狼叔带你一起玩转微信应用号 微信小程序开发适合你吗? 如果想邀请分享,请邮寄给我i5tinig@126.com,如果时间ok,我会尽量分享 文档 https://i5ting.github.io/stuq-wxapp/ 仓库 https://gi...

i5ting
2016/09/29
111
0
全栈工程师之路-Node.js

全栈工程师之路-Node.js 高可用架构专用 原文[高可用架构] https://mp.weixin.qq.com/s?biz=MzAwMDU1MTE1OQ==&mid=405001493&idx=1&sn=f0ecab9b31bad83fb065ac37bb728245&scene=1&srcid=032......

i5ting
2016/04/08
277
0
全栈工程师之路-Node.js

全栈工程师之路-Node.js 高可用架构专用 原文[高可用架构] https://mp.weixin.qq.com/s?_biz=MzAwMDU1MTE1OQ==&mid=405001493&idx=1&sn=f0ecab9b31bad83fb065ac37bb728245&scene=1&srcid=03......

i5ting
2016/04/08
192
1
《Node.js开发指南》书评汇总

刚查了下库存,发现订阅《Node.js开发指南》的读者大增,这是为什么呢?看了下近期本书在豆瓣的评论,口碑很好,现将豆瓣的书评汇总如下: ----------------------------------------------...

生气的散人
2012/10/15
0
0
前端每周清单第 47 期:NPM 年度报告与 2018 展望,Airbnb React Router 实践

前端每周清单专注前端领域内容,以对外文资料的搜集为主,帮助开发者了解一周前端热点;分为新闻热点、开发教程、工程实践、深度阅读、开源项目、巅峰人生等栏目。欢迎关注【前端之巅】微信公...

王下邀月熊
01/15
0
0
Service Mesh、K8S、海量数据一致等,六大热点技术邀你来聊

小蚂蚁说: 云原生(Cloud-Native)到底是什么?这个问题一直很难定义。CNCF技术监督委员会最近通过投票确定了其官方定义。如何使其弹性可扩展、稳定高可用、敏捷易维护等特性应用到现有创新...

兔子酱
06/29
0
0
NodeJS对于Java开发者而言是什么?

我们都知道Node.js现在得到了所有的关注。每个人都对学习Node.js感兴趣,并希望可以工作于Node.js。在开始工作之前了解技术背后的概念总是不会错的。但对初学者来说,可能会因为不同的人使用...

城固如春
2017/10/21
0
0
Node.js到底强在哪里?

PHP VS NODE.JS: THE REAL STATISTICS一文用PHP和Node.js实现文件读写的案例展示两者性能对比, 两者相差14倍之多。究其原因还是Node.JS的异步IO。 I/O是Web应用典型的消耗瓶颈,当一个请求达...

大糊涂
2015/06/20
0
0
golang vs dlang vs nodejs vs php 性能对比较量

这是我本机开的一个单核1G内存的Hyper-V虚拟机,首先我们使用的语言和框架版本给大家看一下: root@kerisy:/home/zoujiaqing# go versiongo version go1.5.1 linux/amd64root@kerisy:/home/...

冰力
2015/11/13
0
1
Node.js的学习资源、教程和工具

这篇文章编译整理自Stack Overflow的一个如何开始学习Node.js的Wiki帖,这份资源列表在SO上面浏览接近60万次,数千个收藏和顶。特意整理发布到这里,其中添加了部分中文参考资料。 学习指南和...

90后爱国
2015/07/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

用Python绘制红楼梦词云图,竟然发现了这个!

Python在数据分析中越来越受欢迎,已经达到了统计学家对R的喜爱程度,Python的拥护者们当然不会落后于R,开发了一个个好玩的数据分析工具,下面我们来看看如何使用Python,来读红楼梦,绘制小...

猫咪编程
18分钟前
0
0
Java中 发出请求获取别人的数据(阿里云 查询IP归属地)

1.效果 调用阿里云的接口 去定位IP地址 2. 代码 /** * 1. Java中远程调用方法 * http://localhost:8080/mavenssm20180519/invokingUrl.action * @Title: invokingUrl * @Description: * @ret......

Lucky_Me
41分钟前
1
0
protobuf学习笔记

相关文档 Protocol buffers(protobuf)入门简介及性能分析 Protobuf学习 - 入门

OSC_fly
昨天
0
0
Mybaties入门介绍

Mybaties和Hibernate是我们在Java开发中应用的比较多的两个ORM框架。当然,目前Mybaties正在慢慢取代Hibernate,这是因为相比较Hibernate而言Mybaties性能更好,响应更快,更加灵活。我们在开...

王子城
昨天
2
0
编程学习笔记之python深入之装饰器案例及说明文档[图]

编程学习笔记之python深入之装饰器案例及说明文档[图] 装饰器即在不对一个函数体进行任何修改,以及不改变整体的原本意思的情况下,增加函数功能的新函数,因为这个新函数对旧函数进行了装饰...

原创小博客
昨天
0
0
流利阅读笔记33-20180722待学习

黑暗中的生物:利用奇技淫巧快活生存 Daniel 2018-07-22 1.今日导读 如果让你在伸手不见五指的黑暗当中生存,你能熬过几天呢?而大千世界,无奇不有。在很多你不知道的角落,有些生物在完全黑...

aibinxiao
昨天
6
0
Hystrix降级逻辑中如何获取触发的异常

通过之前Spring Cloud系列教程中的《Spring Cloud构建微服务架构:服务容错保护(Hystrix服务降级)》一文,我们已经知道如何通过Hystrix来保护自己的服务不被外部依赖方拖垮的情况。但是实际...

程序猿DD
昨天
1
0
gin endless 热重启

r := gin.New()r.GET("/", func(c *gin.Context) {c.String(200, config.Config.Server.AppId)})s := endless.NewServer(":8080", r)s.BeforeBegin = func(add string) ......

李琼涛
昨天
1
0
JAVA模式之代理模式

平时一直在用spring,spring中最大的特效IOC和AOP,其中AOP使用的就是代理模式.闲着无聊,随手写了一个代理模式,也记录下代理模式的实现Demo. 比如现在有一个场景是:客户想要增加一个新的功能,...

勤奋的蚂蚁
昨天
0
0
ES15-JAVA API 索引管理

1.创建连接 创建连接demo package com.sean.esapi.client;import java.net.InetSocketAddress;import org.elasticsearch.action.get.GetResponse;import org.elasticsearch.clien......

贾峰uk
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部