使用 Rollup 和 Typescript 配置 Jest

Cri*_*rez 5 javascript reactjs jestjs rollupjs

我使用纱线工作区在 monorepo (Lerna) 中创建了一个应用程序。

\n

该应用程序的架构如下:

\n
my-monorepo\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 node_modules\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 packages\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 package1(shared components)\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 package2(other package consuming the shared components)\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x82     \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 ./jest.config.js\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 package.json\n
Run Code Online (Sandbox Code Playgroud)\n

问题

\n

问题是尝试在package2中使用package1jest时抛出以下错误时抛出以下错误,并且我还没有找到修复它的方法。

\n
\xe2\x97\x8f Test suite failed to run\n\n    Jest encountered an unexpected token\n\n    This usually means that you are trying to import a file which Jest ca\nnnot parse, e.g. it\'s not plain JavaScript.\n\n    By default, if Jest sees a Babel config, it will use that to transfor\nm your files, ignoring "node_modules".\n\n    Here\'s what you can do:\n     \xe2\x80\xa2 If you are trying to use ECMAScript Modules, see https://jestjs.io\n/docs/en/ecmascript-modules for how to enable it.\n     \xe2\x80\xa2 To have some of your "node_modules" files transformed, you can spe\ncify a custom "transformIgnorePatterns" in your config.\n     \xe2\x80\xa2 If you need a custom transformation specify a "transform" option i\nn your config.\n     \xe2\x80\xa2 If you simply want to mock your non-JS modules (e.g. binary assets\n) you can stub them out with the "moduleNameMapper" config option.\n\n    You\'ll find more details and examples of these config options in the\ndocs:\n    https://jestjs.io/docs/en/configuration.html\n\n    Details:\n\n    C:\\Users\\my-user\\Desktop\\my-monorepo\\node_module\ns\\antd\\es\\date-picker\\generatePicker\\index.js:1\n    ({"Object.<anonymous>":function(module,exports,require,__dirname,__fi\nlename,global,jest){import _extends from "@babel/runtime/helpers/esm/exte\nnds";\n\n                    ^^^^^^\n
Run Code Online (Sandbox Code Playgroud)\n

根据错误,我正在尝试导入一个 Jest 无法解析的文件,因此问题来自 package1 所以我首先想到的是:也许我在package1的汇总中做错了什么的汇总中做错了什么,最终的捆绑包采用了某种笑话无法理解的格式......

\n

玩笑配置

\n

Jest 配置位于package2中,我想在其中使用package1

\n
// jest.config.js in package2\n\nconst config = {\n  roots: [\'src\'],\n  setupFilesAfterEnv: [\'./jest.setup.ts\'],\n  moduleFileExtensions: [\'ts\', \'tsx\', \'js\'],\n  testPathIgnorePatterns: [\'node_modules/\'],\n  transform: {\n    \'^.+\\\\.tsx?$\': \'ts-jest\',\n  },\n  testMatch: [\'**/*.test.(ts|tsx)\'],\n  moduleNameMapper: {\n    // Mocks out all these file formats when tests are run.\n    \'\\\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$\':\n      \'identity-obj-proxy\',\n    \'\\\\.(css|less|scss|sass)$\': \'identity-obj-proxy\',\n  },\n};\n\nexport default config;\n
Run Code Online (Sandbox Code Playgroud)\n

汇总配置

\n

这是package1中的汇总配置

\n
// rollup.config.js\n\nimport peerDepsExternal from \'rollup-plugin-peer-deps-external\';\nimport resolve from \'@rollup/plugin-node-resolve\';\nimport commonjs from \'@rollup/plugin-commonjs\';\nimport typescript from \'rollup-plugin-typescript2\';\nimport postcss from \'rollup-plugin-postcss\';\nimport copy from \'rollup-plugin-copy\';\nimport json from \'@rollup/plugin-json\';\nimport svgr from \'@svgr/rollup\';\nimport { babel } from \'@rollup/plugin-babel\';\nimport { visualizer } from \'rollup-plugin-visualizer\';\n\nimport pkg from \'./package.json\';\n\nexport default {\n  input: \'src/index.tsx\',\n  output: [\n    {\n      file: pkg.main,\n      format: \'cjs\',\n      exports: \'named\',\n      sourcemap: true,\n    },\n    {\n      file: pkg.module,\n      format: \'esm\',\n      exports: \'named\',\n      sourcemap: true,\n    },\n  ],\n  plugins: [\n    peerDepsExternal({\n      includeDependencies: true,\n    }),\n    json(),\n    svgr(),\n    resolve({ extensions: [\'.js\', \'.jsx\', \'.ts\', \'.tsx\', \'.json\'] }),\n    commonjs({\n      include: /\\**node_modules\\**/,\n    }),\n    // UPDATE 3: Add babel\n    babel({\n      babelHelpers: \'bundled\',\n    }),\n    typescript({\n      useTsconfigDeclarationDir: true,\n      exclude: [\'*.d.ts\', \'**/*.d.ts\', \'**/*.test.tsx\'],\n      rollupCommonJSResolveHack: true,\n      clean: true,\n    }),\n    postcss({\n      extensions: [\'.css\', \'.less\'],\n      use: {\n        less: { javascriptEnabled: true, modifyVars: {} },\n      },\n    }),\n    visualizer({ filename: \'stats-visualizer.html\', gzipSize: true }),\n    copy({\n      targets: [\n        {\n          src: \'src/styles/themes/dark-variables.less\',\n          dest: \'dist\',\n          rename: \'theme/dark.less\',\n        },\n        {\n          src: \'src/styles/themes/light-variables.less\',\n          dest: \'dist\',\n          rename: \'theme/light.less\',\n        },\n        {\n          src: \'src/assets/icons\',\n          dest: \'dist\',\n          rename: \'assets/icons\',\n        },\n      ],\n    }),\n  ],\n};\n
Run Code Online (Sandbox Code Playgroud)\n

更新1:

\n

我尝试使用Matt Carlota 提到的transform规则进行转译jest.config.jsantd进行转译,但这不起作用:

\n
// jest.config.js\nconst config = {\n  // ... other jest settings\n  transform: {\n    \'^.+\\\\.tsx?$\': \'ts-jest\',\n    \'node_modules/antd/.+\\\\.(j|t)sx?$\': \'ts-jest\',\n  },\n  // I\'ve tried with `antd/es` pattern too and doesn\'t work\n  transformIgnorePatterns: [\'node_modules/(?!antd)\'],\n};\n
Run Code Online (Sandbox Code Playgroud)\n

更新2:

\n

手动更改antd/es可以暂时antd/lib解决package1问题,但是有一个问题,那就是我们是一大群人在工作,可以作为约定只使用antd/lib,但我觉得这很容易出错。

\n

每当有人忘记使用antd/lib并使用时antd/en所有测试都会中断原始错误。

\n

更新3:

\n

在 rollup 配置中添加 babel 配置文件和插件...

\n
// babel.config.js\n\nmodule.exports = {\n  plugins: [[\'import\', { libraryName: \'antd\', libraryDirectory: \'lib\' }, \'antd\']],\n};\n\n
Run Code Online (Sandbox Code Playgroud)\n

tub*_*tub 0

我已经被同样的问题困扰了很长时间,终于找到了方法。

我的案例中缺少的部分是添加moduleNameMapper. 这里有一个导游提到过。

该解决方案不需要 babel-jest。

笑话配置.js

const path = require('path');
const { lstatSync, readdirSync } = require('fs');
// get listing of packages in the mono repo
const basePath = path.resolve(__dirname, '..', '..', 'packages');
const packages = readdirSync(basePath).filter((name) => {
  return lstatSync(path.join(basePath, name)).isDirectory();
});

module.exports = {
  preset: 'ts-jest',
  verbose: true,
  moduleFileExtensions: ['js', 'json', 'jsx', 'node', 'ts', 'tsx'],
  moduleDirectories: ['node_modules', 'src'],
  moduleNameMapper: {
    ...packages.reduce(
      (acc, name) => ({
        ...acc,
        [`@xyz/${name}(.*)$`]: `<rootDir>/../../packages/./${name}/src/$1`,
      }),
      {}
    ),
  },
  rootDir: './',
  testRegex: '.spec.ts$',
  transform: {
    '^.+\\.(t)s$': 'ts-jest',
  },
  testEnvironment: 'node',
  setupFilesAfterEnv: ['./jest.setup.ts'],
  testMatch: null,
  globals: {
    'ts-jest': {
      tsconfig: 'tsconfig.jest.json',
    },
  },
  roots: ['<rootDir>'],
  transformIgnorePatterns: [],
  collectCoverage: false,
  collectCoverageFrom: ['src/**/*.{js{,x},ts{,x}}', '!src/server/index.ts'],
};

Run Code Online (Sandbox Code Playgroud)

tsconfig.json

{
  "compilerOptions": {
    "module": "esnext",
    "target": "ES2019",
    "lib": ["ES2019", "DOM"],
    "noEmit": true,
    "types": ["node", "jest"],
    "rootDir": "./"
    "paths": {
      "@xyz/*": ["packages/*/src"]
    },
    
  },
  "include": ["test/**/*.ts", "src/**/*.ts", "**/*.spec.ts"],
  "references": [
    { "path": "../../packages/package1" },
  ]
}
Run Code Online (Sandbox Code Playgroud)

包.json

...
scripts: {
  "test": "NODE_ENV=production tsc --build ./tsconfig.jest.json && jest --env=node test --watch",
}
Run Code Online (Sandbox Code Playgroud)