开玩笑无法解析模块别名

Posted

技术标签:

【中文标题】开玩笑无法解析模块别名【英文标题】:jest cannot resolve module aliases 【发布时间】:2020-02-13 00:56:07 【问题描述】:

我正在使用一个名为 module-alias 的 npm 模块。我在 tsconfig.json 和 package.json 中映射了一些模块

tsconfig.json

"compilerOptions": 
   "baseUrl": "./src",
   "paths": 
   "@config/*": ["config/*"],
   "@interfaces/*": ["interfaces/*"],
   "@services/*": ["services/*"]
  ,
  "module": "commonjs",
  "target": "es2015",                   /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
  "sourceMap": true,
  "outDir": "./dist",                        /* Redirect output structure to the directory. */
  "rootDir": "./src",    
  "allowSyntheticDefaultImports": true          /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */

package.json

  ...
 "_moduleAliases": 
    "@config": "src/config",
    "@interface": "src/interface",
    "@services": "src/services"
  ,
  "jest": 
    "moduleNameMapper": 
      "@config/(.*)": "src/config/$1",
      "@interface/(.*)": "src/interface/$1",
      "@services/(.*)": "src/services/$1"
    ,

     "moduleFileExtensions": ['js', 'json', 'jsx', 'ts', 'tsx', 'node']
  ,
...

server.ts

import  logger  from '@config/logger';

当我运行npm start 时一切正常,但是当我运行 jest 时它给了我一个错误

FAIL  src/test/article.spec.ts
  ● Test suite failed to run

    Cannot find module '@config/logger' from 'server.ts'

    However, Jest was able to find:
        'rest/server.ts'

    You might want to include a file extension in your import, or update your 'moduleFileExtensions', which is currently ['js', 'json', 'jsx', 'ts', 'tsx', 'node'].

有人知道问题出在哪里吗?谢谢

解决方案对我有用(2019 年 18 月 10 日更新):

使用以下代码创建一个 jest.config.js:

module.exports = 
  "roots": [
    "<rootDir>/src/"
],
  "transform": 
    "^.+\\.tsx?$": "ts-jest"
  


并更新 package.json 中的 moduleNameMapper:

...
  "_moduleAliases": 
    "@config": "./src/config",
    "@interfaces": "./src/interfaces",
    "@services": "./src/services"
  ,
  "jest": 

    "moduleNameMapper": 
      "@config/(.*)": "<rootDir>/src/config/$1",
      "@interfaces/(.*)": "<rootDir>/src/interfaces/$1",
      "@services/(.*)": "<rootDir>/src/services/$1"
    
  
...

【问题讨论】:

您应该从问题中删除您的解决方案并添加您自己的答案。 【参考方案1】:

几个小时后,我设法完成了这项工作。我会尽力简化它以节省其他人的时间并使其顺利进行。

我的应用属于以下堆栈:

用于 API 构建 (.ts) 的 Typescript(tscts-node/register,没有 Babel) 反应(.tsx 使用 Webpack) jest 用于 API 测试(无 Babel) testcafe 用于 UI/E2E VSCode 作为 IDE

重点说明:

    对我有用的解决方案是别名前必须有“@”字符。 module-alias 理论上不需要它,但是当我们应用模块名称映射器时,Jest 会迷路。 “webpack”别名和“tsconfig”之间的命名需要保持一致。 VSCode 有必要不要在 TSX 文件中用红色下划线模块名称。 无论您的文档结构如何,这都应该有效,但如果遇到问题,请记住调整 baseUrl 和开玩笑配置。 在 VSCode 中为 .tsx 文件应用更改时,不要担心某些路径带有下划线。这是暂时的,因为 VSCode 似乎只有在所有文件正确连接时才能掌握它。一开始它让我失去了动力。

首先,从https://www.npmjs.com/package/module-alias 安装module-alias

npm i --save module-alias

然后添加到您的初始启动文件(仅适用于 .ts 文件,即您的应用程序服务器):

require('module-alias/register')

正如module-alias 文档所示。然后设置tsconfig.ts。请记住,baseUrl 在这里也很重要:


 "compilerOptions": 
    "baseUrl": ".",
    ...
    "paths": 
      "@helpers/*": ["src/helpers/*"],
      "@root/*": ["src/*"]
      ...
    
 

然后设置你的webpack.js:

const path = require('path')
...

  resolve: 
    ...
    alias: 
      '@helpers': path.resolve(__dirname, 'src', 'helpers'),
      '@root': path.resolve(__dirname, 'src')
    
  

然后设置你的package.json:


   ...
   "_moduleAliases": 
     "@helpers": "src/helpers",
     "@root": "src"
   

然后设置您的 jest 配置(我仅附上应用更改时相关的内容):


   rootDir: ".",
   roots: ["./src"],
   transform: 
     "^.+\\.ts?$": "ts-jest"
   ,
   moduleNameMapper: 
     "@helpers/(.*)": "<rootDir>/src/helpers/$1",
     "@root/(.*)": "<rootDir>/src/$1"
   ,
   ...
 

现在,我们需要处理构建过程,因为tsc 无法将别名转换为它们的相关兄弟。

为此,我们将使用 tscpaths 包:https://github.com/joonhocho/tscpaths。这个很简单。

所以考虑到您的构建命令只是:

tsc

现在变成了

tsc && tscpaths -p tsconfig.json -s ./src -o ./dist/server

您需要调整 -s-o 以适应您的结构,但是当您在构建后检查 .js 文件时,您应该查看相对路径是否正确链接(并相应地进行调试)。

就是这样。它应该像王牌一样工作。这很多,但值得。

控制器 (.ts) 和 React 组件 (.tsx) 文件中的调用示例:

import  IApiResponse  from '@intf/IApi'

【讨论】:

"moduleNameMapper" 是为我做的,谢谢你的回复!【参考方案2】:

我认为您没有在 tsconfig 中正确配置路由,因为路径缺少 src 文件夹(虽然它们出现在您的 package.json 模块别名配置中):

您的tsconfig 代码:

"@config/*": ["config/*"],
"@interfaces/*": ["interfaces/*"],
"@services/*": ["services/*"]

我认为应该是这样的:

"@config/*": ["src/config/*"],
"@interfaces/*": ["src/interfaces/*"],
"@services/*": ["src/services/*"]

【讨论】:

似乎 compilerOptions 中的 baseUrl 可以通知编译器在哪里找到模块,因为在我将 'src' 添加到路径后它给了我打字错误 我什至无法启动我的应用程序,它也让我找不到模块'@config/...' 哇,这真的让我很困惑。我有一个带有 ts 和 jest 的工作配置,我正在指定指向我的路径的完整路径,指示 src 段。我在你的 package.json 中看到你指的是 'interface' ,但是在你的 tsconfig 中有一个对 'interfaces' 的引用(带有额外的s)。也许是相关的,我不确定。 我创建了一个 jest.config.js 并添加了两个选项,包括“roots”和“transform”,然后一切正常。

以上是关于开玩笑无法解析模块别名的主要内容,如果未能解决你的问题,请参考以下文章

React Webpack 错误“找不到模块:错误:无法解析 'public/bundle.js' in..”/“字段 'browser' 不包含有效的别名配置”

Webpack 无法正确解析我的别名

运行玩笑时打字稿路径无法解析?

Gatsby - webpack 无法使用 `gatsby-plugin-alias-imports` 解析别名导入

PLSQL ORA-12154: TNS: 无法解析指定的连接标识符

ESLint 无法识别根别名 (@)