express 最佳实践 (一)

第二篇: express 最佳实践(二):中间件

最近,一直在使用 nodejs 做项目,对 nodejs 开发可以说深有体会。

先说说 nodejs 在业务中的脚色,, 在 web同构 方面, nodejs 的优势相对于其他语言来说,可以说非常巨大,基本上算是只有 nodejs 能做,其他语言根本不能做。在传统 web 开发方面,nodejs(必竟时间太短了)的相对于其他语言来说的劣势,已经不是太明显了。

再来说说自己,算了算差不多做了 5 个项目,都是使用 express 做为项目的基础框架,然后再上面进行业务开发工作,一个路由下来,平均 10 个左右的中间件,执行效率都是不错的,开发效率也非常好,是时候总结一下 express 实践经验,同时结合配套自己的想法,来看看理想中 express 项目应该是怎样的规划,以及我是怎么想的。

思想

做一个项目的规划,首先要为项目订一个基调,就是项目架构是应该怎样设计,怎样考虑的,对业务开发是否方便,部署是否方便等要素。

我现在认为一个项目最重要的规划是:核心+插件式开发。一个项目一定要支持这两点,如果不支持这个项目就很难做下去,为什么我这样说。因为现在的任何一个项目都不可能是一个人开发,一定是多人分工开发,如果你的项目支持 核心+插件式开发,你就可以把核心的基础功能如:网络,日志,基础布局等功能,找个高级工程师来完成;业务开发,就可以分给一些初级工程师,并行完成,同时在做项目的时候对代码码进行审查,及时调整坏代码。这样项目,能保证进度,也能保证项目质量,不会大烂,同时人力也得到了充分利用。

这种思想落实到架构上,就是从项目的文件组织结构上考虑怎样达到这样的目标。

我是这样规划文件目录的:

按业务特性而不按分层进行规划

分层最典型的代表就是ruby on rails,app 目录下,就是 controllers, models等目录,当然我不是说,这种规划不好,只是到项目大到一定程度,你想找某个 controller 下的一个方法,就会很麻烦,不知道没有这种体验,在几十个文件中找某个方法是怎样的感觉,搜索也是全文搜索,不能限定到某个目录下面。因此在这个项目规划中,以业务特征为插件名,在 express 中,也就是 subExpress,如果,我有一个购物车的业务,那于购物车相关的所有的项目都规在 passport 这个子应用下了,这样相关的业务在一起,方便查找,同时也方便理解和修改。当然这种规划方式也有不方便的地方,如果想跨 subApplication 调用方法,就没有那么方便。

边界显式说明

这个跟传统的 controller, service , model 没有什么区别。还是刚才的 passport 应用,按分层进行划分,包括 controllers, services, models, views, index.js, router.js。需要说明一下,在项目中我们一再强调, controllers 中负责与 http 的连接工作,只做简单参数的验证,传参和调起 services ,禁止把 rep, res 对像做为参数传递到 services 层;services 层纯业务,没有与 http 相关的任何东西,需要数据请调用 models 中的方法;models 只于数据打交到,其它都不管。这样做的好处是什么呢? 想想看,如果相把一个页面的数据拿出来做接口,只需要简单几行就搞定了,还有如果要把框架改成 koa ,你的业务都不用重写,还有你想增加 websocket 的支持,直接在 controllers 进行调整就行了。 models的作用更明显,原来的项目是一个普通是 web 项目,models 是连接数据库的,现在技术升级要前后端分离,不用数据库了,改成调用后端的接口了,你就只用把 models 用接口实现一遍,其他不用变了。 controllers 和 models 就是你业务的边界,service 则是你业务的核心,边界实现的改变不应该影响你业务。

落实

思想利用 express 的中间件思想,达到我的架构意图,如下图所示:

图中,蓝色的部分代表业务中间件,橙黄色代表 核心中间件。在一个网站项目中核心中间件,应该包括 limiter 限流操作,这个中间件主要是防止爬虫;htaccess 改写 url,这个中间件主要用,改写网站url, 为什么要改呢?因为一但网站线上运行时,路由的规则不应发生变化,但是有时候 seo 的时候,你需要兼容新老 url 的时候,这个中间件就会非常有用,网站的业务都不用变,只用在新url 到达时,变成老的再进行处理就行了;dispatch 不是一个中间件,它的思想是用来整合各个业务线的 subApplication 和主 application 的关系的;auth 鉴权,有些页面和接口需要有用户登录,如果没有用户登录,就需要跳转到登录页面,登录完成后跳回来;clientError 和 serverError 是对错误进行统一的处理,统一显示 404 , 如果是接口的话也会统一 404 的返回码。

业务端在开发时只需要在 dispatch 的地方加入自已的模块,然后就可以开始写自己的业务,不用但心自己的文件被别人改动。

下面是项目的文件夹规划:

简单说明下:

apps 目录下就写各自的业务逻辑,用 dispatch 把 主app 与 业务 连接起来,实现起来也挺简单的:

module.exports = (app) => {
app.use('/passport', require('./apps/passport'));
}

还有 shared 的存在,是为了解决前后端模板公用的问题。

与业务没有关系的代码可以,移到到 modules 中使用。

如果个业务的之间需要共享部分代码,就放到 utils 中,这个文件夹就是用来干这种事的。

总结

这个项目中规划就是,怎样使用 express 最好,另外再加上自己的一些思考,现在项目的结构出来了,后面会再讨论一些有关中间件的处理方法。

该项目的 github

nodejs 实践:express 最佳实践 (一)的更多相关文章

  1. nodejs 实践:express 最佳实践(四) express-session 解析

    nodejs 实践:express 最佳实践(四) express-session 解析 nodejs 发展很快,从 npm 上面的包托管数量就可以看出来.不过从另一方面来看,也是反映了 nodejs ...

  2. nodejs 实践:express 最佳实践系列

    nodejs 实践:express 最佳实践系列 nodejs 实践:express 最佳实践(一) 项目结构 nodejs 实践:express 最佳实践(二) 中间件 nodejs 实践:expr ...

  3. nodejs 实践:express 最佳实践 (一) 项目结构

    express 最佳实践 (一) 第二篇: express 最佳实践(二):中间件 最近,一直在使用 nodejs 做项目,对 nodejs 开发可以说深有体会. 先说说 nodejs 在业务中的脚色 ...

  4. nodejs 实践:express 最佳实践(三) express 解析

    nodejs 实践:express 最佳实践(三) express 解析 nodejs 发展很快,从 npm 上面的包托管数量就可以看出来.不过从另一方面来看,也是反映了 nodejs 的基础不稳固, ...

  5. nodejs 实践:express 最佳实践(五) connect解析

    nodejs 实践:express 最佳实践(五) connect解析 nodejs 发展很快,从 npm 上面的包托管数量就可以看出来.不过从另一方面来看,也是反映了 nodejs 的基础不稳固,需 ...

  6. nodejs 实践:express 最佳实践(六) express 自省获得所有的路由

    nodejs 实践:express 最佳实践(六) express 自省获得所有的路由 某些情况下,你需要知道你的应用有多少路由,这在 express 中没有方法可以.因此我这边曲线了一下,做成了一个 ...

  7. nodejs 实践:express 最佳实践(七) 改造模块 connect2 解析

    nodejs 实践:express 最佳实践(七) 改造模块 connect2 解析 nodejs 发展很快,从 npm 上面的包托管数量就可以看出来.不过从另一方面来看,也是反映了 nodejs 的 ...

  8. nodejs 实践:express 最佳实践(八) egg.js 框架的优缺点

    nodejs 实践:express 最佳实践(八) egg.js 框架的优缺点 优点 所有的 web开发的点都考虑到了 agent 很有特色 文件夹规划到位 扩展能力优秀 缺点 最大的问题在于: 使用 ...

  9. nodejs 实践:express 最佳实践(二) 中间件

    express 最佳实践(二):中间件 第一篇 express 最佳实践(一):项目结构 express 中最重要的就是中间件了,可以说中间件组成了express,中间件就是 express 的核心. ...

随机推荐

  1. Graphical Analysis of German Parliament Voting Pattern

    We use network visualizations to look into the voting patterns in the current German parliament. I d ...

  2. 挂载mount

    mount 1 挂载mount 基本概念 挂载:将额外文件系统与根文件系统现存的目录建立起关联关系,进而使得此目录做为其它文件访问入库的行为 卸载:为解除关联关系的过程 注意:挂载点下原有的文件在挂载 ...

  3. 【译】Envoy with Nomad and Consul (一)

    原文: http://timperrett.com/2017/05/13/nomad-with-envoy-and-consul 在过去的许多年我的职业生涯一直是围绕着数据中心和平台基础设施.工作范围 ...

  4. 教你一步搭建Flume分布式日志系统

    在前篇几十条业务线日志系统如何收集处理?中已经介绍了Flume的众多应用场景,那此篇中先介绍如何搭建单机版日志系统. 环境 CentOS7.0 Java1.8 下载 官网下载 http://flume ...

  5. 堆结构的优秀实现类----PriorityQueue优先队列

    之前的文章中,我们有介绍过动态数组ArrayList,双向队列LinkedList,键值对集合HashMap,树集TreeMap.他们都各自有各自的优点,ArrayList动态扩容,数组实现查询非常快 ...

  6. hdu4638

    hdu4638 题意 给定一个序列,序列由1-N个元素全排列而成,求任意区间可组成的连续的段数,比如[1,2,4]两段{[1,2],[4]},[1,2,4,3]一段{[1,2,3,4]}. 对于查询的 ...

  7. 生成JSON数据--fastjson(阿里)方法

    fastjson(阿里)方法生成JSON数据: 与Gson类似,创建相应类,再使用JSON.toJSONString()添加对象 要求:生成如下JSON数据 1.{"age":3, ...

  8. mybatis在mysql和oracle批量插入不同

    两者不同 1,批量插入 2,主键自增 3,分页不同 4,......待补充 批量插入 mysql: <insert id="batchinsertSelective" par ...

  9. 学习web前端怎样入门?初学者赶紧看过来!

    web前端怎么样才能入门,首先我们要从什么是初级web前端工程师说起: 按照我的想法,我把前端工程师分为了入门.初级.中级.高级这四个级别, 入门级别指的是了解什么是前端(前端到底是什么其实很多人还是 ...

  10. HTTPS系列干货(一):HTTPS 原理详解

    HTTPS(全称:HyperText Transfer Protocol over Secure Socket Layer),其实 HTTPS 并不是一个新鲜协议,Google 很早就开始启用了,初衷 ...