node-fetch 3.0.0 和 jest 出现语法错误: Cannot use import statement outside a module。

35

我正在尝试升级我的api以使用node-fetch 3.0.0。他们文档中的破坏性变更之一是node-fetch现在是纯ESM模块。

https://github.com/node-fetch/node-fetch/blob/main/docs/CHANGELOG.md

这个改变已经导致了我的单元测试出现问题。我曾使用jest.requireActual("node-fetch")来获得Response对象。

const { Response } = jest.requireActual("node-fetch");

然而,使用新的更改后,我得到了以下错误信息:

"在类型“{}”上不存在属性“Response”。"

我尝试了更改为import语句,这似乎修复了该错误:

import { Response } from "node-fetch"

现在,当我运行单元测试时,我得到了以下错误:

Test suite failed to run
                                                                                                                                                                                                                                                                                                                                                                                         
    Jest encountered an unexpected token                                                                                                                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                                                                                                                                                         
    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                         
    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".                                                                                                                                                                                                                                                                          

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    C:\Users\{mypath}\api\node_modules\node-fetch\src\index.js:9
    import http from 'http';
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      2 | import { AuthProvider, TokenCache } from "./tokenTypes";
      3 | import { getUserEmail, getUserId, getUserRole } from "../common/authUtil";
    > 4 | import fetch from "node-fetch";

错误似乎发生在node-fetch本身。

我尝试更改package.json中的测试脚本,以匹配jest文档建议的ESM模块。 https://jestjs.io/docs/ecmascript-modules

package.json

"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
文档还建议在jest.config.js中将transform属性更改为一个空对象,但是我的typescript和ts-jest的转换对象如下所示:

jest.config.js

transform: { "^.+\\.ts?$": "ts-jest" }
如果我将其更改为空对象,则所有测试都会失败。我对CJS与ESM并不十分熟悉,因此希望能得到帮助。
2个回答

13

Fetch 3.0是设计用于使用esmodules而不是commonjs。因此,您必须确保将其导入到模块中。

例如:要将其导入到app.js中:在package.json中添加"type":"module",然后导入它。

要将其导入到其他文件或甚至app.js中,您也可以将扩展名从.js更改为mjs,这将告诉nodejs将其视为esmodule。

否则,请降级fetch以使用支持commonjs的旧版本,例如2.something。

npm install node-fetch@2
npm install @types/node-fetch@2

1
我已经添加了"type":"module"并将我的jest.config.js更改为"export default"而不是module.export。我仍然收到以下错误。“import http from' http'; ^^^^^^`SyntaxError:无法在模块外部使用导入语句1 |从"@ jest / globals"导入{jest}
2 |从"node-fetch"导入{Response}“
同样适用于 4 |从"node-fetch"导入获取;
- avenmia
5
这不是解决问题的办法。 - VityaSchel
降级到@2 对我有用,而且没问题,因为我只需要在测试期间使用它。 - Robert Pazurek
我已经添加了"type":"module",但它仍然不起作用。 :( - MrHIDEn

2
我有同样的问题!添加
 transform: {
    "^.+\\.(ts|tsx)$": "ts-jest",
    "^.+\\.(js)$": "babel-jest",
  },
  transformIgnorePatterns: [
  ],

对于我的jest.config.js文件的修改解决了这个问题。 顺便说一下,这是我的版本:

    "jest": "^27.3.1",
    "ts-jest": "^27.0.7",
    "node-fetch": "^3.1.0"

10
仍然遇到错误,即使在 ts-jest 的相同 transform 选项下。 - mikemaccana
它解决了我的问题。 - Amerrnath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接