【问题标题】:Node cannot find required modules with non-relative path after transpiling them with tsc使用 tsc 编译后,节点找不到具有非相对路径的所需模块
【发布时间】:2019-12-22 14:46:31
【问题描述】:

我们正在使用普通打字稿构建应用程序。为了使导入更易于阅读,我们将 typescript 配置为能够通过 tsconfig 解析非相对路径。

使用 tsc 将代码转换为 JS 代码可以正常工作。但是每当我们想用node dist/demo/demonstration.js 启动应用程序时,我们都会收到cannot find lib/input/parser module 错误。这是生成的 .js 文件的第一次导入。这是所有导入的普遍问题。

起初我们认为这可能是我们的tsconfig.json 的问题。但是在运行 js 文件时,任何修改 pathsbaseurl 键的尝试都会遇到相同或不同的错误。 tsc 本身在没有错误的情况下完成的情况也使这一点无效。

在 Webstorm 中通过 jest.config.js 运行 jest 也可以。

我们找到了两种可能的解决方法。一种是将dist 中的文件夹复制到nodes_modules 中。通过符号链接执行此操作可以省去一些手动工作。

另一个是像NODE_PATH=dist dist/demo/demonstration.js这样通过终端运行应用程序。

这两个都感觉很hacky。我是否在这里遗漏了一个概念,或者这就是您在打字稿中进行非相对导入的方式?如何配置 Webstorm 运行配置以运行我们的应用程序?

打字稿中的导入示例:

import {Parser} from "lib/input/parser";

tsc 能够解决这些问题。

tsconfig.json,清除未使用的选项。留下我们一起玩的那些:

{
    "compilerOptions": {
        /* Basic Options */
        "target": "es2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
        "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */

        "outDir": "dist", /* Redirect output structure to the directory. */
        //     "rootDir": ".",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */


        /* Strict Type-Checking Options */
        "strict": true, /* Enable all strict type-checking options. */

        /* Module Resolution Options */
        "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
        "baseUrl": "src", /* Base directory to resolve non-absolute module names. */
        //     "paths": {
        //       "lib/*": ["lib/*"],
        //       "demo/*": ["demo/*"],
        //       "test/*": ["test/*"]
        //     },                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */

        "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */

        /* Source Map Options */

        "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
        "inlineSources": true /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    }
}

jest.config.js:

module.exports = {
  "roots": [
    "<rootDir>/src/lib", //src is our folder where sources reside
    "<rootDir>/src/test",
    "<rootDir>/src/demo"
  ],
  "transform": {
    "^.+\\.tsx?$": "ts-jest" //tells jest to use ts-jest for ts / tsx files
  },
  //"testRegex": "(/test/.*|(\\.|/)(test|spec))\\.tsx?$", //tells Jest to look for test in any __tests__ folder
  // AND also any files anywhere that use the (.test|.spec).(ts|tsx) extension e.g. asdf.test.tsx etc.
  "testRegex": "/test/.*",
  "moduleFileExtensions": [
    "ts",
    "tsx",
    "js",
    "jsx",
    "json",
    "node"
  ],
  moduleDirectories: ['node_modules', 'src']
};

package.json

{
  "name": "questionsys",
  "version": "0.1.0",
  "description": "Context-based questionnaire engine",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Tagman",
  "license": "ISC",
  "devDependencies": {
    "@types/axios": "^0.14.0",
    "@types/jest": "^24.0.17",
    "@types/node": "^12.7.2",
    "@types/uuid": "^3.4.5",
    "jest": "^24.8.0",
    "ts-jest": "^24.0.2",
    "typedoc": "^0.15.0",
    "typescript": "^3.5.3"
  },
  "dependencies": {
    "axios": "^0.19.0",
    "uuid": "^3.3.2"
  }
}

【问题讨论】:

  • 要构建项目,我在项目根目录中输入tsc。然后用 node dist/demo/demonstration.js 运行 JS 有没有别的办法?这是我的第一个 Typescript 项目。所以我缺乏很多内部知识。
  • 在您发表第一条评论后,我阅读了 babel。听起来是个很棒的工具。我只是不太明白 babel 和 typescript 是如何联系在一起的。 Babel 和 TS 都可以将我的代码转换为 Javascript。我现在明白需要将路径转换回相对路径。这就是我需要 Babel(或类似的东西)的全部吗?我们的目标是首先为控制台应用程序编写一个库,然后再支持移动设备和浏览器。
  • 我要试试 babel。感谢你的信息。如果您发表评论作为答案,我会接受。

标签: javascript node.js typescript jestjs


【解决方案1】:

TypeScript 仅在单独的构建步骤中对 compile checksexpects you to convert path aliases 使用 pathsbaseUrl

我们对此的一般看法是,您应该编写在运行时有效的导入路径,并设置您的 TS 标志以满足编译器的模块解析步骤,而不是为 TS 编写开箱即用的导入然后尝试其他一些步骤“修复”运行时有效的路径。 (core developers' standpoint)

  1. 保留所有 JavaScript 代码的运行时行为。 (TypeScript design goals)

Node.js 这样的下游运行时环境不会知道映射的绝对路径,如果路径尚未转换,则会发出错误。有一个名为Import Maps 的提案(请参阅相应的Node.js issue),它可能会在将来简化映射路径解析。在此之前,以下是一些常用构建工具的示例:

babel-plugin-module-resolver

示例:转换@/foo/bar/index./src/foo/bar/index

.babelrc:
{
  // ...  
  "plugins": [
    [ "module-resolver", { "alias": { "^@/(.+)": "./src/\\1" }} ]
  ]
}

tsc 编译后的单独构建步骤中:

babel src --out-dir dist # or similar

tsconfig-paths / tsconfig-paths-webpack-plugin

webpack.config.js:
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
module.exports = {
  // ...
  resolve: {
    plugins: [new TsconfigPathsPlugin({/* options */})]
  }
}

更多信息

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-28
    • 2012-09-27
    • 1970-01-01
    • 2022-11-07
    • 2020-05-21
    • 2020-03-29
    • 1970-01-01
    • 2016-05-24
    相关资源
    最近更新 更多