首页 > 解决方案 > 无服务器不包括 lambda 函数中的 node_modules

问题描述

我正在尝试部署具有一些外部依赖项的 lambda 函数,但是当我看到我的 lambda 已部署或打包时,尽管 webpack 清楚地显示依赖项已正确打包,但我看不到 node_modules。

这是 lambda 函数:

const AWS = require('aws-sdk')
import { AWSAppSyncClient } from 'aws-appsync'
import { gql } from 'graphql-tag'

const graphqlClient = new AWSAppSyncClient({
  url: process.env.APP_SYNC_API_URL,
  region: process.env.AWS_REGION,
  auth: {
    type: 'AWS_IAM',
    credentials: {
      accessKeyId: process.env.AWS_ACCESS_KEY_ID,
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
      sessionToken: process.env.AWS_SESSION_TOKEN
    }
  },
  disableOffline: true
})

const mutation = gql`mutation CreateRadonData($id: String!, $name: String!) {
  createRadonData(id: $id, name: $name) {
    id
    name
  }
}`

export const handler = (event) => {
  event.Records.forEach((record) => {
    if (record.eventName !== 'INSERT') return

    const newImage = AWS.DynamoDB.Converter.unmarshall(record.dynamodb.NewImage)

    graphqlClient.mutate({
      mutation,
      variables: {
        id: newImage.id,
        name: newImage.name
      }
    })
  })
}

这是sls打包时的日志serverless package --package artefacts

Serverless: Bundling with Webpack...
asset src/functions/onCreateRadonData.js 1.46 KiB [emitted] [minimized] (name: src/functions/onCreateRadonData) 1 related asset
runtime modules 937 bytes 4 modules
built modules 1.17 KiB [built]
  ./src/functions/onCreateRadonData.ts 1.05 KiB [built] [code generated]
  external "aws-sdk" 42 bytes [built] [code generated]
  external "aws-appsync" 42 bytes [built] [code generated]
  external "graphql-tag" 42 bytes [built] [code generated]
webpack compiled successfully in 736 ms
Serverless: Copying existing artifacts...
Serverless: Packaging service...

正如您在日志中看到的,webpack 正在打包我的 lambda 函数及其依赖项aws-sdkaws-appsync并且graphql-tag. 但是在 artefacts 文件夹(解压缩)中,我看不到 node_modules,只有 lambda 函数。

在此处输入图像描述

这是我的 webpack 配置(使用serverless create --template aws-nodejs-typescript脚本构建):

const path = require('path');
const slsw = require('serverless-webpack');
const nodeExternals = require('webpack-node-externals');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');

/*
This line is only required if you are specifying `TS_NODE_PROJECT` for whatever reason.
 */
// delete process.env.TS_NODE_PROJECT;

module.exports = {
  context: __dirname,
  mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
  entry: slsw.lib.entries,
  devtool: slsw.lib.webpack.isLocal ? 'eval-cheap-module-source-map' : 'source-map',
  resolve: {
    extensions: ['.mjs', '.json', '.ts'],
    symlinks: false,
    cacheWithContext: false,
    plugins: [
      new TsconfigPathsPlugin({
        configFile: './tsconfig.paths.json',
      }),
    ],
  },
  output: {
    libraryTarget: 'commonjs',
    path: path.join(__dirname, '.webpack'),
    filename: '[name].js',
  },
  optimization: {
    concatenateModules: false,
  },
  target: 'node',
  externals: [nodeExternals()],
  module: {
    rules: [
      // all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
      {
        test: /\.(tsx?)$/,
        loader: 'ts-loader',
        exclude: [
          [
            path.resolve(__dirname, 'node_modules'),
            path.resolve(__dirname, '.serverless'),
            path.resolve(__dirname, '.webpack'),
          ],
        ],
        options: {
          transpileOnly: true,
          experimentalWatchApi: true,
        },
      },
    ],
  },
  plugins: [],
};

和yaml文件:

service: aws

plugins:
  - serverless-appsync-plugin
  - serverless-offline
  - serverless-webpack

package:
  exclude:
    - 'node_modules/**'
    - '!node_modules/aws-appsync/**'
    - '!node_modules/aws-appsync-auth-link/**'
    - '!node_modules/aws-appsync-subscription-link/**'
    - '!node_modules/graphql-tag/**'


provider:
  name: aws
  runtime: nodejs14.x
  region: eu-west-1
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Scan
        - dynamodb:Query
        - dynamodb:PutItem
      Resource:
        - !GetAtt RadonDataTable.Arn
        - !Join [ '', [ !GetAtt RadonDataTable.Arn, '/*' ] ]
    - Effect: Allow
      Action:
        - appsync:GraphQL
      Resource: 
      - !GetAtt GraphQlApi.Arn
      - !Join [ '/', [ !GetAtt GraphQlApi.Arn, 'types', 'Mutation', 'fields', 'createRadonData' ] ]

custom:
  appSync:
    name: ${self:service}
    authenticationType: AWS_IAM
    mappingTemplates:
      - dataSource: RadonData
        type: Query
        field: listRadonData
        request: Query.listRadonData.request.vtl
        response: Query.listRadonData.response.vtl
      - dataSource: None
        type: Mutation
        field: createRadonData
        request: Mutation.createRadonData.request.vtl
        response: Mutation.createRadonData.response.vtl
    schema: src/schema.graphql
    dataSources:
      - type: NONE
        name: None
      - type: AMAZON_DYNAMODB
        name: RadonData
        description: 'DynamoDB Radon Data table'
        config:
          tableName: !Ref RadonDataTable

    

functions:
  handleDynamoDbStream:
    maximumRetryAttempts: 1
    maximumRecordAgeInSeconds: 60
    handler: src/functions/onCreateRadonData.handler
    environment:
      APP_SYNC_API_URL: !GetAtt GraphQlApi.GraphQLUrl
    events:
      - stream:
          type: dynamodb
          arn: !GetAtt RadonDataTable.StreamArn

resources:
  Resources:
    RadonDataTable:
      Type: AWS::DynamoDB::Table
      Properties:
        ProvisionedThroughput:
          ReadCapacityUnits: 5
          WriteCapacityUnits: 5
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S
        KeySchema:
          - AttributeName: id
            KeyType: HASH
        StreamSpecification:
          StreamViewType: NEW_IMAGE

我尝试手动包含/排除模块(如您在 serverless.yml 文件中看到的那样),但我也不起作用(无论如何,这似乎是一种不一致的方式)。

有人能告诉我为什么外部模块没有与我的 lambda 函数一起打包吗?先感谢您!

标签: typescriptamazon-web-serviceswebpackaws-lambdanode-modules

解决方案


推荐阅读