尝试通过 --experimental-loader 选项使用 mocha、ES6 模块和 ts-node

Posted

技术标签:

【中文标题】尝试通过 --experimental-loader 选项使用 mocha、ES6 模块和 ts-node【英文标题】:Trying to use mocha, ES6 modules, and ts-node with the --experimental-loader option 【发布时间】:2021-03-30 06:01:59 【问题描述】:

我正在尝试让 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, context, defaultResolve);


export async function getFormat(url, context, defaultGetFormat) 
  console.log('getFormat');
  return defaultGetFormat(url, context, defaultGetFormat);


export async function getSource(url, context, defaultGetSource) 
  console.log('getSource');
  return defaultGetSource(url, context, defaultGetSource);


export async function transformSource(source, context, defaultTransformSource) 
  console.log('transformSource');
  return defaultTransformSource(source, context, 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

【问题讨论】:

【参考方案1】:

我终于找到了一个解决方案,尽管它与我最初寻找的方式不同。我放弃了让 mocha 对额外的 .js 扩展感到满意的尝试,并找到了一种让 webpack 在没有它们的情况下满意的方法。所以...

import  Angle, Mode, Unit  from './angle.js';

...回到...

import  Angle, Mode, 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 的基本问题。

【讨论】:

以上是关于尝试通过 --experimental-loader 选项使用 mocha、ES6 模块和 ts-node的主要内容,如果未能解决你的问题,请参考以下文章

尝试通过Subprocess发送命令以使用ffmpeg进行操作

尝试通过 Vue Axios 加载 json

尝试通过电子邮件发送多个附件时出现 ActivityNotFoundException

尝试通过 Docker 安装夹层

尝试通过 AJAX 验证 Laravel 表单时出现错误 422

Python - 尝试通过 for 循环创建字典