如何为 AWS Lambda nodejs 运行时构建单个 js 文件

How do I build a single js file for AWS Lambda nodejs runtime

我们正在开发 project/framework 来帮助在 AWS Lambda 中部署和维护代码。我想 build/bundle 一个 lambda 函数的所有 node.js 代码到一个 js 文件中,因为:

我们不想创建自定义捆绑器来执行此操作,因为已经有很多选项(systemjs、browserify、webpack 等)。但是,我们担心某些节点模块不能很好地与 bundlers/builders.

配合使用的问题

具体来说 aws-sdkknown issues with webpack, says it has browserify support 但我已经与那些对浏览器化 aws-sdk 有问题的人交谈过

我们想选择一个现有的捆绑器(或 2 个),但我们想确保它适用于尽可能多的 modules/code。我们正在尝试为 JAWS 创建一个插件生态系统,因此做好这一点很重要(不想让人们失望,因为他们使用的模块 X 不会捆绑)。

问题:

  1. 我将如何bundling/building满足这些限制?
  2. 我们是否可以为我们产品的消费者提供任何指南,以确保他们 write/use 将捆绑代码?例如:动态 require()s 导致问题 AFAIK。

可能的答案可能是使该函数的行为类似于引导加载程序。使函数从 S3 下载打包代码,解压并运行它。

必须按照您提议的方式修改代码似乎是个坏主意,可能会导致无法预测且难以调试的错误。

我不喜欢使用单个文件解决方案,而是上传打包了所有代码的 zip 文件。我为此使用 gulp。下面的代码仅上传生产依赖项,不包括开发依赖项和之前上传的 zip 存档。您还可以使用 gulp.src.

参数排除您的测试文件夹或任何其他文件

顺便提一下,aws-sdk 库在我的开发依赖项中,因为 AWS Lambda 已经有一个副本 ;)

var gulp = require('gulp');
var lambda = require('gulp-awslambda');
var zip = require('gulp-zip');
var settings = require('./settings');
var argv = require('yargs').argv;
var p = require('./package.json');

gulp.task('default', function () {
    var profile = argv.profile;
    var src = ['**', '!*.zip', '!node_modules/aws-sdk{,/**}'];
    var i;
    for (i in p.devDependencies) {
        src.push("!node_modules/" + i + "{,/**}");
    }
    if (!profile) {
        profile = settings.aws.defaultProfile;
    }
    return gulp.src(src)
        .pipe(zip('archive.zip'))
        .pipe(lambda(settings.aws.lambda, {
            region: settings.aws.region,
            profile: profile
        }))
        .pipe(gulp.dest('.'));
});

这并没有直接回答您的问题,但 serverless 项目可能正是处于这种情况的人所需要的。

它允许您在普通的 webpack 风格的多文件架构中构建项目,然后使用 CLI 实用程序将您的项目构建到 Lambda 优化的文件中。

CLI 还处理函数初始化、部署和一连串我什至不需要的其他函数。它甚至会 create/configure 您的触发器(例如,s3 对象创建或通过 AWS API 服务设置新的 REST API)。

我只有几个 Lambda 函数,但在我开始使用 serverless 之前,即使维护这些函数也很痛苦 serverless

(这是一个讨好 post,但需要说明的是,我与该项目无关)

aws-sdk-js now officially supports browserify. You can why this is a great thing on my blog.

我创建了一个名为 serverless-plugin-browserify 的无服务器插件,它将以非常少的配置完成所有繁重的工作。

为了具体回答这个问题,我用这个 browserify 配置解决了这个问题:

{
  disable: false, //Not an official option, used as internal option to skip browserify
  exclude: [],    //Not an option, but will use for setting browserify.exclude() if defined in yml
  ignore:  [],    //Not an option, but will use for setting browserify.ignore() if defined in yml

  basedir:          this.serverless.config.servicePath,
  entries:          [],
  standalone:       'lambda',
  browserField:     false,  // Setup for node app (copy logic of --node in bin/args.js)
  builtins:         false,
  commondir:        false,
  ignoreMissing:    true,  // Do not fail on missing optional dependencies
  detectGlobals:    true,  // We don't care if its slower, we want more mods to work
  insertGlobalVars: {      // Handle process https://github.com/substack/node-browserify/issues/1277
    //__filename: insertGlobals.lets.__filename,
    //__dirname: insertGlobals.lets.__dirname,
    process: function() {
    },
  },
  debug:            false,
}

你可以看到我的完整代码here with a complete example here