typescript NestJS和无服务器-处理程序“handler”不是函数

5ssjco0h  于 2023-06-07  发布在  TypeScript
关注(0)|答案(3)|浏览(168)

我正在尝试使用无服务器框架将NestJS实现为AWS无服务器函数。
我遵循了这个官方文档,我的代码和文档中的完全一样。但是当我启动它时,我得到错误Failure: offline: handler 'handler' in [..] is not a function

如果我进入我编译的main.js源代码,并将exports.handler = handler;行更改为module.exports.handler = handler;,它就开始工作了。

我也试过修改main.ts的代码来适应这个问题,但是没有用,因为webpack编译的方式不一样。

// main.ts
const handler ...;
module.exports.handler = handler;

这是我的main.ts

import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { Callback, Context, Handler } from 'aws-lambda';
import serverlessExpress from '@vendia/serverless-express';
import { AppModule } from './app.module';

let server: Handler;

async function bootstrap(): Promise<Handler> {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true,
    }),
  );
  await app.init();

  const expressApp = app.getHttpAdapter().getInstance();
  return serverlessExpress({ app: expressApp });
}

export const handler: Handler = async (event: any, context: Context, callback: Callback) => {
  server = server ?? (await bootstrap());
  return server(event, context, callback);
};

这是我的serverless.yml

service:
  name: serverless-example

plugins:
  - serverless-offline

provider:
  name: aws
  runtime: nodejs12.x

functions:
  main:
    handler: dist/main.handler
    events:
      - http:
          method: ANY
          path: /
      - http:
          method: ANY
          path: '{proxy+}'

这里是我的webpack.config.js

return {
  ...options,
  externals: [],
  output: {
    ...options.output,
    libraryTarget: 'commonjs2',
  },
  // ... the rest of the configuration
};

最后是tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "es2017",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true,
    "skipLibCheck": true,
    "strictNullChecks": false,
    "noImplicitAny": false,
    "strictBindCallApply": false,
    "forceConsistentCasingInFileNames": false,
    "noFallthroughCasesInSwitch": false,
    "esModuleInterop": true
  }
}

我在webpack上缺少一些配置吗?或者修改typescript配置文件?我不知道,文件说,它应该只是工作,但它没有。
从理论上讲,我所需要的是在我的编译文件中将它改为module.exports.handler = handler而不是exports.handler = handler,因为正如我所说,我确实改变了它,它开始正常工作。
这是我使用的临时修复程序,但显然这是错误的方法。

"build": "nest build --webpack && sed -i 's/exports.handler = handler;/module.exports.handler = handler;/g' dist/main.js",
kpbwa7wx

kpbwa7wx1#

我通过创建确保webpack输出具有commonjs2libraryTarget来解决这个问题。在项目的根目录下创建(或编辑)一个webpack.config.js文件,包含以下内容,确保我们将libraryTarget设置为commonjs2

module.exports = (options) => {
  return {
    ...options,
    output: {
      ...options.output,
      libraryTarget: 'commonjs2',
    },
  };
};

在我的serverless.yml中,我为我的lambda函数定义了以下内容:

...

functions:
  example:
    handler: "./dist/apps/example/main.js.handler"
...

请注意,如果您的入口点/函数不同,则应更改main.js.handler。例如,如果它是entrypoint,则该字符串将是dist/apps/example/main.js.entrypoint

w8rqjzmb

w8rqjzmb2#

我找到了解决方案:)对于同样的问题,但与serverless-plugin-typescript与nx工作区
关于tsconfig with module:commonjs

"compilerOptions": {  
  "module": "commonjs",
},

然后我在./build文件夹中看到

...
exports.main = main;
tuwxkamq

tuwxkamq3#

由于很多人都有同样的问题,我找不到一个“好”的解决方案,这里是一个有效的解决方案:只需在已编译的main.js文件中将exports.handler替换为module.exports.handler即可。
这就是您在package.json内部的构建过程中使用sed简单地完成它的方法

"build": "nest build --webpack && sed -i 's/exports.handler = handler;/module.exports.handler = handler;/g' dist/main.js",
"build:mac": "nest build --webpack && sed -i '' 's~exports.handler = handler;~module.exports.handler = handler;~g' dist/main.js",

请注意,MacOS有一个特定的命令,因为出于某种原因,它有一个不同的sed实现。

相关问题