ThinkJS3升级之路

是否要升级

CmPage后端的NodeJS框架,当初选择的是ThinkJS,主要是用async/await的写法比较符合一般的思维习惯,也适合写一些比较复杂的业务逻辑,ThinkJS升级到版本3.x以后,基于koa2进行了重构,和之前的版本改动还是蛮大的,之前也曾经考虑想采用过Egg.JS,不过所需时间成本应该会比较大。CmPage是否要升级的问题,答案其实是明确的,只能跟着走呗,难道要自己去维护ThinkJS2。有的时候实际项目中也经常会碰到类似情况,很无奈啊,大部分开源项目都是小众的,重构的频率比商用系统要快得多。
当然升级到ThinkJS3后,可以更方便地采用各种koa的资源,也可以多一些选择,说干就干,利用国庆被堵在家里的时间做点有意思的事情(有意义还不好说^-^)。

升级杂项

  1. 关于数据库的选择,之前CmPage考虑了多种数据库,主要测试了Mysql、PostgreSql和MSSQL(ORM采用的是sequelize),直接写SQL语句的话还是有不少区别的,数据类型的格式处理也有差异。考虑到cmpage还是个比较新的项目,数据库改为支持mysql,插件采用think-model-mysql,等框架的功能齐全和稳定后再考虑其他的数据库类型;
  2. 关于cmpage和应用系统的代码分离,稍微大一点的企业,他的IT信息化应用都会有多方面的需求,我们就可能会构建多个系统,由不同的团队进行维护,这样如果cmpage升级的话就比较麻烦。之前考虑EggJS也是这个原因,据其文档说可以方便地进行框架和插件的开发,试了一下也不是很方便,还是需要踩坑(总的来说还是时间不够,ps:程序员的焦虑),但话又说回来,目前开发业务系统的过程中还是需要随时查看框架的代码,甚至改改弄弄什么的才能较好地进行调试。
    因此和数据库的选择一样,考虑东西太多了就会束手束脚,还是暂不考虑。
  3. 关于工作流的考虑同上,先实现简单的状态流转类的工作流,而且是面向开发人员的,当然cmpage本身就是面向开发人员的,非傻瓜式。
  4. 修改继承类 think.controller.base, think.logic.base,think.model.base 改成 think.Controller, think.Logic, think.Model,继承的语法export default class extends XXX 也改成了 module.exports = class extends XXX
  5. 去掉 sequelize,改用 think-model-mysql,新建一个空的model文件 src/cmpage/model/base.js就行了,因为之前base.js的方法名称做了兼容性处理;
  6. controller中有this.http的地方换成 this.ctx,ThinkJS3中很多方法名称没有变,但换了所属者了;
  7. 数据库配置原先在各个模块中,现在统一配置到 /src/common/config/adapter.js中;
  8. 默认数据库为admin,在直接调用cmpage的表t_xxx时需要加上数据配置,如 this.model(‘t_module’,’cmpage’)
  9. 删除原错误处理页面,采用Thinkjs默认的处理;
  10. 修改ThinkJS的校验配置,把原先 src/common/config/locale/zh-cn.js中的中文错误信息,配置到src/common/config/validator.js中,稍作修改。/src/cmpage/logic/page.js中增加aliasName的处理。
  11. 文件上传的处理需要修改,具体参见 /src/cmpage/controller/page.js中的upload_fileAction;
  12. controller中驼峰命名的方法,改为下划线,如 uploadFileAction 改为 upload_fileAction,注意是区分大小写的。

升级感受

本次升级比我想象中的要顺利些,改动也不算特别多,绝大部分代码还是可以用的。还好没有采用EggJS进行升级,当然可能也不是那么复杂呢,谁知道呢,和多数其他的选择一样,机会成本是必须的。

补充事项

随着对thinkjs3的各种概念的熟悉,对cmpage的架构也多了一些考虑。

一、业务模块的基类采用 think.Service

业务模块的实现类是否应该从 think.Model 继承? Model主要实现了ORM部分,而cmpage的业务模块更多的是处理页面和实际的业务逻辑,用到数据库的时候才会去调用ORM,有时的频率还是偶尔,因此作为‘组成’比较好,think.Service是个空类,根据配置会增加一些成员(如model,fetch等),是个组合的过程,较为灵活,因此采用think.Service作为所有业务模块的基类应该更为合理,说干就干。
1. 把所有model目录名称改为service,把cmpage.model函数重新实现为 cmpage.service,并将所有调用的地方替换掉(vscode的全局查找和替换还是蛮好用的^-^);
2. 查找所有用 this.model 的地方,看看如果是调用模块的,改为 cmpage.service;
3. 修改业务模块实现类的构造函数,用 this.connStr = ‘cmpage’; 来指定其他数据库连接参数,修改基类 cmpage/service/base.js 中的 query 方法,使之可以操作不同的数据库执行 sql 语句;

module.exports = class extends think.Service {
    constructor(){
        super();
        this.connStr = 'admin'; //默认连接参数
        this.cmpage = require('../cmpage.js');
    }

    /**
     * 执行原生SQL语句,取结果集返回
     * @return {array} 查询结果集
     * @param {string} sql
     * @param {object} options 参数设置
     * @param {string} connStr 数据库连接参数配置,可以临时指定,这样业务类可以操作不同的数据库
     */
    async query(sql,options,connStr) {        
        const connName = connStr ? connStr : this.connStr;
        // debug(sql,'base.query - SQL');
        return await this.model('',connName).query(sql,options);        
    }

}

4.有些直接从 think.Model 继承的业务类,改为从cmpage/service/base.js 继承。

接下来, 完各种出错和调试的 ,总算没有太复杂的地方,稍微调整一下就完事了,目前一切正常 ^-^

二、增加cmpage对象的智能提示

cmpage对象原先是直接增加到global上的,记得好像2.0的时候写cmpage.xxxx的时候vscode还是有智能提示,但现在没有了。如果要有智能提示,需要显式地让vscode知道有个常量是从某个文件中导出的,因此需要在controller和service的基类中增加成员变量,这样用 this.cmpage.xxxxx 就有提示了,而且用F12也可以导航了,可以提高一些开发效率。
用 think.service() 实例化的对象也是没有智能提示的,因为vscode找不到出处(如果thinkjs有个插件啥的就好了),因此,如果需要有提示什么的,可以用 const XXX = require(); const xxx = new XXX(); 的方式;这样再写 xxx. 的时候,就有成员方法等提示了。但这种事直接加载静态文件,和用think-loader加载的方式还是有区别的,因此写service的时候尽量用 think.model等全局方法,以减少依赖,不排除后期两种方式的差异会越来越大。

三、定时任务设置与实现方式

thinkjs3 提供了定时任务模块,只要简单配置一下就能启动定时执行一些任务,但我希望能在UI界面上体现有哪些任务,可以随时启动、停止啥的,并且有对应的日志记录,出现错误的时候可以多种方式通知到某些人,或者后续还有其他功能要增加,通过查看think-crontab、think-loader等源码,可以看出定时任务是在系统启动时通过加载相应的config 文件来实现的,不能通过 think.config(‘crontab’)等方式来修改,但可以通过修改配置文件 /src/demo/config/crontab.js 来重新设置定时任务。
因此,我们完全可以在界面上有个按钮,点击调用后台方法,把数据库中的任务设置转换成配置文件的格式,写入到配置文件中,thinkjs会检测到源码的变动,从而重新加载配置文件。
剩下的事情就顺理成章了 ^-^

你可能感兴趣的:(企业信息化框架)