51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Node.js TypeScript Azure Function: 无法使用绝对路径导入(附有最小可复现示例)

英文:

Node.js Typescript Azure Function: Cannot import with absolute path ( minimal reproducible example attached)

问题 {#heading}

以下是代码部分的翻译:

我有一个本地的Nodejs TypeScript Azure函数:

这是`tsconfig.json`:
{
  "compilerOptions": {
    "module": "commonjs",
    "moduleResolution": "node",
    "target": "es6",
    "outDir": "dist",
    "rootDir": ".",
    "sourceMap": true,
    "strict": false,
    "esModuleInterop": true,
    "preserveConstEnums": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "baseUrl": "./sealworker",
    "paths": {
      "*": [
        "*",
        "sealworker/*",
        "node_modules/*"
      ]
    }
  },
  "exclude": [
    "node_modules",
    "**/*.test.ts"
  ],
  "include": [
    "**/*"
  ]
}

`package.json`:
{
  "name": "azure_function",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "build": "tsc",
    "watch": "tsc -w",
    "clean": "rimraf dist",
    "prestart": "npm run clean && npm run build",
    "start": "func start",
    "test": "echo \"No tests yet...\""
  },
   ...
}

这是`index.ts`,它从`./services/worker.ts`导入一个函数:
import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { workerExec } from "./services/worker";

const sealWorkerFunction: AzureFunction = async function (
  context: Context,
  req: HttpRequest
): Promise<void> {
...

这是`./services/worker.ts`:
import "dotenv/config";
import "reflect-metadata";
import { HttpRequest, Context } from "@azure/functions";
import { getMachineInfo } from "utils/machineInfo";

export const workerExec = async (req: HttpRequest, context: Context) => {
  context.log("start....");
...

这是`utils/machineInfo.ts`:
import os from "os";

// 获取标识当前运行此代码的主机的机器信息;
export const getMachineInfo = () => {
  const machineInfo = {
    // 主机名;
    hostname: os.hostname(),
    // CPU数量;
    numCPUs: os.cpus().length,
  };
  return machineInfo;
};

现在,关于导入模块"utils/machineInfo"无法找到的错误信息:

错误消息:
[2023-08-10T03:59:00.616Z] Worker无法加载入口点"dist/sealworker/index.js":找不到模块'utils/machineInfo'
[2023-08-10T03:59:00.616Z] 需要堆栈:
[2023-08-10T03:59:00.616Z] - /Users/code/seal/azure_function/dist/sealworker/services/worker.js
[2023-08-10T03:59:00.616Z] - /Users/code/seal/azure_function/dist/sealworker/index.js
[2023-08-10T03:59:00.616Z] - /usr/local/Cellar/azure-functions-core-tools@4/4.0.5198/workers/node/dist/src/worker-bundle.js
[2023-08-10T03:59:00.616Z] - /usr/local/Cellar/azure-functions-core-tools@4/4.0.5198/workers/node/dist/src/nodejsWorker.js

有关问题的建议:

请检查以下几个可能导致这个错误的因素:

  1. 检查文件路径是否正确:确保utils/machineInfo.ts文件位于与tsconfig.json中的baseUrlpaths设置相匹配的位置。可能需要调整这些设置来匹配文件的实际位置。

  2. 确保文件名的大小写正确:文件系统通常区分大小写,确保文件名的大小写与导入语句中的大小写一致。

  3. 检查utils/machineInfo.ts文件是否存在:确保文件确实存在于指定的路径中,并且没有拼写错误。

  4. 运行构建命令:运行npm run build以确保TypeScript成功编译并生成dist目录中的JavaScript文件。

如果问题仍然存在,请提供更多信息,以便进行更详细的诊断。 英文:

I have this Nodejs Typescript Azure function in local:

&lt;root-directory&gt;
├── README.md
├── dist
├── host.json
├── local.settings.json
├── node_modules
├── package-lock.json
├── package.json
├── sealworker
│   ├── constants
│   ├── errors
│   ├── function.json
│   ├── index.ts
│   ├── interfaces
│   ├── sample.dat
│   ├── services
│   │     ├── worker.ts
│   │     └── ...
│   └── utils
│         ├── machineInfo.ts
│         └── ...
└── tsconfig.json

This is the tsconfig.json:

{
  &quot;compilerOptions&quot;: {
    &quot;module&quot;: &quot;commonjs&quot;,
    &quot;moduleResolution&quot;: &quot;node&quot;,
    &quot;target&quot;: &quot;es6&quot;,
    &quot;outDir&quot;: &quot;dist&quot;,
    &quot;rootDir&quot;: &quot;.&quot;,
    &quot;sourceMap&quot;: true,
    &quot;strict&quot;: false,
    &quot;esModuleInterop&quot;: true,
    &quot;preserveConstEnums&quot;: true,
    &quot;skipLibCheck&quot;: true,
    &quot;forceConsistentCasingInFileNames&quot;: true,
    &quot;baseUrl&quot;: &quot;./sealworker&quot;,
    &quot;paths&quot;: {
      &quot;*&quot;: [
        &quot;*&quot;,
        &quot;sealworker/*&quot;,
        &quot;node_modules/*&quot;
      ]
    }
  },
  &quot;exclude&quot;: [
    &quot;node_modules&quot;,
    &quot;**/*.test.ts&quot;
  ],
  &quot;include&quot;: [
    &quot;**/*&quot;
  ]
}

package.json:

{
  &quot;name&quot;: &quot;azure_function&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;scripts&quot;: {
    &quot;build&quot;: &quot;tsc&quot;,
    &quot;watch&quot;: &quot;tsc -w&quot;,
    &quot;clean&quot;: &quot;rimraf dist&quot;,
    &quot;prestart&quot;: &quot;npm run clean &amp;&amp; npm run build&quot;,
    &quot;start&quot;: &quot;func start&quot;,
    &quot;test&quot;: &quot;echo \&quot;No tests yet...\&quot;&quot;
  },

...

This is the index.ts, which imports a function from ./services/worker.ts:

import { AzureFunction, Context, HttpRequest } from &quot;@azure/functions&quot;;
import { workerExec } from &quot;./services/worker&quot;;

const sealWorkerFunction: AzureFunction = async function (
context: Context,
req: HttpRequest
): Promise\&lt;void\&gt; {


...

and this is the ./services/worker.ts:

import &quot;dotenv/config&quot;;
import &quot;reflect-metadata&quot;;
import { HttpRequest, Context } from &quot;@azure/functions&quot;;
import { getMachineInfo } from &quot;utils/machineInfo&quot;;

export const workerExec = async (req: HttpRequest, context: Context) =\&gt; {
context.log(\&quot;start....\&quot;);

And this is utils/machineInfo.ts:

import os from &quot;os&quot;;
`// Get the machine info that identifies the current host running this code;
export const getMachineInfo = () =&gt; {
const machineInfo = {
// The machine&#39;s hostname;
hostname: os.hostname(),
// the machine&#39;s number of CPUs;
numCPUs: os.cpus().length,
};
return machineInfo;
};
`

Now it is complaining that the in line:

import { getMachineInfo } from &quot;utils/machineInfo&quot;;

it cannot find module 'utils/machineInfo':

Error message:

[2023-08-10T03:59:00.616Z] Worker was unable to load entry point &quot;dist/sealworker/index.js&quot;: Cannot find module &#39;utils/machineInfo&#39;
[2023-08-10T03:59:00.616Z] Require stack:
[2023-08-10T03:59:00.616Z] - /Users/code/seal/azure_function/dist/sealworker/services/worker.js
[2023-08-10T03:59:00.616Z] - /Users/code/seal/azure_function/dist/sealworker/index.js
[2023-08-10T03:59:00.616Z] - /usr/local/Cellar/azure-functions-core-tools@4/4.0.5198/workers/node/dist/src/worker-bundle.js
[2023-08-10T03:59:00.616Z] - /usr/local/Cellar/azure-functions-core-tools@4/4.0.5198/workers/node/dist/src/nodejsWorker.js

I have tried different things with &quot;baseUrl&quot; and &quot;paths&quot; in tsconfig.json, and the values should be straight-forward and self explanatory now. But apparently I have made a mistake somewhere....

Any suggestions?

--------- UPDATE ---------

I have made a public minimal reproducible repo at: https://github.com/DaCao/minimal_reproducible_example

To reproduce, git clone this repo and open VS Code:

  1. You need to have Azure tools plugin installed in VS Code;

  2. In local WORKSPACE, click the azure functions icon and choose:

Node.js TypeScript Azure Function: 无法使用绝对路径导入(附有最小可复现示例)

  1. Go through the creation process; select Programming Model V3;

  2. After setting up the local project, build the nodejs:

    john@MacBook-Pro:~/myapp/code/minimal_reproducible_example$ ls host.json local.settings.json node_modules/ package-lock.json package.json sealworker/ tsconfig.json john@MacBook-Pro:~/myapp/code/minimal_reproducible_example$ npm run-script build

    &gt; minimal_reproducible_example@1.0.0 build /Users/john/myapp/code/minimal_reproducible_example &gt; tsc

    john@MacBook-Pro:~/myapp/code/minimal_reproducible_example$


you also need to have Azure Function Core Tools installed:

john@MacBook-Pro:~/myapp/code/minimal_reproducible_example$ func -v 
4.0.5198

and then just run:

john@MacBook-Pro:~/myapp/code/minimal_reproducible_example$ func start

you should see the error:

...

For detailed output, run func with --verbose flag.
\[2023-08-11T05:38:06.464Z\] Worker process started and initialized.
\[2023-08-11T05:38:06.474Z\] Worker was unable to load function sealworker: \&#39;Cannot find module \&#39;services/JobProcessor\&#39;
\[2023-08-11T05:38:06.474Z\] Require stack:
\[2023-08-11T05:38:06.474Z\] - /Users/john/myapp/code/minimal_reproducible_example/dist/sealworker/services/worker.js
\[2023-08-11T05:38:06.474Z\] - /Users/john/myapp/code/minimal_reproducible_example/dist/sealworker/index.js
\[2023-08-11T05:38:06.474Z\] - /usr/local/Cellar/azure-functions-core-tools@4/4.0.5198/workers/node/dist/src/worker-bundle.js
\[2023-08-11T05:38:06.474Z\] - /usr/local/Cellar/azure-functions-core-tools@4/4.0.5198/workers/node/dist/src/nodejsWorker.js\&#39;


...

答案1 {#1}

得分: 2

根据您的堆栈跟踪,我猜您使用tsc编译您的代码,然后使用node执行它。请记住,如果使用tsc构建,绝对路径最终不会转换为相对路径。

因此,我建议通过使用tsc-alias 进行额外的步骤来转换这些路径。

// package.json
{
  "build": "tsc && tsc-alias",
}

在查看示例存储库后更新:

我注意到您设置了 rootDir: ".",这是为了将您构建的代码包含在同一个目录sealworker下,但不幸的是,这个设置出于某种我也不清楚的原因阻止了tsc-alias正常工作(这可能是需要向他们报告的错误)。

无论如何,我建议设置另一个命令将构建的代码移动到该目录中,或者甚至删除此设置并将构建的代码放在dist目录下就足够了。 英文:

Based on your stack trace, I guess you compile your code with tsc and then gets executed with node. Keep in mind that if you build with tsc, the absolute paths will end up not converting to relative path at all.

As result of that, I would recommend to have an extra step to convert those paths by using tsc-alias

// package.json
{
  &quot;build&quot;: &quot;tsc &amp;&amp; tsc-alias&quot;,
}

Update after looking at the example repo:

I noted that you set rootDir: &quot;.&quot; which is to include your built code under the same dir sealworker but unfortunately this setup prevents tsc-alias from working properly for some reason that I have no idea too (it could be a bug to report to them).

Anyway I would suggest either set up another command to move the built code into the dir or even remove this setup and place built code under dist is enough.


赞(1)
未经允许不得转载:工具盒子 » Node.js TypeScript Azure Function: 无法使用绝对路径导入(附有最小可复现示例)