eggjs-框架, 最近入了nodejs的坑…写给新东家的新框架,基于eggjs

 框架结构

  • app[框架主目录]
    • controller[控制器]
      控制器已实现路由的自动装载,只需要建立具体的控制器. 具体功能业务按需建立目录. 不要将不相干的业务揉在同一模块,同一控制器里.

      • admin[业务模块]
        • admin.js[控制器]
        • system.js[控制器]
    • extend[扩展]
      扩展目录中,可以给控制器,请求类,上下文扩展通用函数(https://eggjs.org/zh-cn/basics/extend.html)
    • io[socket控制器]
      特别注意,静态资源,控制器请求以及io请求,都是同一个端口.通过特殊解析实现具体访问.

      • controller[socket控制器]
        • client[socket模块]
          保留模块, 后续新socket编写需要单独建立模块目录,并在具体动作中实现业务逻辑. 同样在egg的基础上补充了自动路由装载的实现.

          • client.js[控制器]
            这个socket控制器为保留控制器, 为兼容原客户端的socket请求以及回调的特殊处理类. 所有原socket请求都会通过映射, 跳转到/app/service/client/*里的业务类进行特殊处理,并回调.原请求方式. io.emit(‘message’,{api:’login’,param:{username:’xxx’,password:’xxx’}},function(res){})新请求方式. io.emit(‘/admin/admin/login​​’,{param:{username:’xxx’,password:’xxx’}},function(res){})需要明确注意, socket本质上是不存在回调的. 只是socket.io-client内部和服务器实现了packetid为标志的特殊实现. 其它任何语言都没有…但然. 通过原理编写也行..原理:https://www.cnblogs.com/lightsong/p/10226940.html​​
      • extend[socket扩展]
        同/app/extend
      • middleware[socket中间件]
        • connection.js[连接中间件]
          建立链接时, 可以做权限校验
        • packet.js[数据包中间件]
          数据请求过程中触发
    • lib[工具类]
      引用方式按最原始的方式引用. 不封装引用的主要目的是保留代码提示.

      • common[通用工具目录]
        • commonHelper.js[原通用类 ]
          按需要加,不需要的不要乱加进来,明确功能的.建立目录单独存放​
        • expressHelper.js[快递通用类]
          快递一些通用的获取调用, 在各自模块中实现, 并提供统一调用. 通用类,根据类型去调用具体的帮助类, 减少过程式代码, 增加代码可读性
      • cngg[功能模块目录]
        不同于业务, 一般功能模块都有其特殊实现和封装. 单独放这里. 业务功能再在业务目录里实现. 最大限度避免代码混乱. 当扩展达到一定的重复性和可用性, 可以考虑写成插件

        • cnggHelper.js[菜鸟裹裹帮助类]
      • kdn[快递鸟目录]
    • middleware[中间件]
      个人建议称为中间处理件会相对好理解, 需要先了解下洋葱模型(https://eggjs.org/zh-cn/basics/middleware.html), 类似过滤器

      • commonRequest.js[通用请求中间件]
        将常规请求进行前置处理, 如get和body合并到ctx.request.params中. 不区分get和post.
      • mwAdminUser.js[用户请求权限中间件]
        实现用户的权限判断和拦截
    • model[数据模型]
      暂时使用的数据库是mongodb, 然后暂时选用的访问方式为mongose(https://mongoosejs.com/docs/guide.html), 同时提供原访问方式, 方便快速复用原代码(尽量能写成新的写成新的…别只复制粘贴…)

      • Admin[业务模块]
        特别注意,其它目录都是小写开头, 只有数据模型的目录和类是大写开头….

        • Admin.js[数据模型类]
          数据层可复用代码,尽量复用到数据模型. 业务层复用业务模型. 尽量减少重复代码. 如可以写一个函数load(id), 找不到直接报错. 后续通用调用即可.
    • public[静态文件]
      egg-static提供静态文件访问支持​, 同端口访问时. 如果路径为/public/则会自动进入该目录​, 客户端和小访问量服务器可以直接使用. 大访问量, 需要实际压力测试看看. 最好还是走nginx做反向代理.

      • assets[静态资源目录]
      • backstage[后端静态资源目录,主要是组件类封装]
        复制原资源文件, 暂时按习惯的来
      • upload[上传文件目录]
    • router[路由配置]
      • router.dev.js
        路由实际配置脚本, 自动化脚本能满足基本路由情况, 如果需要特殊路由或者兼容原路由. 可以单独在这个地方再补充映射https://eggjs.org/zh-cn/basics/router.html
    • schedule[计划任务]
      计划任务只需要复制即可使用, 但是发现需要重启服务才会引入, 需要研究下热部署?
    • service[业务]
      需要理解下新的设计分层, 该形式接近MVC, 但是不是MVC.常规MVC是模型,视图,控制器, egg 结构层是 数据层(model), 控制器(controller), 业务(service), 视图(view), 控制器只做权限以及参数校验, 具体功能封装到业务层中. ​主要目的是实现代码的高复用性.如登陆,封装成service.user.login(username,password), 后续任何地方都是调用这个业务, 即可实现登陆. ​同时后续的单元测试, 主要是测试业务类.同时, 业务需要以抛出异常的形式代替返回值判断, 并再最外层进行异常处理. 可大大增加代码的可读写以及编写. 避免没必要的各种判断​

      • admin[业务模块]
        • adminService.js[业务类]
          结构类似控制器, 全是只为处理具体业务代码
      • client[保留模块]
        原客户端的io调用使用的方式和egg-socket不一样. 未避免冲突, 单独配置一个io路由,并将原请求动作全部映射到这里的具体业务动作. 同时兼容了socket.io-client的回调

        • enterpriseService.js[原客户端所有socket调用]
    • view[视图]
      所有页面文件以*.ejs做后缀, webstorm,vscode等格式化和开发过程中<% %>会有代码提示, 会极大的提高开发效率, 测试过程中, 也可以考虑页面代码在<%%>中测试再贴回去. 页面保存是实时更新的. nodejs其它功能模块修改在ssd的情况下, 依然需要4,5 秒的重启

      • admin[模块目录]
        • site[控制器目录]
          • login.ejs[登陆页面]
            页面对应具体的控制器
      • layout[通用页面组件]
        • layout.ejs[图层]
          包含常用的静态资源文件引入, 控制器里渲染页面时, 图层会包裹具体的页面代码, 可以方便全局性调整. 对于可复用的页面组件, 都可以考虑封装成*.ejs或者作成vue组件, 按需要来
      • 200.ejs[通用消息提示页面]
      • 500.ejs[通用错误消息提示页面]
    • router.js[路由脚本]
      用于引用/app/router里的实际路由脚本​, 路由脚本在egg的基础上加了自动配置, 只需要复制或新增控制器, 就会自动添加路由
  • test[单元测试目录]
  • local_test[自己编写的框架外的测试脚本]
  • cache[缓存目录]
    如果使用缓存, 则目标缓存会生成到该路径下, 如果服务器有多节点. 缓存必需存放到redis或数据库, 不能配置单机的fs或内存缓存. 除非是代码或页面类缓存,视具体情况选择
  • config[配置目录]
    • locale[翻译目录]
      • zh-CN.js[翻译语言配置脚本]
        egg-validate的翻译,需要在这个地方进行配置
    • config.default.js[默认配置]
    • config.dev.js[具体环境配置脚本]
      可根据启动命令不同,加载不同配置文件,方便测试
    • plugin.js[插件配置]
      框架使用插件,必须在这个地方启用, 然后如果有特殊参数配置,在/config/config.default.js里进行详细参数配置. egg默认启用的插件需要到/node_modules/eggjs 里进行查看.
  • logs[日志目录]
    • test_egg[项目名]
      • common-error.log[常规日志]
      • egg-agent.log[agent日志]
      • egg-schedule.log[计划任务日志]
      • egg-web.log[egg内部日志]
  • package.json[配置文件]
    • 启动命令
      • 启动开发环境:npm run dev
        • 实际脚本:egg-bin dev –sticky –port 7001
      • 启动生产环境:npm run start
        • 实际脚本:egg-scripts start –daemon –sticky –port 7001
    • 启动模式
      • 框架是以 Cluster 方式启动的,而 socket.io 协议实现需要 sticky 特性支持,否则在多进程模式下无法正常工作。
    • 注意事项
      • 最好指定端口, 否则开发工具崩溃后, 重新运行, 会被重新分配端口, 避免带来不必要的问题
  • 框架保留问题, 需要找时间进行优化
    • 框架文件过多(超过3w+文件…)
      • 优化方向:减少不必要的扩展.
    • 重启速度需要再进行研究优化,在ssd的情况下, 重启服务需要大概4,5秒, 较影响开发, 不过配合调试模式, 可以弥补.
      • 优化方向:考虑单独写个启动脚本, 抛弃一些特性来实现热更新, 具体再观望看看别人有没有其它实现. 尽可能实现修改后马上可见.
    • 页面组件化
      • 优化方向:无
        • 还在学习和了解中.

2019-08至2020-01 半年份懒人笔记

宝塔CC时提示被屏蔽
  cc时直接抛出416不是很友好,而且有撞库的问题.
  function drop -- 如果已经被标记,则在这个地方抛出416
  function cc  -- 计数器.首次触发和标记
    补充html输出提醒 return_html22(config['cc']['status'],'
您的请求异常已被屏蔽,有需要请联系管理员(QQ:243008827)!
') svn 调整为主线分支类型,或者将某个目录的提交记录,导入到另一个库的某个分支中.   #将reposA导出到一个文件中   svnadmin dump reposA/ > f1     -r xx:xx 指定版本范围     --incremental 只进行增量导出.少这个会导致最后版本的整个目录被导出   #将reposA中的code过滤出来,svndumpfilter include表示只保留制定的目录和文件   svndumpfilter include dirB/code < f1 > f2   #将dumpfile2导入相应的目录,也就是reposB/dirAA/,用parent-dir来指定   svnadmin load reposB --parent-dir dirAA < f2   提交步骤是合并分支到主线,再提交.如果需要查看分支的日志,日志查询时,勾选底部显示合并分支日志. fish &&   make; and make install phash   mysql 用法 BIT_COUNT(img_dhash ^ b'01111') ,如果不是以b'xxx'形式.直接000111形式.会导致前面的数据丢失,出现奇怪的bit_count   感知算法走的是灰度.所以对颜色变化不敏感. 同时, 感知算法.更像是图片颜色分布识别. 并不能很好的识别图像以及内容....没有学习库还是不行. 考虑走百度的图片库或淘宝的商品图片库进行商品图片识别.     百度商品图片识别已测试.符合预期效果       百度入库一天1w免费,搜索500免费.基本够用(不够用就看老板钱包了~). nginx   一键防火墙 https://zhih.me/ngx-lua-waf/   nginx 编译后 在源码的 objs 里,要注意. nginx -V 观察编译参数   安装后,如果原来有安装后.替换 /usr/local/sbin/nginx 以及 /usr/local/nginx/sbin/   测试参数 /xxx.tar /xxx.sql 等. /?id=1 or 1=1 无效....,需要自行调整配置 elasticsearch   https://www.elastic.co/guide/cn/elasticsearch/php/current/_search_operations.html   elasticsearch sql     https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-xpack.html     配合postman测试     php 扩展       https://github.com/elastic/elasticsearch-x-pack-php   中文分词插件     https://www.jianshu.com/p/bb89ad7a7f7d     elasticsearch install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.5.0/elasticsearch-analysis-ik-7.5.0.zip       win file:///xxxx     外网开放       只改 0.0.0.0 会报错,需要配置下面两个参数,将服务器改成node       https://juejin.im/post/5cb81bf4e51d4578c35e727d   elasticsearch 降版本安装...     rpm remove elasticsearch     find / -name "*elasticsearch*" 删除所有出现的文件.不然安装低版本的会报错. rpm删除不干净导致日志部分报错 php barcode zbar   epel     wget https://download-ib01.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm     rpm -Uvh epel-release-6-8.noarch.rpm   yum install zbar-devel     zbarimg xxx.png 返回解析后的内容 php win 下 执行命令时, 报出一个奇怪的错误8, 切换php版本到5.6就正常, 比较神奇...原因不明 ss5 所需扩展包   https://blog.csdn.net/Vincent95/article/details/71172986 thinkphp   model update_time 被格式化问题     模型中,补充两个函数 setUpdateTimeAttr getUpdateTimeAttr 跳过系统自动格式化 php 线程安全和不安全会导致 ?undefined symbol:?core_globals 错误...   https://www.jianshu.com/p/e13efb052844 百度图片搜索坑   图片尺寸1000 + jpg... 切记不要听沙雕说尺寸问题.....漏了另一个 mysql 关联更新    update a inner join b on a.id = b.id set a.xx=b.xxx where b.xx=xxx thinkphp 命令行模式   命令行模式一直找不到的问题   configure 动作中 setName 必需为小写且与类同名   php think xxx     think 只是一个没有php后缀的php文件 rabbitmq   php 后台运行 nohup php xxxx &   消费者消费后,标记消息     $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);   php 多线程折腾起来麻烦事较多,通过 rabbitmq 做异步消息,并补充多个消费者...加快执行速度,相对来说改动和影响较小. recaptcha 人机交互验证   https://www.google.com/recaptcha/admin   注册.获取网站密钥和通讯密钥     页面demo:https://developers.google.com/recaptcha/docs/display     服务器demo:https://developers.google.com/recaptcha/docs/verify#api_request   国内使用     www.google.com 替换成 www.recaptcha.net 即可(js以及接口地址) webstorm   鼠标移动,代码提示开启     Setting->Editor->General->show quick documentation on mouse move uniapp h5 收录之神坑   #只会在客户端, 并不会传递到服务器端,导致路由参数无法传递到服务器端. 即使服务器端渲染出了静态页面, 也没用.     解决方案只能等官方的uniapp出正式的ssr 或者废了uniapp 用普通语言重写     所以官方说即使配置了关键字,二级页面也不会被收录,推荐走百度小程序....       如果不是因为#后传递参数,还可以通过chrome headless 进行静态页面渲染   发个福利...chrome headless 获取页面渲染后文档结构...     const content =await page.content(); 如果搞采集,还是不错的....vue.也可以采集和截图 tmux   https://www.ruanyifeng.com/blog/2019/10/tmux.html   tmux new -s 1     tmux ls 显示列表     ctrl b + w 显示列表并切换     ctrl b +c 新建     ctrl b + % 分屏     ctrl b + 上下左右 控制分屏     ctrl b + z 当前窗口最大化/恢复(第二次)     ctrl b + x 关闭   附加功能,通过tmux打开,shell不会断线...哈哈... ss一键安装脚本国内安装问题...   没错,是要在国内装,做国内的代理. 打开安装脚本. 补充代理设置或者直接下载安装文件. 下载特别慢的. 手动下载,然后按照安装方式安装. puppeteer 报错 Chromium revision is not downloaded   const browser = await puppeteer.launch({     //多加这个参数写死路径    executablePath: '/usr/bin/google-chrome'     ....   服务器网页截图,拦截百度统计脚本...   特别需要注意截图的页面是否有出现死循环的问题...,同时为了优化速度,只保证打开指定域名的资源,其它资源全部屏蔽     await page.setRequestInterception(true);     await page.on('request', request => { request.url()='' ; request.abort();/request.continue(); }) php 命令行情况下,久了mysql会出现has gone away问题   wait_timeout 默认为28800,也就是说,用久了.很容易出现掉链的问题. 反过来说,要测试也容易了,改小这个值.然后执行域名命令行.再访问数据库即可.   thinkphp 数据库补充重连参数 'break_reconnect' => true, rabbitmq 消费报错时,延迟重新执行   消息报错时处理,多声明一个交换机和队列, 关键参数     x-message-ttl 超时时间     x-dead-letter-exchange 队列超时后,,进入的路由.设置原来队列的交换机即可     x-dead-letter-routing-key 下面同上     重新发送的队列的交换机记得不要和原队列相同. 原理是       声明两个通道,原消息队列和延迟发送的消息队列,一个消费者,消费消费报错时,将消息重新发送到延迟发送队列,超时触发,然后进入死信,也就是回到了原来的消息队列,这样形成一个反复执行的过程. 然后通过rabbitmq的管理平台手动进行调控.   https://my.oschina.net/huaxian8812/blog/780086 elastcisearch 帐号密码访问   https://juejin.im/post/5c9c58fa5188250ef95d8b3c   配置     xpack.security.enabled: true     xpack.security.transport.ssl.enabled: true   postman中     http://user:pass@localhost:9200 sdk中同样是补充帐号密码前缀进行登陆 手机浏览器安装谷歌扩展   https://smartphones.gadgethacks.com/how-to/use-desktop-chrome-extensions-android-0196246/   安装 kiwi 浏览器     打开 chrome://extentions 敏感词/敏感图片过滤   走微信免费接口     敏感图片, 没有做ocr处理, 色*图片会被检测出来, 但是敏感词截图, 会识别不出来...   easywechat win 下图片上传报请求超时错误, 参数名补充@即可. linux下不会, 待核实具体问题点. mysql 主从复制   主机从机配置     https://www.jianshu.com/p/b0cf461451fb   从机延长同步时间参数     MASTER_DELAY=xxx     查了文档. mysql 8.0 才是每次传输时补充延迟, 5.7只在第一次延迟,后续都实时同步...,改成计划任务,通过计划任务控制,做延迟同步实现.       获取主机binlog当前位置. 然后从机开启, 等位置达到时,停止...   中文详细总结     https://www.fooher.com/20170502_53.html   官方配置参数列表     https://dev.mysql.com/doc/refman/5.7/en/replication-options-slave.html   主从错误详细说明     http://xstarcd.github.io/wiki/MySQL/online_mysqlrepl_error.html   ssh 稳定通道 autossh + 公钥登陆(不知道为啥ssh-copy-id不成功,我直接手动粘贴到/root/.ssh/authorized_keys 一行一个公钥, 记得得开启允许公钥登陆/etc/ssh/sshd_config 里)     id_xx为默认私钥和公钥, 如果不是默认,需要通过-i 单独指定私钥     https://freeman.one/2018/12/08/ssh-tunnel/ mysql 误删除超快速恢复方案   利用主从实现数据库同步,再通过追加延迟参数,这样的数据库可以做为一个延迟备份数据库, 出现误删除操作时, 可以从这个比较慢同步的数据库中快速回复所需的数据.   恢复所需数据时,可以将商品id放入临时表中, 通过临时表,可以快速识别出丢失的数据然后进行恢复.   主从时, 主从复制时, 如果备份机或只读的那台. 没有什么特殊操作...空间比较小的时候. 可以考虑关闭binlog, 或者调整为2天. 默认是10天. 会导致生成的文件占用非常多的空间. editplus 搜索文件技巧   Search->Find in Files     包含的文件, 如果有多个的,用 ";" 进行分隔, 不需要搜索的, 也一样是通过";" 进行分隔. find 命令删除文件时, 如果文件包含空格或特殊字符导致的报错(rm: invalid option -- )处理   find . -name "*284x*" -print0 | xargs -0 rm -rf   find 命令详解     https://wangchujiang.com/linux-command/c/find.html 共享目录报错提示 无法访问,你 中能没有权限访问网络资源   凭证管理器, 手动添加权限   https://blog.csdn.net/luman1991/article/details/71248761 sqlserver 默认访问,无法通过端口访问问题   需要在服务器开启监听全部,才能通过端口访问, 不清楚默认情况下走什么协议     sql server 网络配置-mssqlserver的协议>tcp/ip 是否启用, 属性中是否监听全部   查询当前所监听端口     exec sys.sp_readerrorlog 0, 1, 'listening'     正常需要看到5条记录,1434和1433   sa 登录需要在安全中设置为混合登录. nodejs 热更新   require 只会引入一次,必定是有缓存,同时是以绝对路径为缓存标志,路径分割是"\",win下如果出现拼接时,需要注意"/",需要替换成目标路径     检测文件是否被二次加载,只需要在加载文件中console.log即可   删除缓存     delete require.cache[pwd];   isntall 时报错 operation not permitted     需要删除lock文件     package.json 不存在, 只能npm init初始化... 不保留svn是原罪. navicat 12.1.x注册提示找不到rsa   文件都复制到目录, 最好删除原来的, 然后安装时路径多个加版本号.   以管理员权限运行注册机, 其它参考教程 egg-view-ejs 配置正确还报错:Can't find viewEngine   检查 cxt.render 前是否有加await. VMware 虚拟机无法复制   虚拟机设置,选项,客户机隔离,取消,再保存一遍