如何为多运行时 AWS Lambda 服务设置 serverless.yml 和 webpack.config

How to setup serverless.yml and webpack.config for a multiple-runtime AWS Lambda service

我想从一个 serverless.yml 文件中使用 Node8.10 和 Ruby2.5 运行时部署 AWS Lambda 函数。

我设置了以下文件夹结构,/node 和 /ruby 包含我各自的处理程序。

 -/nodeRubyLambdas
  -/node
    -handler.js
    -package.json, package-lock.json, /node_modules
  -/ruby
    -rubyRijndaelEncryption.rb
    -Gemfile, Gemfile.lock, /vendor
  -serverless.yml
  -webpack.config.js
  -package.json for serverless-webpack

这是我的 serverless.yml

service: nodeRubyLambdas

plugins:
  - serverless-webpack
  - serverless-offline

custom:
  webpack:
    webpackConfig: ./webpack.config.js
    includeModules: true

provider:
  name: aws
  stage: dev
  region: us-west-2
  iamRoleStatements:
    - Effect: Allow
      Action:
        - lambda:InvokeFunction
      Resource: "*"

  package:
    individually: true

functions:
  nodeMain:
    handler: node/handler.main
    runtime: nodejs8.10
    events:
      - http:
          path: main
          method: get
    package:
      individually: true
  rubyEncryption:
    handler: ruby/rubyRijndaelEncryption.lambda_handler
    runtime: ruby2.5
    environment:
      RIJNDAEL_PASSWORD: 'a string'
    package:
      individually: true

我的 webpack 配置:(这是基本示例,当我遇到第一个错误时,我刚刚添加了忽略 ruby 文件的位。)

const slsw = require("serverless-webpack");
const nodeExternals = require("webpack-node-externals");

module.exports = {
  entry: slsw.lib.entries,
  target: "node",
  // Generate sourcemaps for proper error messages
  devtool: 'source-map',
  // Since 'aws-sdk' is not compatible with webpack,
  // we exclude all node dependencies
  externals: [nodeExternals()],
  mode: slsw.lib.webpack.isLocal ? "development" : "production",
  optimization: {
   // We do not want to minimize our code.
   minimize: false
  },
  performance: {
    // Turn off size warnings for entry points
    hints: false
  },
  // Run babel on all .js files and skip those in node_modules
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: "babel-loader",
        include: __dirname,
        exclude: [/node_modules/, /\.rb$/]
      }
    ]
  }
};

失败 #0: [Webpack 编译错误] 模块解析失败

失败 #1: 基本上,webpack 假定所有函数都是 .js 并尝试将它们打包。基于 this suggestion,我强制我在 webpack 配置中的入口点是我的 handler.js

 module.exports = {
  entry: "./node/handler.js",
  target: "node",
  ...

这只打包了 Node Lambda。 Ruby Lambda 的空占位符是在 AWS 上创建的。

失败#2: 我从 serverless.yml 中注释掉了 webpack,并在函数包选项中添加了 include 和 exclude 语句。

functions:
  nodeMain:

    package:
      individually: true
      include:
        - node/**
        - handler.js
      exclude:
        - ruby/**
        - rubyLambda/**
  rubyEncryption:

    package:
      individually: true
      include:
        - vendor/**
        - rubyRijndaelEncryption.rb
      exclude:
        - Gemfile
        - Gemfile.lock
        - node/**

这为 node/node_modules/@babel/core/node_modules/.bin/parser 获取了一个 [ENOENT:没有这样的文件或目录]。该文件不存在,但我不明白为什么要查找它,因为未调用 webpack。

算不算成功?: 如果我注释掉 webpack 并使用

,我就能部署 Lambdas
    serverless deploy function -f <function name here>

部署 Ruby Lambda,然后取消注释 webpack 并使用相同的东西部署 Node Lambda。

我相信有更好的方法让他们部署;我在我的设置中遗漏了什么吗?还有其他我没试过的选择吗?

P.S。我确实看到了这个 pull request https://github.com/serverless-heaven/serverless-webpack/pull/256,但它似乎自 2017 年以来就被废弃了。

serverless-webpack 不是为非 JS 运行时设计的。它劫持 serverless 打包并仅部署 webpack 输出。

以下是您的选择:

  1. 不要使用serverless-webpack,只需使用serverless'内置包装。
  2. 您可以直接使用 webpack(而不是 serverless-webpack),并将构建过程更改为先使用 webpack 进行编译,然后让 serverless 部署输出文件夹。

P.S。 package.individually 属性 是您 serverless.yml 中的根级别 属性。它不应该在 provider 或您的函数定义中。

对于那些可能正在寻找 serverless-webpack 以外的多运行时选项的人,我最终切换到了这个插件:https://www.npmjs.com/package/serverless-plugin-include-dependencies
它适用于我的运行时(Ruby 和 Node),并允许您将 package.individually 与包一起使用。include/exclude 如果插件遗漏某些内容,则在根和函数级别。