serverless / serverless

⚡ Serverless Framework – Effortlessly build apps that auto-scale, incur zero costs when idle, and require minimal maintenance using AWS Lambda and other managed cloud services.
https://serverless.com
MIT License
46.39k stars 5.7k forks source link

configuration for ES6/ES7 within modules #434

Closed alexklibisz closed 8 years ago

alexklibisz commented 8 years ago

I'm trying to get ES6 and ES7 to work within my handler and lib functions. Locally it all runs fine, but when I deplloy, the lambda functions are returning errors.

Here is my s-function.json file:

{
  "functions": {
    "test": {
      "custom": {
        "excludePatterns": [],
        "envVars": [],
        "optimize": {
          "browserify": {
            "transform": [["babelify", { "presets": ["es2015", "stage-0"] }]]
          },
          "minify": true
        }
      },      
      "handler": "modules/babel/test/handler.handler",
      "timeout": 6,
      "memorySize": 1024,
      "eventSourceArn": "",
      "endpoints": [{
        "path": "babel/test",
        "method": "GET",
        "authorizationType": "none",
        "apiKeyRequired": false,
        "requestParameters": {},
        "requestTemplates": {
          "application/json": ""
        },
        "responses": {
          "400": {
            "statusCode": "400"
          },
          "default": {
            "statusCode": "200",
            "responseParameters": {},
            "responseModels": {},
            "responseTemplates": {
              "application/json": ""
            }
          }
        }
      }]
    }
  }
}

Here is the handler.js:

'use strict';
/**
 * Serverless Module: Lambda Handler
 * - Your lambda functions should be a thin wrapper around your own separate
 * modules, to keep your code testable, reusable and AWS independent
 * - 'serverless-helpers-js' module is required for Serverless ENV var support.  Hopefully, AWS will add ENV support to Lambda soon :)
 */

// Require Serverless ENV vars
var ServerlessHelpers = require('serverless-helpers-js').loadEnv();

// Lambda Handler
module.exports.handler = function(event, context) {
  const incr = (n) => n + 1;
  const toStr = (n) => `n: ${n}`;

  return context.succeed(toStr(incr(10)));
};

I am getting the following error for the default GET request to this endpoint.

{
  "errorMessage": "Use of const in strict mode.",
  "errorType": "SyntaxError",
  "stackTrace": [
    "Module._compile (module.js:439:25)",
    "Object.Module._extensions..js (module.js:474:10)",
    "Module.load (module.js:356:32)",
    "Function.Module._load (module.js:312:12)",
    "Module.require (module.js:364:17)",
    "require (module.js:380:17)"
  ]
}

I've tried commenting out the use-strict and changing const to var, but then I get an error about an unexpected token >, which I assume is the arrow function.

I have also installed babilify, babel-preset-es2015, and babel-preset-stage-0 to the module's package.json as both dev and standard dependencies.

prestonvanloon commented 8 years ago

@alexklibisz The transform property goes here: functions.test.custom.optimize.transform.

Example:

{
  "functions": {
    "notify": {
      "custom": {
        "excludePatterns": [],
        "envVars": [],
        "optimize": {
          "browserify": {
            "babelify": true
          },
          "minify": true,
          "transform": ["babelify", { "presets": ["es2015"] }]
        }
      },
      "handler": "modules/slack/notify/handler.handler",
      "timeout": 6,
      "memorySize": 1024,
      "events": [{
        "name": "default",
        "eventSourceArn": "",
        "startingPosition": "TRIM_HORIZON",
        "batchSize": 100,
        "enabled": true
      }],
      "endpoints": []
    }
  }
}
alexklibisz commented 8 years ago

I'm still receiving the same error.

Here is the s-function.json:

{
  "functions": {
    "test": {
      "custom": {
        "excludePatterns": [],
        "envVars": [],
        "optimize": {
          "browserify": {
            "babelify": true
          },
          "minify": true,
          "transform": ["babelify", { "presets": ["es2015"] }]
        }
      },
      "handler": "modules/babel/test/handler.handler",
      "timeout": 6,
      "memorySize": 1024,
      "eventSourceArn": "",
      "endpoints": [
        {
          "path": "babel/test",
          "method": "GET",
          "authorizationType": "none",
          "apiKeyRequired": false,
          "requestParameters": {},
          "requestTemplates": {
            "application/json": ""
          },
          "responses": {
            "400": {
              "statusCode": "400"
            },
            "default": {
              "statusCode": "200",
              "responseParameters": {},
              "responseModels": {},
              "responseTemplates": {
                "application/json": ""
              }
            }
          }
        }
      ]
    }
  }
}

Here is handler.js:

'use strict';
// Require Serverless ENV vars
var ServerlessHelpers = require('serverless-helpers-js').loadEnv();
// Lambda Handler
module.exports.handler = function(event, context) {
  const incr = (n) => n + 1;
  const toStr = (n) => `n: ${n}`;
  return context.succeed(toStr(incr(20)));
};

Again, it works fine locally, but then I get this when I hit the URL:

{
errorMessage: "Use of const in strict mode.",
errorType: "SyntaxError",
stackTrace: [
"Module._compile (module.js:439:25)",
"Object.Module._extensions..js (module.js:474:10)",
"Module.load (module.js:356:32)",
"Function.Module._load (module.js:312:12)",
"Module.require (module.js:364:17)",
"require (module.js:380:17)"
]
}
joostfarla commented 8 years ago

@alexklibisz Seems like ES6/7 is not transpiled at all. Did you install the plugin correctly?

The steps needed to install a plugin are:

"plugins": [
    {
      "path": "serverless-optimizer-plugin"
    }
  ]

Documentation on this will be added soon.

Note: The current version of the serverless-optimizer-plugin is work-in-progress and still containing some issues and inconsistencies. There's currently an interesting open PR which will fix these issues: https://github.com/serverless/serverless-optimizer-plugin/pull/1, so it might be better to use the forked version for now.

alexklibisz commented 8 years ago

Thanks @joostfarla. I tried that, but I get the following warning when I run sls dash deploy:

WARNING: This plugin was requested by this project but could not be found: serverless-optimizer-plugin

and still same syntax errors on the endpoint.

Worth mentioning: there's no package.json in the plugins directory and also no package.json in the plugins directory. When I made a package.json in the plugins dir and then installed the plugin with --save, I get:

path.js:8
    throw new TypeError('Path must be a string. Received ' +
    ^

TypeError: Path must be a string. Received [Function: ServerlessPlugin]
    at assertPath (path.js:8:11)
    at Object.posix.join (path.js:479:5)
    at module.exports.SPlugin._optimize.evt._browserifyBundle.evt.function.custom.optimize.browserify.exclude.forEach._generateIncludePaths.evt (/home/alex/dev/loop/studyloop-serverless/plugins/node_modules/serverless-optimizer-plugin/index.js:10:35)
    at Serverless._loadPlugins (/usr/local/lib/node_modules/serverless/lib/Serverless.js:306:25)
    at new Serverless (/usr/local/lib/node_modules/serverless/lib/Serverless.js:62:12)
    at Object.<anonymous> (/usr/local/lib/node_modules/serverless/bin/serverless:11:23)
    at Module._compile (module.js:425:26)
    at Object.Module._extensions..js (module.js:432:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Function.Module.runMain (module.js:457:10)
    at startup (node.js:136:18)
    at node.js:972:3

I'm not sure how to specify to use a PR/fork for a plugin. For the sake of time I'll probably just hold off and use ES5 for now.

joostfarla commented 8 years ago

@alexklibisz Easiest way of using the forked version for now is by doing a git clone of the forked repo instead of npm install in the plugins/custom dir:

git clone git@github.com:chrisseto/serverless-optimizer-plugin.git

Make sure this command is run within the plugins/custom directory, so that the plugin's location becomes plugins/custom/serverless-optimizer-plugin. Don't forget to run npm install from the plugins/custom/serverless-optimizer-plugin dir to install its dependencies.

alexklibisz commented 8 years ago

@joostfarla I did that and the warning went away, but the endpoint still returns the same error.

I'm just going to stick with es5 until this is documented or an example is posted. Just a time trade-off decision. Thank you for the pointers though.

joostfarla commented 8 years ago

@alexklibisz I managed to get it working by using the following config in s-function.json:

      "custom": {
        "excludePatterns": [],
        "envVars": [],
        "optimize": {
          "browserify": {
            "transforms": [{
              "name": "babelify",
              "opts": {
                "presets": ["es2015"]
              }
            }],
            "exclude": [
              "aws-sdk"
            ]
          },
          "minify": true
        }
      },

I had to install the babel-preset-es2015 package in my module (back/module/<name>) dirs.

But, as you mentioned, it requires a lot of custom hacking and it might be better to just leave ES6/7 syntax for now ;)

betarelease commented 8 years ago

Is there a standard/approved fix for this? I started using serverless and this is the first error I see "This plugin could not be found: serverless-optimizer-plugin"

chadsmith commented 8 years ago

@betarelease It sounds like you might be missing the serverless-optimizer-plugin. The babel-runtime is a good alternative too.

HyperBrain commented 8 years ago

@betarelease @joostfarla For me the optimizer plugin configured as you stated works really great. To have babel separated from my lambda/library's modules I've put the function base into a subdir of the project and the babel module directly into the project's root.

betarelease commented 8 years ago

@HyperBrain maybe I am missing the plugin. But I was following the instructions on serverless and on step two where I was installing project serverless-starter and this message showed up. Do I need to install the plugin before I install the project?

HyperBrain commented 8 years ago

@betarelease You need to install the optimizer plugin by using npm install serverless-optimizer-plugin in your project's root directory. This is not done automatically, as well as you have to do a npm installto install your project's dependencies. IMHO the plugin is not installed by default. Please also check the s-project.json, if the optimizer plugin is in the plugins array.

flomotlik commented 8 years ago

I'm closing the issue now, let us know if any further questions come up