Nextjs和Jest的transform/transformIgnorePatterns不能与esm模块一起使用。

8
我已经对此做了大量研究,并找到了不少解决方案。我找到了一种感觉像是变通方法的东西,想让transformtransformIgnorePatterns工作起来。然而,似乎我唯一能够让其正常工作的事情就是在我的__mocks__文件夹中手动添加一些模拟模块。
不确定这是否是由于使用了NextjsJest造成的?
以下是我的jest.config.js
const nextJest = require("next/jest");

const esModules = ["react-markdown", "rehype-raw", "remark-gfm"].join("|");

const createJestConfig = nextJest({
  // Provide the path to your Next.js app to load next.config.js and .env files in your test environment
  dir: "./",
});

// Add any custom config to be passed to Jest
const customJestConfig = {
  setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
  moduleNameMapper: {
    // Handle module aliases (this will be automatically configured for you soon)
    "^@/components/(.*)$": "<rootDir>/components/$1",

    "^@/pages/(.*)$": "<rootDir>/pages/$1",
  },
  testEnvironment: "jest-environment-jsdom",
  transform: {
    [`(${esModules}).+\\.js$`]: "babel-jest",
  },
  transformIgnorePatterns: [
    `[/\\\\]node_modules[/\\\\](?!${esModules}).+\\.(js|jsx|mjs|cjs|ts|tsx)$`,
  ],
};

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig);

我读到需要一个 babel.config.js 文件。以下是该文件:

module.exports = {
  presets: ["next/babel", "@babel/preset-env"],
};

1
我卡在了同样的地方,你最后解决了这个问题吗? - Romuloux
2个回答

12
以下是一种解决方案,适用于使用 NextJs 12.2、next/jest 和 Jest 28 的用户遇到相同问题的情况。
Jest 提供了一些实验性的 ECMAScript 模块(ESM)支持(链接1),但是"node_modules" 尚未被 next/jest 转译
因此,我们需要使用 transformIgnorePatterns 来防止 ESM 文件被转换。
更改 transformIgnorePatterns 的默认配置被 next/jest 覆盖,请参见下面的解决方案。
// jest.config.js
const nextJest = require('next/jest')

const createJestConfig = nextJest({
  // Path to Next.js app to load next.config.js
  dir: './'
})

/** @type {import('@jest/types').Config.InitialOptions} */
const customJestConfig = {
  /**
   * Custom config goes here, I am not adding it to keep this example simple.
   * See next/jest examples for more information.
   */
 }

module.exports = async () => ({
  ...(await createJestConfig(customJestConfig)()),
  transformIgnorePatterns: [
    // The regex below is just a guess, you might tweak it
    'node_modules/(?!(react-markdown|rehype-raw|remark-gfm)/)',
  ]
})

我创建了一个存储库,用于完整参考一个使用swiper/react的案例所需的设置。 https://github.com/markcnunes/with-jest-and-esm 请注意,这个设置可能需要更改以适应未来的Next.js/next/js版本,但是为了其他使用相同设置的人有用,我分享了这种方法。
我还使用了这个答案另一个问题,如果您正在寻找与swiper/react相关的解决方案。

非常感谢!只要我在执行jest时也没有设置--experimental-vm-modules标志,这对我在Jest v29上运行良好。 - wolfyuk
你会如何为@firebase/auth模块格式化正则表达式? - Luis
很抱歉,Luis,我无法帮助你,因为我不使用@firebase/auth,你可能需要为此创建一个新问题。 - Mark Nunes
太棒了!我花了好几个小时才找到这个!我可以确认这个配置也适用于 Next.js 13,并且对于转译 @aws-sdk 及其内部模块非常有效。 - ccarvalhaes

0

我在使用 jestreact-dnd 时遇到了这个问题,详见 这里

我采用了与 @Mark Nunes 相同的解决方案,但稍作整理:

// jest.config.js
const nextJest = require('next/jest')

const createJestConfig = nextJest({
  // Provide the path to your Next.js app to load next.config.js and .env files in your test environment
  dir: './',
})

const customJestConfig = {
  // You can add other jest config overrides here

  testPathIgnorePatterns: ['/node_modules/'],

  // DON'T SET THIS HERE - it's overridden below
  transformIgnorePatterns: [],
}

module.exports = async function() {
  const makeConfig = await createJestConfig(customJestConfig)
  const finalJestConfig = await makeConfig()

  // This replaces the default of '/node_modules/'
  finalJestConfig.transformIgnorePatterns[0] =
    '/node_modules/(?!@react-dnd|react-dnd|dnd-core|react-dnd-html5-backend/)'

  return finalJestConfig
}


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