1. 前提
Midway 设计之初就可以兼容多种上层框架,比如常见的 Express、Koa 和 EggJS 。 本文关于启动缓慢的问题是针对特定的@midwayjs/web:EggJS 框架。
Midway 有多套技术方案可以选择,我们以部署的方式来做区分, 本次解决方案中会部分涉及到部分拓展组件的优化。
2.方案
2.1 关闭每次 require 的类型检查
Midway 在本地开发时会使用 ts-node 实时扫描并 require 模块,如果 ts 文件太多(比如 200+)个,启动时可能会导致比较慢,在 Windows 下非 SSD 硬盘的情况下特别明显,导致 ts-node 的类型检查的 Server 频繁 fullGC,每个文件加载可能会达到 1-2s。
优化: 在开发环境下,关闭每次 require 的类型检查。代价是启动运行时不会做类型校验,由于一般在编辑器里已经有提示,运行时不再做检查也可以。
步骤: 在执行midway-bin dev命令前增加下面两个环境变量。
TS_NODE_TYPE_CHECK=false TS_NODE_TRANSPILE_ONLY=true
比如:
cross-env TS_NODE_TYPE_CHECK=false TS_NODE_TRANSPILE_ONLY=true NODE_DEBUG=midway* NODE_ENV=local midway-bin dev --ts
2.2 采用swc的js编译器
swc,根据官方测试, 对比 babel,swc 有至少 10 倍以上的性能优势
2.3 根据自身业务在tsconfig.ts中排除不需要编译加载的文件
比如:
"exclude": [
"dist",
"node_modules",
"test",
"src/storage",
"run",
"logs",
"typings"
]
2.4 删除Egg框架中的内置插件
大家可以在midway启动后的run中有几一些文件: agent_timing_[pid].json: 展示了从进程分配到启动完成,各模块的加载顺序和耗时。 agent_config.josn: 展示了项目中所有的配置文件,包括egg的内置插件情况。
我们从agent_timing_[pid].json中看到Process Start花费了6-7秒,Application Start在半秒左右,这是由于框架或者电脑配置自身原因,无法优化。但是我们往下可以看到egg-mock这种用于测试的插件也在每次编译中耗费时间。
{
"name": "Process Start",
"start": 1650941616033,
"end": 1650941621754,
"duration": 5721,
"pid": 25168,
"index": 0
},
{
"name": "Application Start",
"start": 1650941621754,
"end": 1650941622151,
"duration": 397,
"pid": 25168,
"index": 1
},
{
"name": "Require(10) C:/Users/Chunmei.Xia/Documents/Cloud-Frontend/Yoda-Backend/node_modules/egg-mock/app/extend/application.js",
"start": 1650941621797,
"end": 1650941621902,
"duration": 105,
"pid": 25168,
"index": 15
},
上面我们从agent_timing_[pid].json中看到有一些无用的内置插件在耗时,我们具体转到 agent_config.josn文件查看一共有哪些插件,而且查看这些插件是否开启。 下面截取的文件部分可以看到有一些egg内置开启的插件,其实我们并没有用到,我们可以在项目中禁用掉,以节省插件的一个加载时间。
"plugins": {
"onerror": {
"enable": true,
"name": "onerror",
"dependencies": [],
"optionalDependencies": [
"jsonp"
],
"env": [],
"from": "C:\Users\Chunmei.Xia\Documents\Cloud-Frontend\Yoda-Backend\src\config\plugin.ts",
"package": "egg-onerror",
"path": "C:\Users\Chunmei.Xia\Documents\Cloud-Frontend\Yoda-Backend\node_modules\egg-onerror",
"version": "2.1.0"
},
"session": {
"enable": true,
"package": "egg-session",
"name": "session",
"dependencies": [],
"optionalDependencies": [],
"env": [],
"from": "C:\Users\Chunmei.Xia\Documents\Cloud-Frontend\Yoda-Backend\node_modules\egg\config\plugin.js",
"path": "C:\Users\Chunmei.Xia\Documents\Cloud-Frontend\Yoda-Backend\node_modules\egg-session",
"version": "3.3.0"
},
"i18n": {
"enable": false,
"package": "egg-i18n",
"name": "i18n",
"dependencies": [],
"optionalDependencies": [],
"env": [],
"from": "C:\Users\Chunmei.Xia\Documents\Cloud-Frontend\Yoda-Backend\node_modules\@midwayjs\web\config\plugin.js",
"path": "C:\Users\Chunmei.Xia\Documents\Cloud-Frontend\Yoda-Backend\node_modules\egg-i18n",
"version": "2.1.1"
},
步骤: 通过分析 agent_timing_[pid].json,agent_config.josn文件,我们发现可以在config/plugin.ts中禁用掉eggjs如下插件,虽然控制台会报错,但是并不影响midway的使用。
'egg-mock': {
enable: false,
package: 'egg-mock',
},
jsonp: {
enable: false,
package: 'egg-jsonp',
},
onerror: {
enable: false,
package: 'egg-onerror',
},
security: {
enable: false,
package: 'egg-security',
},