关于Midwayjs启动缓慢的问题

407 阅读3分钟

1. 前提

Midway 设计之初就可以兼容多种上层框架,比如常见的 ExpressKoaEggJS 。 本文关于启动缓慢的问题是针对特定的@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',
  },

2.5 定期删除logs和run里面的文件有助于速度提升