开玩笑设置“SyntaxError:意外的令牌导出”

Posted

技术标签:

【中文标题】开玩笑设置“SyntaxError:意外的令牌导出”【英文标题】:Jest setup "SyntaxError: Unexpected token export" 【发布时间】:2017-07-04 18:05:20 【问题描述】:

我正在对当前没有测试的现有项目实施测试。我的测试无法编译 node_modules/ 导入。

/Users/me/myproject/node_modules/lodash-es/lodash.js:10
export  default as add  from './add.js';
^^^^^^
SyntaxError: Unexpected token export
  
  at transformAndBuildScript (node_modules/jest-runtime/build/transform.js:320:12)
  at Object.<anonymous> (app/reducers/kind_reducer.js:2:43)
  at Object.<anonymous> (app/reducers/index.js:12:47)

我发现的解决方法是在 package.json jest 配置中将node_modules 列入“白名单”,如下所示:

"jest": 
    "transformIgnorePatterns": [
      "!node_modules/"
    ]
  

这似乎是个 hack,因为运行一个导入 node_modules/lodash-es/lodash.js 的简单测试需要 1 分钟多的时间。

【问题讨论】:

很多节点模块都导出 ES5,这样 jest 可以直接运行它而无需转换。这就是为什么默认情况下 jest 不会转换 node_modules。在这种情况下,lodash-es 专门导出 es 模块,因此您必须让 jest 转换该代码。如果您在 transformIgnorePatterns 中使用 "!node_modules/lodash-es" 来代替 jest 仅在 lodash-es 上运行 babel,您可能是安全的。 【参考方案1】:

如果上述解决方案都不适合您,您可以开玩笑地尝试一下

"moduleNameMapper": 
    "^lodash-es$": "lodash"

它将在测试运行时将lodash-es替换为commonjs版本。

【讨论】:

我讨厌这是唯一对我有用的答案。必须有比两次将 lodash 作为依赖项更好的方法 @jamesthollowell 您不必直接依赖它,因为您很可能已经通过另一个软件包深深地依赖它。我真的不建议这样做,但如果你不想在你的 pkg.json 中有另一个条目,你可以这样做。 谢谢,这是唯一对我有用的解决方案。 transformIgnorePatterns 方法对我不起作用。 @jamesthollowell,你只需要lodash in devDependencies,用于测试。所以它不会影响您的捆绑包大小。您仍然可以在整个应用程序中使用 lodash-es 导入。 此解决方案似乎比transformIgnorePatterns 快得多。 (我的测试套件运行这个大约需要 17 秒,使用 transformIgnorePatterns 运行大约需要 23 秒。)【参考方案2】:

我必须将此添加到我的.jestconfig

"transformIgnorePatterns": [
  "<rootDir>/node_modules/(?!lodash-es)"
]

【讨论】:

这个可行,但我必须安装babel-jestbabel-preset-envbabel-preset-react,然后是"transform": "^.+\\.(js|jsx|mjs)$": "&lt;rootDir&gt;/node_modules/babel-jest" ,因为ts和js文件需要不同的转换。 如果您有多个,您可能需要包含在同一个正则表达式中,例如(?!lodash-es|my-module)。出于某种原因,如果它们在单独的条目中,它们会相互抵消。 他们必须在同一个条目中,因为 jest 文档中的这个语句。 “如果测试路径匹配任何模式,它将不会被转换。”因此,当 my-module 进行测试时,它会为 ?!lodash-es 正则表达式测试 true,然后将其忽略。 扩展 Jazzy 的评论:如果您已经有一个transformIgnorePatterns: [ 'node_modules/(?!foo|bar)' ] 条目,那么您必须将lodash-es 添加到该列表;您不能在 transformIgnorePatterns 数组中添加单独的条目,因为现有条目已经意味着“忽略 node_modules 下的所有文件夹,除了 foo 和 bar”,因此 node_modules/lodash-es 将被忽略。 // 提示(来自github issue comment):如果使用jest.config.js,你可以先const esModules = ['foo', 'bar', 'lodash-es'] 然后esModules.join('|') 注意:如果你已经运行了jest --watch,你必须退出并重新运行 jest 才能看到transformIgnorePatterns 的更改生效。【参考方案3】:

在这里发布更完整的答案:

默认情况下,Jest 不会转换 node_modules,因为 node_modules 很大。大多数节点模块被打包以暴露 ES5 代码,因为它无需任何进一步的转换即可运行(并且很大程度上向后兼容)。

在您的情况下,lodash-es 专门公开了 ES 模块,这些模块需要由 Jest 通过 babel 构建。

您可以尝试缩小白名单,这样 Jest 就不会尝试通过 babel 传递 node_modules 中的每个 javascript 文件。

我认为您的正确配置是:

"jest": 
  "transformIgnorePatterns": [
    "/!node_modules\\/lodash-es/"
  ]

【讨论】:

【参考方案4】:

对于正在寻找修复程序的create-react-app 用户,这对我有用:

// package.json
...
  "jest": 
    "transformIgnorePatterns": [
      "<rootDir>/node_modules/(?!lodash-es)"
    ]
  ,
...

jest.config.js 文件中的覆盖选项对我不起作用。请记住,并非每个选项都可以被覆盖,以下是支持的选项列表:https://create-react-app.dev/docs/running-tests#configuration

【讨论】:

谢谢伙计。解决了我的问题【参考方案5】:

将 .babelrc 重命名为 babel.config.js 并添加 transformIgnorePatterns 对我有用。

module.exports = 
  "presets": ["@babel/preset-env"]

附:我的笑话版本是: “笑话”:“24.9.0”

https://github.com/facebook/jest/issues/6229#issuecomment-419885857

【讨论】:

【参考方案6】:

可能有人觉得这很有用:

就我而言,我有一个使用 lodash-es 包的 Angular 应用程序。在测试过程中,我遇到了和作者一样的错误。

OPatel 的回答对我来说很好,只需稍加调整(将其添加到您的 jest.config.ts):

"moduleNameMapper": 
    "lodash-es": "lodash"

更改后,我还需要将"esModuleInterop": true 添加到tsconfig.spec.json 中的compilerOptions 属性中,以摆脱TypeError: cloneDeep_1.default is not a function

更新:

在上述所有 lodash 方法的解决方案之后,返回 LodashWrapper 而不是实际值,例如

const clone = cloneDeep(object); // LodashWrapper

为了摆脱这个问题,我使用了这个解决方案: https://github.com/nrwl/nx/issues/812#issuecomment-787141835

moduleNameMapper: 
    "^lodash-es/(.*)$": "<rootDir>/node_modules/lodash/$1",

【讨论】:

以上是关于开玩笑设置“SyntaxError:意外的令牌导出”的主要内容,如果未能解决你的问题,请参考以下文章

打字稿:SyntaxError:意外的令牌“导出”

未捕获的 SyntaxError:意外的令牌导出 (Redux)

我的 nodejs 代码的导出关键字中有语法错误 [重复]

没有覆盖设置的“由于覆盖阈值违规”开玩笑失败

如何在玩笑中将 process.env 设置为未定义

开玩笑找不到模块