开玩笑设置“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-jest
、babel-preset-env
、babel-preset-react
,然后是"transform": "^.+\\.(js|jsx|mjs)$": "<rootDir>/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:意外的令牌导出”的主要内容,如果未能解决你的问题,请参考以下文章