Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typescript + egg-mock cluster 報錯 #3930

Closed
alickmail opened this issue Sep 10, 2019 · 17 comments
Closed

Typescript + egg-mock cluster 報錯 #3930

alickmail opened this issue Sep 10, 2019 · 17 comments
Assignees

Comments

@alickmail
Copy link

What happens?

使用 Typescript + egg-mock 的 mm.cluster 起动後,出现 nodejs.Error: Please set config.keys first 错误

我知道 npm start 前需要 npm tsc,这样起动是没问题的。但 mm.cluster 跑测试就会出现问题。

最小可复现仓库

请使用 npm init egg --type=simple bug 创建,并上传到你的 GitHub 仓库
https://github.com/alickmail/typescript-eggjs-mm-cluster-error

复现步骤,错误日志以及相关配置

  1. git clone https://github.com/alickmail/typescript-eggjs-mm-cluster-error
  2. npm install
  3. npm run 'test-cluster'
  4. 在 chrome 访问 localhost:17001
  5. 出现 nodejs.Error: Please set config.keys first 错误

使用 egg-mock cluster 的原因是 egg-socket.io 必须使用 cluster 模式才能成功测试

參考:

https://github.com/eggjs/egg-socket.io/blob/master/test/io.test.js

相关环境信息

  • 操作系统:macOS Mojave (Mac Pro)
  • Node 版本:v10.13.0
  • Egg 版本
 "egg": "^2.6.1",
 "egg-scripts": "^2.6.0"
 "egg-ci": "^1.8.0",
 "egg-bin": "^4.11.0",
 "egg-mock": "^3.16.0",
 "tslib": "^1.9.0",
 "tslint": "^5.0.0",
 "tslint-config-egg": "^1.0.0",
 "typescript": "^3.0.0"

謝謝

@alickmail
Copy link
Author

这是 egg-mock/lib/start-cluster 文件,只要加入这句就能解决找不到 config.default.js 的问题

#!/usr/bin/env node

'use strict';

if (process.env.EGG_BIN_PREREQUIRE) require('./prerequire');

const options = JSON.parse(process.argv.slice(2));
if(!options.require) {
  options.require = [];
}

options.require.push(require.resolve('ts-node/register')); // 加入这句
require(options.framework).startCluster(options);

期待更好的解决方案,谢谢!

@atian25
Copy link
Member

atian25 commented Sep 10, 2019

cluster 里面是不可能去加 ts-node 的,我印象中 egg-bin 已经会判断然后注入 ts-node 的了。

cc @whxaxes

@alickmail
Copy link
Author

我明白在生产环境是不用加载 ts-node ,因为生产环境是是用 tsc 生成好的 js。

但是如果我要跑 socketio 的测试,我必须使用 egg-mock 的 mm.cluster。这里是例子:
https://github.com/eggjs/egg-socket.io/blob/master/test/io.test.js

当我调用

app = mm.cluster({
      baseDir: '../../',
      coverage: false,
    });

cluster.js 会使用 start-cluster 的 script,fork 一个 process 出来,我估计就是 fork 出来的这个 process 没有支持 ts

#!/usr/bin/env node

'use strict';

if (process.env.EGG_BIN_PREREQUIRE) require('./prerequire');

const options = JSON.parse(process.argv.slice(2));

require(options.framework).startCluster(options); <- 这里是在没有 ts 支持

谢谢

@atian25
Copy link
Member

atian25 commented Sep 10, 2019

egg-bin 的 ts-node 应该会继承下去吧,可能没放 env 里面。

可以先:

mm.cluster({
   baseDir: '../../',
   coverage: false,
   opt: {
     execArgv: [ '--require', require.resolve('ts-node/register') ]
   }
});

可以试下这样,cluster 是继承 coffee 的,我记得有个 opt 的参数的。

@ahungrynoob
Copy link
Contributor

遇到相同的问题 加了opt就报了另外的错误:

/Users/xudading/work/lazada/iris-proxy/node_modules/[email protected]@typescript/lib/typescript.js:122217
                throw new Error("Could not find sourceFile: '" + fileName + "' in " + (program && JSON.stringify(program.getSourceFiles().map(function (f) { return f.fileName; }))) + ".");
                      ^
Error: Could not find sourceFile: '/Users/xudading/.node-spawn-wrap-75420-68ff7c5550db/node'

@ahungrynoob
Copy link
Contributor

egg-bin test 没有问题 egg-bin cov 会有上面的问题

@ahungrynoob
Copy link
Contributor

ahungrynoob commented Sep 22, 2019

找到根本原因了 https://github.com/istanbuljs/spawn-wrap/blob/master/lib/mungers/node.js#L60
https://github.com/istanbuljs/nyc/blob/cfd3da05156b98952f03f7be2dd3d23ba328073f/bin/nyc.js
这里加了shim ts直接报错了

[ '/Users/xudading/work/lazada/iris-proxy/node_modules/node/bin/node',
  '--require',
  '/Users/xudading/work/lazada/iris-proxy/node_modules/[email protected]@ts-node/register/index.js',
  '--require',
  '/Users/xudading/work/lazada/iris-proxy/node_modules/[email protected]@source-map-support/register.js',
  '/Users/xudading/.node-spawn-wrap-85177-a701b28fe038/node',
  '/Users/xudading/work/lazada/iris-proxy/node_modules/[email protected]@egg-mock/lib/start-cluster',
  '{"baseDir":"/Users/xudading/work/lazada/iris-proxy","cache":true,"coverage":true,"clean":true,"sticky":true,"framework":"/Users/xudading/work/lazada/iris-proxy/node_modules/egg","customEgg":"/Users/xudading/work/lazada/iris-proxy/node_modules/egg","plugins":{"egg-mock":{"enable":true,"path":"/Users/xudading/work/lazada/iris-proxy/node_modules/[email protected]@egg-mock"}},"port":17001,"workers":1}' ]

这个shim 应该放到node_modules下面就不会报错了

@ahungrynoob
Copy link
Contributor

最终解决方案:
package.json中修改为:

"cov": "SPAWN_WRAP_SHIM_ROOT=\"node_modules\" egg-bin cov --ts"

@atian25
Copy link
Member

atian25 commented Sep 23, 2019

看起来是没权限写入 HOME,为啥?

可以提个 PR 给 mm.cluster 把这个 env 内置进去

@ahungrynoob
Copy link
Contributor

@atian25 没权限写入HOME是那个人的情况,我这边是因为这个shim的路径在HOME,导致typescript报Could not find sourceFile,我把source file都打印出来了,都是一些单测覆盖到的源文件和.d.ts文件,我理解应该HOME不在typescript的file文件查找范围,cwd/node_modules就可以 ,忙完这阵 我pr 一个~

@atian25
Copy link
Member

atian25 commented Sep 27, 2019

land [email protected]

@atian25 atian25 closed this as completed Sep 27, 2019
@whlsxl
Copy link

whlsxl commented Feb 21, 2020

egg-bin 的 ts-node 应该会继承下去吧,可能没放 env 里面。

可以先:

mm.cluster({
   baseDir: '../../',
   coverage: false,
   opt: {
     execArgv: [ '--require', require.resolve('ts-node/register') ]
   }
});

可以试下这样,cluster 是继承 coffee 的,我记得有个 opt 的参数的。

看了下,mm.app不支持opt

mm.app(
   baseDir: '../../',
   coverage: false,
   opt: {
     execArgv: [ '--require', require.resolve('ts-node/register') ]
   }
)

@atian25
Copy link
Member

atian25 commented Feb 21, 2020

因为 cluster 是继承 Coffee 的,而 app 是为了单测速度在单进程里面做。

@whlsxl
Copy link

whlsxl commented Feb 21, 2020

因为 cluster 是继承 Coffee 的,而 app 是为了单测速度在单进程里面做。

遇到个尴尬的问题,在js项目里,测试加载ts的apps。

难道只能分开两个命令?

@atian25
Copy link
Member

atian25 commented Feb 21, 2020

这不是命令啊,你一个单测不是有个 case 么,一个用 mm.app,一个用 mm.cluster 啊

@whlsxl
Copy link

whlsxl commented Feb 23, 2020

最小版本
这个需求比较特殊,在js项目里运行ts测试,
npx egg-bin test --ts=true test/app/run.test.js 的话,提示TypeError: Class constructor BaseContextClass cannot be invoked without 'new'
直接testts文件没编译,还是会报错。
麻烦 @atian25 帮忙看下。

@whlsxl
Copy link

whlsxl commented Feb 24, 2020

@atian25 是这个写test的需求
eggjs/egg-graphql#30 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants