Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript path-mapping not being translated in node app

Currently using typescript in a node.js application. I've compiled my app, and I'm using typescript's path mapping feature.

'api/*' should instead look in the root folder. Using the following in development works:

nodemon --watch src -e ts,tsx --exec ts-node -r tsconfig-paths/register --disableWarnings ./src/index.ts

tsconfig-paths/register allows the require to be translated correctly and ts-node will execute/run the app properly. Now, the problem comes happens when I move to production. In the past in production, I simply ran tsc on the folder, and moved the contents of the outDir (dist/) to /app in my docker image, and ran node /app/index.js. This has worked until I started using the path mapping feature of typescript. Now I simply get the error:

Error: Cannot find module 'api/module/path/here'

From this github comment the module names are apparently not mapped to the output compiled javascript.

My tsconfig.json file:

{
    "compilerOptions": {
      "target": "es2015",
      "module": "commonjs",
      "moduleResolution": "node",
      "allowSyntheticDefaultImports": true,
      "jsx": "react",
      "allowJs": true,
      "alwaysStrict": true,
      "sourceMap": true,
      "forceConsistentCasingInFileNames": true,
      "noFallthroughCasesInSwitch": true,
      "noImplicitReturns": true,
      "noUnusedLocals": true,
      "noUnusedParameters": true,
      "noImplicitAny": false,
      "noImplicitThis": false,
      "strictNullChecks": false,
      "experimentalDecorators": true,
      "emitDecoratorMetadata": true,
      "lib": ["es2017", "dom"],
      "baseUrl": "src",
      "outDir": "dist",
      "types": [
        "node"
      ],
      "paths": {
        "universal/*": ["../../universal/*"],
        "api/*": ["*"],
        "*": ["node_modules/*"]
      },
      "typeRoots": [
        "./node_modules/@types",
        "./src/types"
      ]
    },
    "include": [
      "src/**/*"
    ]
}

What is the recommended approach to using relative path-mapping in a node.js environment? If typescript is the one doing the resolution, why shouldn't it rewrite the require statements? It feels silly to involve another step like babel or webpack just to add the functionality that typescript is providing with module resolution.

EDIT: After additional digging, I found that I could use -r tsconfig-paths/register in my node environment (I just have to copy in my tsconfig.json file). I can switch my entrypoint in docker to:

ENTRYPOINT [ "node", "-r", "tsconfig-paths/register", "index.js" ]

The problem is, I now need to modify my tsconfig.json baseUrl, as the directory src/ doesn't exist. Also, I noticed that the resolution isn't working for the module 'util' (It's apparently using util in my node_modules folder instead of the node.js util library), which is causing my app to crash.

like image 440
ugh StackExchange Avatar asked Dec 20 '17 20:12

ugh StackExchange


1 Answers

According to the source you supplied, you might be able to use (e.g. resolve the last path AS the first path):

"rootDirs": [
      "src/api/module/path/here",
      "api/module/path/here"
    ]

The problem is, I now need to modify my tsconfig.json baseUrl, as the directory src/ doesn't exist.

typescript's path mapping feature states:

The flexibility of rootDirs is not limited to specifying a list of physical source directories that are logically merged. The supplied array may include any number of ad hoc, arbitrary directory names, regardless of whether they exist or not. This allows the compiler to capture sophisticated bundling and runtime features such as conditional inclusion and project specific loader plugins in a type safe way.

Also, did you try Tracing module resolution: tsc --traceResolution

like image 90
Gillsoft AB Avatar answered Oct 05 '22 14:10

Gillsoft AB