Очень запутанная проблема express .Router () - PullRequest
1 голос
/ 02 апреля 2020

У меня есть большая сборка приложения с NestJS, которую я развертываю, используя serverless framework. Я делал это в течение некоторого времени, и все было замечательно. Через пару дней go мне пришлось обновиться до Nestjs 7, и у меня возникло множество проблем при начальной загрузке приложения, когда оно развернуто до aws. Пройдя бесчисленные неудачные попытки решить проблему, оказалось, что на самом деле это никак не связано с процессом начальной загрузки Nestjs / serverless, и apollo-server-express не смог получить доступ к маршрутизатору express - ошибка с ошибкой:

express_1.default.Router is not a function

Наконец я понял, что когда я импортирую express напрямую и пытаюсь получить доступ к express.Router(), у меня возникает та же проблема. Поэтому я сделал очень простой тест:

lambda.ts:

import { Context, Handler } from "aws-lambda";
import express from "express";

export const handler: Handler = async (event: any, context: Context) => {
  console.log("Import express:", express);
  console.log("Test express app: ", express());
  console.log("Test router:", express.Router());

  /* express.Router() ->
  ERROR TypeError: express_1.default.Router is not a function at 
  /var/task/dist/lambda.js:19:51 at Generator.next (<anonymous>) at 
  /var/task/dist/lambda.js:8:71 at new Promise (<anonymous>) at 
  __awaiter (/var/task/dist/lambda.js:4:12) at exports.handler (/var/task/dist/lambda.js:16:39) at 
  Runtime.handler (/var/task/serverless_sdk/index.js:9:131872) at 
  Runtime.handleOnce (/var/runtime/Runtime.js:66:25)
  */
};

Это не с ошибкой в ​​комментарии, как было сказано ранее. Вот другие файлы:

serverless.yml:

service: xxxxx
app: xxxx
tenant: xxxxx

plugins:
  - serverless-pseudo-parameters
  - serverless-prune-plugin
  - serverless-deployment-bucket

provider:
  name: aws
  runtime: nodejs12.x
  region: eu-west-1
  stage: dev
  timeout: 29
  memorySize: 3008
  deploymentBucket:
    name: ${self:service}-${self:custom.currentStage}-deployment-bucket
    serverSideEncryption: AES256

custom: ${file(./serverless-common.yml):custom}
package:
  include:
    - ./dist/**
  exclude:
    - node_modules/aws-sdk/**

functions:
  index:
    handler: ./dist/lambda.handler
    name: bm-${self:custom.currentStage}-express-test
    events:
      - http:
          path: "/{proxy+}"
          method: POST

пакет. json:

{
  "name": "@xxx/XXXXXX",
  "version": "0.1.13",
  "dependencies": {
    "express": "4.17.1"
  },
  "devDependencies": {
    "serverless-deployment-bucket": "1.1.1",
    "serverless-prune-plugin": "1.4.2",
    "serverless-pseudo-parameters": "2.5.0",
    "ts-node": "^8.7.0",
    "tsconfig-paths": "^3.7.0",
    "tslint": "5.12.1",
    "tslint-config-prettier": "^1.18.0",
    "typescript": "^3.8.3"
  }
}

tsconfig. json:

{
  "compilerOptions": {
    "baseUrl": "./",
    "paths": {
      "@root/*": ["src/*"]
    },
    "module": "commonjs",
    "moduleResolution": "node",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es6",
    "sourceMap": true,
    "outDir": "dist",
    "esModuleInterop": true
  },
  "include": ["*"],
  "exclude": ["**/node_modules/**/*", "dist"]
}

Я хотел бы подчеркнуть, что этот код дает сбой только после развертывания в lambda. Он работает нормально локально, что указывает на то, что, возможно, что-то не так с процессом упаковки, но zip-файл содержит правильный код и зависимости.

Я долго работал над этой проблемой, прежде чем сузить ее до этого. Если кто-то сможет пролить свет на вышесказанное, это было бы очень признательно, поскольку оно, очевидно, блокирует меня.

Большое спасибо


ОБНОВЛЕНИЕ:

ОК, похоже что если я:

import Router from 'express/lib/router'

, то я получаю экземпляр маршрутизатора. Это тот же экземпляр, который индекс express должен экспортировать.

Так что я близок, но это кажется неправильным, я ничего не изменил, я чувствую, что у меня какая-то неправильная конфигурация модуля или что-то в этом роде.

Так почему я не могу сделать express.Router(). Любые идеи будут с благодарностью.


ОБНОВЛЕНИЕ:

В конце я исправил apollo-server-express, чтобы он получал экземпляр маршрутизатора из lib / router, а затем все работает, как ожидалось.

Я, очевидно, не хочу этого делать, поэтому мне действительно нужно разобраться, что вызывает это.

Исправлен ApolloServer. js: https://gist.github.com/TreeMan360/8dc8373ffebe2b24ff51df42090fcb52


ОБНОВЛЕНИЕ:

Другая связанная проблема возникла из-за того, что заголовки возвращаются как часть тела ответа, например:

HTTP/1.1200OKX-Powered-By: ExpressAccess-Control-Allow-Origin: *Content-Type: application/json;charset=utf-8Content-Length: 155ETag: W/"9b-mbrRmusN4ADjvBFA5aFJNLyRMHs"Date: Sat,
04Apr202014: 35: 09GMTConnection: keep-alive{
  "data": {
    "memberLoginHook": {
      "id": "1bb4ca87-d9f6-4ccb-a2a4-0249b19699b3",
      "occupation": "C3PO",
      "positions": [
        {
          "id": "f4deaf82-ad87-472b-82ab-c78d08138526"
        }
      ]
    }
  }
}

Также стоит отметить, что я нашел кто-то еще, кто имеет такую ​​же проблему: https://forum.serverless.com/t/highly-confusing-express-router-issue/10987/8

1 Ответ

2 голосов
/ 04 апреля 2020

Я знаю, что вызывает проблему, очень странная ошибка имеет очень странное решение. Попробуйте отключить Serverless Framework Enterprise (если он включен), вы можете просто закомментировать строки клиента и приложения в файле serverless.yml и снова развернуть приложение. Я думаю, что в последней версии serverless-sdk есть ошибка.

...