问题描述
我试图让 ts-node 选项 --experimental-loader
与 mocha 一起工作,但没有运气。在我开始尝试编译 ES6 模块之前,我曾经能够以这种方式运行 mocha 测试:
"test": "nyc --reporter=html mocha --require ts-node/register src/**/*.spec.ts"
这在生成 ES6 模块时不再起作用。
我会使用 TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }'
解决方案进行测试,但由于另一个复杂因素,这对我不起作用:我正在生成 ES6 模块作为构建的第一步,但是也 使用 webpack 和 babel 生成 ES5/Commonjs 模块。除非我将 .js
添加到本地 TypeScript import
语句的末尾,否则最后一步不起作用。
但是添加这些 .js
扩展名会破坏 TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }'
解决方案,但是,如果我返回并删除所有 .js
扩展名,这将起作用。我显然不希望在测试和构建过程中我必须在添加和删除这些扩展程序之间来回切换。
为了简化现在,我已经去掉了 nyc,我正在尝试运行这样的测试:
mocha -r ts-node/register --experimental-loader ./ts-loader.mjs src/**/*.spec.ts
这种方式我没有遇到任何错误,但也没有任何反应。就像 src/**/*.spec.ts
不存在一样。
我什么都不做(现在)虚拟加载器看起来像这样:
console.log('ts-loader loaded');
export async function resolve(specifier,context,defaultResolve) {
console.log('resolve');
return defaultResolve(specifier,defaultResolve);
}
export async function getFormat(url,defaultGetFormat) {
console.log('getFormat');
return defaultGetFormat(url,defaultGetFormat);
}
export async function getSource(url,defaultGetSource) {
console.log('getSource');
return defaultGetSource(url,defaultGetSource);
}
export async function transformSource(source,defaultTransformSource) {
console.log('transformSource');
return defaultTransformSource(source,defaultTransformSource);
}
export function getGlobalPreloadCode() {
console.log('getGlobalPreloadCode');
return '';
}
我可以判断它已加载,因为 'ts-loader loaded'
消息出现,但没有调用任何函数。
我尝试过其他排列方式,但只是得到了诸如 src/**/*.spec.ts
被视为文字文件名而不是 glob 之类的错误,或者关于未找到模块的错误。
我希望看到我的加载程序为每个被处理的 import
调用,然后弄清楚如何操作文件扩展名,但我还没有做到这一点。有什么建议吗?
我正在使用节点 v14.15.1。可以在此处找到我的项目的完整代码,包含一个有效的构建,但测试失败:https://github.com/kshetline/tubular_math
解决方法
我终于找到了一个解决方案,尽管它不是我最初寻找的方向。我放弃了让 mocha 对额外的 .js
扩展感到满意,并找到了一种方法来让 webpack 在没有它们的情况下也满意。所以...
import { Angle,Mode,Unit } from './angle.js';
...回到...
import { Angle,Unit } from './angle';
我的测试脚本如下所示:
"scripts": {
"build": "rimraf dist/ && tsc && webpack && webpack --env target=umd","prepublishOnly": "npm run build","lint": "eslint 'src/**/*.ts'","test": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' nyc --reporter=html mocha --require ts-node/register src/**/*.spec.ts"
},
最后,最重要的是,我想出了如何让 webpack 5.x(4.x 没有这个问题)对没有 .js
扩展名的本地 JavaScript 导入感到满意,webpack如果您的 package.json
说 "type": "module"
,现在否则坚持:
module: {
rules: [
{ test: /\.js$/,use: 'babel-loader',resolve: { fullySpecified: false } }
]
}
...其中将 fullySpecified
设置为 false 是解决方案的关键。
更新:上面的例子是在一个特意简单的项目上完成的,对于初学者来说,用 ESM 模块生成 npm 包很容易。现在我正在尝试更高级的东西,我在运行单元测试时再次遇到了障碍。一旦 *.spec.ts 文件直接或间接导入外部代码,模块加载就会失败。在弄清楚如何解决该问题之前,我只能测试没有外部依赖项的代码。显然,使用 "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}'
只是让我更深入地解决与 ts-node 一起运行 mocha 的基本问题。