0

我有一个使用 Yarn 3 和 TypeScript 4 的 Create-React-App 5 项目。Web 应用程序通过 Yarn 的协议在同一个仓库中使用了一个库(portal:使用Yarn 工作区)。

myRepo
├── myLib
│   ├── package.json
│   ├── yarn.lock
│   └── src
│       ├── index.js
│       └── macro.js
├── myApp
│   ├── package.json
│   ├── yarn.lock
│   └── src
│       ├── App.tsx
│       ├── App.test.tsx
│       └── index.tsx
└── yarnrc.yml

myApp/package.json使用这样的门户:

"dependencies": {
  "myLib": "portal:../myLib",

我的顶级纱线配置:

# yarnrc.yml
nodeLinker: node-modules

如果我替换file:portal:一切正常。即使使用portal:,yarn buildyarn startinsidemyApp仍然可以正常工作,但yarn test成为一个问题:/Users/luke/myRepo/myLib/src/index.js: The macro imported from "./macro" must be wrapped in "createMacro" which you can get from "babel-plugin-macros".

嗯?我当然不会尝试对 Babel 宏做任何事情。此外,这些东西在库中,而不是应用程序本身。

发生了什么事,我该如何解决?

4

1 回答 1

0

好吧,我想我已经想通了!

首先,CRA 包括babel-plugin-macros( source ),它通过查找特定的文件名来操作,例如macro.js并将它们视为 Babel 宏 ( docs )。所以,如果我有一个文件myApp/src/macro.js,它会以类似的方式出错,但对于构​​建/启动也是如此。

、为什么只是Jest下的问题?Jest 实际上是在转换依赖项,而 Webpack 不知何故知道不这样做。通常这是无关紧要的(除了减慢速度),但在这种情况下,Jest 的转译是遇到问题的原因,因为它错误地尝试myLib使用 Babel 宏进行解释(myLib当然作者从未打算这样做)。

第三,为什么 Jest 首先要转换位于外部myApp的另一个库?它当然不应该。实际上,Jest 试图转换明确排除的内容之外的所有内容,并且 CRA 下的排除默认为 ( source ):

transformIgnorePatterns: [
  '[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$',
  '^.+\\.module\\.(css|sass|scss)$',
],

目的是包含应用程序本身并排除其依赖项。这种方法有点假设 的所有依赖关系myApp都在 a 之下,这( PnPnode_modules除外)在 之下是一个特别合理的期望nodeLinker: node-modules。但是对于门户,有一个指向 的符号链接myLib,它(在解析其真实路径后)不在任何之下node_modules,因此与忽略模式不匹配。因此,在此配置下,通过门户访问的依赖项不会从 Jest 转换中排除。

解决方案

为了解决这个问题,将 Jest 配置为也排除项目根目录下的任何内容,即添加:

'^(?!<rootDir>)'

由于我碰巧已经在使用 Craco,所以我可以:

// craco.config.js
module.exports = {
  jest: {
    configure: jestConfig => ({
      ...jestConfig,
      transformIgnorePatterns: [
        ...jestConfig.transformIgnorePatterns,
        '^(?!<rootDir>)',
      ],
    }),
  },
};

确实应该有一种内置的方法来处理这个问题,但是 ‍♂️</p>

于 2021-12-31T08:45:30.730 回答