英文:
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
有关问题的建议:
请检查以下几个可能导致这个错误的因素:
-
检查文件路径是否正确:确保
utils/machineInfo.ts
文件位于与tsconfig.json
中的baseUrl
和paths
设置相匹配的位置。可能需要调整这些设置来匹配文件的实际位置。 -
确保文件名的大小写正确:文件系统通常区分大小写,确保文件名的大小写与导入语句中的大小写一致。
-
检查
utils/machineInfo.ts
文件是否存在:确保文件确实存在于指定的路径中,并且没有拼写错误。 -
运行构建命令:运行
npm run build
以确保TypeScript成功编译并生成dist
目录中的JavaScript文件。
如果问题仍然存在,请提供更多信息,以便进行更详细的诊断。 英文:
I have this Nodejs Typescript Azure function in local:
<root-directory>
├── 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
:
{
"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...\""
},
...
This is the index.ts
, which imports a function from ./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\> {
...
and this is the ./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....\");
And this is utils/machineInfo.ts
:
import os from "os";
`// Get the machine info that identifies the current host running this code;
export const getMachineInfo = () => {
const machineInfo = {
// The machine's hostname;
hostname: os.hostname(),
// the machine's number of CPUs;
numCPUs: os.cpus().length,
};
return machineInfo;
};
`
Now it is complaining that the in line:
import { getMachineInfo } from "utils/machineInfo";
it cannot find module 'utils/machineInfo':
Error message:
[2023-08-10T03:59:00.616Z] Worker was unable to load entry point "dist/sealworker/index.js": Cannot find module 'utils/machineInfo'
[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 "baseUrl"
and "paths"
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:
-
You need to have Azure tools plugin installed in VS Code;
-
In local WORKSPACE, click the azure functions icon and choose:
-
Go through the creation process; select Programming Model V3;
-
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
> minimal_reproducible_example@1.0.0 build /Users/john/myapp/code/minimal_reproducible_example > 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: \'Cannot find module \'services/JobProcessor\'
\[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\'
...
答案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
{
"build": "tsc && tsc-alias",
}
Update after looking at the example repo:
I noted that you set rootDir: "."
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.