Packaging code for AWS Lambda

扶醉桌前 提交于 2019-12-12 18:36:39

问题


I am trying to package code for AWS Lambda. Lambda has various restrictions, such as using Node 6.10, and not having a build step, like AWS EB does. I also am using NPM modules, so these will need to be bundled with the AWS Lambda handler.

Here is what I would like to do:

  • Define and use NPM modules (pure JS modules only)
  • Transpile all code (including NPM modules) to a JS version that Node 6.10 supports
  • Statically link all NPM modules into one big JS file
  • Upload that single file to AWS Lambda

For example, suppose I have an NPM module foo (node_modules/foo/index.js):

export default { x: 1 };

and I have my own code ('index.js'):

import foo from 'foo';

export const handler = (event, context, callback) => {
  console.log(foo); // Will appear in CloudWatch logs
  callback(null, 'OK');
};

The output would be something like this ('dist/bundle.js'):

var foo = { x: 1 };

exports.handler = function(event, context, callback) {
  console.log(foo);
  callback(null, 'OK');
};

I should be able to upload and run bundle.js on AWS Lambda without further modification.

How can I achieve this using existing JS tools?


回答1:


You can use serverless with serverless-webpack

Then you deploy your bundle with serverless deploy




回答2:


It turns out that this is possible, but it requires some tricky configuration to achieve. I have created a boiler-plate repo for others to use.

Here are the important bits...

First, you need a .babelrc that targets Node.js 6.10:

{
  "presets": [
    [
      "env", {
        "targets": {
          "node": "6.10"
        }, 
        "loose": false,
        "spec": true
      }
    ]
  ]
}

Next, you need to configure Webpack to generate a commonjs library targetting node:

const path = require('path');
const webpack = require('webpack');

const debug = process.env.NODE_ENV !== 'production';

module.exports = {
  context: __dirname,
  entry: [ 'babel-polyfill', './index.js' ],
  output: {
    path: path.join(__dirname, 'out'),
    filename: 'index.js',
    libraryTarget: 'commonjs'
  },
  devtool: debug ? 'source-map' : false,
  module: {
    rules: [
      {
        test: /\.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            babelrc: true,
            compact: !debug
          }
        }
      }
    ],
  },
  target: 'node',
  plugins: [
    new webpack.DefinePlugin({ 'global.GENTLY': false })
  ]
};

Note that you do not want to ignore the node_modules folder, since that would prevent static-linking.

The babel-polyfill plugin is also crucial if you want to use modern JS features.

Your actual handler code should have a named export that matches what you have set in the AWS console:

export const handler = (event, context, callback) => callback(null, 'OK');

Do not do it like this!

// Bad! 
export default {
  handler: (event, context, callback) => callback(null, 'OK'),
};

When packaging the code, make sure you add index.js to the top level of the zip:

zip -j bundle.zip ./out/index.js


来源:https://stackoverflow.com/questions/47905321/packaging-code-for-aws-lambda

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!