10月29, 2017

记一次node项目总结

这两周终于写完了一个基于node的接口API。也该总结一下,便于日后能翻阅,或者今后来看看此时的自己有多么幼稚吧。。,

对于这个项目,我自己的满意度只有50%,是的,及格线都不到。不过我也总结了一套自己的node脚手架(比较粗浅的模子),所以算上这个,勉强给自己打个60分吧。

这个项目地址:node_project_template

思路来源

这个项目是我基于scott老师分享的冰火之歌改造而来。

他这个在慕课网有一个专门的课程,那个课程让我收获良多。

项目特点

  • 能够在里面尽情使用import export这些语法,因为在外层加入一层babel编译
  • 强大的路由装饰器

简单提一下路由装饰器,譬如我们有这样的一个功能。前端表单有10个字段,这10个字段都需要校验非空,除了前端要校验,后端也得校验。

我目前的代码是这样写的:

const mapArr = [
    {
        id: {
            isRequired: true,
            errorMsg: "ID不能为空"
        }
    },
    {
        order: {
            isRequired: true,
            errorMsg: "序号不能为空"
        }
    },
    {
        parent: {
            isRequired: true,
            errorMsg: "组件归属不能为空"
        }
    },
    {
        zh_name: {
            isRequired: true,
            errorMsg: "组件名称不能为空"
        }
    },
    {
        en_name: {
            isRequired: true,
            errorMsg: "组件英文名称不能为空"
        }
    },
    {
        description: {
            isRequired: true,
            errorMsg: "描述不能为空"
        }
    },
    {
        interactive_article: {
            isRequired: false
        }
    },
    {
        design_article: {
            isRequired: false
        }
    },
    {
        fe_article: {
            isRequired: false
        }
    }
];
for (let i = 0, len = mapArr.length; i < len; i++) {
    const item = mapArr[i];
    for(let key in item) {
        if (item[key].isRequired && !fields[key]) {
            ctx.body = ApiResponse.error({
                msg: item[key].errorMsg
            })
            return;
        }
    }
}

多了之后,难免重复的代码会越来越多。有了装饰器的路由,我们可以这样来重构:

alt

分别对应:GET、普通POST、form-data的POST

还有一个在项目中需要考虑的是字段校验,比如电话号码、邮箱之类的。

在项目中可以使用koa-validator,我已经将其集成进去了。

当然非空校验也是它的一种,但我个人觉得这个可以单独拎出来放到路由装饰器中。validate这一块,有想过集成到装饰器里面,但这样又会涉及到以下几种情况:

  • 内置的校验器
  • 正则表达式
  • 较复杂的逻辑判断

特别是第三种情况,所以暂时先不整理吧。

项目分层

我对自己做的东西不满意的其中一点是分层,只做了route层,没做controller层及api层。

细想想,我个人觉得业务可以放在route层做处理,也可以传递到controller层做处理。api层是与db打交道,或者与三方做交互(如request请求到java/go之类的,来获取数据)

所以对此的结论是api层必须要有,而controller层可以保留,看具体的业务逻辑复杂度。。api抽象出来一层,也有一个好处是将来如果要切GraphQL,也可以很方便地切了,同时也可以单独拿来做测试用例。

ApiResponse的必要性?

之前我在项目中有封装了一个ApiResponse,觉得在项目中有必要用到这个。

但当我看到这个代码时,发现我还是太年轻了。

其实完全可以用中间件的方式来实现。

app.use(router)之前,我们可以加一个新的中间件,譬如response

然后router里面,可以将data绑定到ctx.state.data上。再在response.js中做出相应的处理即可。

项目日志

这一块,我自己思路还没有彻底理通。基于扩展,我们要考虑以下几个事:

  • 日志分类(比如所有、db、error、crash崩溃)
  • 日志存放多久(比如所有的只要存一周,或者两周),避免硬盘空间被塞满
  • 统计API接口每天被调用的次数

针对三,像我司有一个日志系统,专门是用来分析日志这一块的。

针对一,目前可用的日志库:

针对二,可以用winston-daily-rotate-file,我个人这一块还没有彻底深入了解这个库,所以只能等日后深入了,再做补充吧。

项目配置

简单地说,拿我目前的项目来说,不同的环境,所要连接的mysql账号、minio配置肯定是不一样的。

业内普通是以下几个做法:

  • 区分环境,即利用node_env,来读取不同的配置文件
  • 搞一个config的html,通过用户自己填入信息,来生成config.js文件
  • 提供config.default.js文件,然后用户自己去copy这个文件,然后自己手动编辑文件
  • zookeeper(分布式的配置中心)

这一块我之前也翻了一些资料,让我找到一篇node.js 配置中心

公司也有一个自己的配置中心后台,但未打通node这一块。

希望自己有机会实践一下吧。。

本文链接:www.my-fe.pub/post/node-project-note.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。