Node.js async/await中断了我为AWS Lambda构建的网页包;如何迁移到节点8.10?

Node.js async/await中断了我为AWS Lambda构建的网页包;如何迁移到节点8.10?,node.js,amazon-web-services,webpack,aws-lambda,Node.js,Amazon Web Services,Webpack,Aws Lambda,注意:这是一个关于将AWS Lambda Webpack版本从v6.10迁移到v8.10的问答-不需要任何帮助,但当然,我们始终鼓励提供更好的答案 一段时间以来,在阅读了James Long的优秀系列《带Webpack的后端应用程序》(和)之后,我一直是使用Webpack构建后端Lambdas的信徒 直到最近,Node.js的唯一版本是6.10;您必须以“回调”样式编写Lambda fn。但在2018年4月2日,建议的模式是async/await,这太棒了!直到它立即破坏了我的网页包构建。经过

注意:这是一个关于将AWS Lambda Webpack版本从v6.10迁移到v8.10的问答-不需要任何帮助,但当然,我们始终鼓励提供更好的答案


一段时间以来,在阅读了James Long的优秀系列《带Webpack的后端应用程序》(和)之后,我一直是使用Webpack构建后端Lambdas的信徒

直到最近,Node.js的唯一版本是6.10;您必须以“回调”样式编写Lambda fn。但在2018年4月2日,建议的模式是async/await,这太棒了!直到它立即破坏了我的网页包构建。经过一点调试后,我可以通过向Lambda处理程序添加一个异步fn来中断构建(我甚至不需要调用它):

明确地说,在AWS Lambda控制台中执行此操作非常好,运行非常好。Webpack甚至成功地构建了它,但在上传到AWS Lambda时,我收到以下错误消息:
未定义regeneratorRuntime
。我的代码如下。我需要做什么

webpack.config.js

const nodeExternals = require('webpack-node-externals');
const path = require('path');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const webpack = require('webpack');

const config = {
  entry: './src/index.js',

  output: {
    path: path.resolve(__dirname, 'dist'),
    library: 'index',
    libraryTarget: 'commonjs2',
    filename: 'index.js'
  },
  target: 'node', // building for a Node environment
  externals: [nodeExternals()], // in order to ignore all modules in node_modules folder 
  module: {
    rules: [{
      test: /\.(js|jsx)$/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['env']
        }
      }
    }]
  },
  plugins: [
    new UglifyJsPlugin()
  ]
};

module.exports = config;
package.json

{
  "name": "lambda-webpack",
  "version": "1.0.0",
  "description": "An empty project scaffold to enable webpack builds in AWS Lambda",
  "main": "index.js",
  "scripts": {
    "build": "webpack",
    "upload": "upload.bat"
  },
  "author": "Geek Stocks®",
  "license": "MIT",
  "devDependencies": {
    "aws-sdk": "^2.179.0",
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-env": "^1.6.1",
    "uglifyjs-webpack-plugin": "^1.1.6",
    "webpack": "^3.10.0",
    "webpack-node-externals": "^1.6.0"
  }
}

要开始在网页包构建的代码中使用async/await,您需要Babel的一些帮助,特别是
Babel运行时
Babel插件转换运行时
。幸运的是,在安装和使用这两个方面都有很好的编写。您需要Babel为您执行以下操作:

使用时自动需要babel运行时/再生器 生成器/异步函数

我不会重复那里写的内容,但是,特别要注意的是您需要如何安装它们,因为虽然它们的writeup肯定适用于大多数情况,但对于一些AWS Lambda开发人员来说,有一个必要的调整,他们以前不需要运行时
依赖项

第一部分很正常,您需要新的devdependency:

npm install --save-dev babel-plugin-transform-runtime
此外,您还需要调整
.babelrc
文件,就像它们描述的那样:

{
  "plugins": [
    ["transform-runtime", {
      "helpers": false,
      "polyfill": false,
      "regenerator": true,
      "moduleName": "babel-runtime"
    }]
  ]
}
但关键是,这是上面代码的新功能:
babel运行时
是常规的
依赖项
,而不是
devdependency

npm install --save babel-runtime
这两次安装和
.babelrc
调整确实解决了上述异步/等待问题,但它给上述构建带来了一个新问题:
找不到模块“babel runtime/regenerator”

如果你关心的是保持你的网页代码的小型化,你可能也会像上面的代码那样使用。例如,非常大,并且已经在Lambda环境中可用,因此再次绑定它是多余的。上面的
webpack node externals
配置默认情况下将webpack配置为忽略
node modules
中的所有模块,这是新问题的根源。新安装的
babel运行时
是一个模块,需要捆绑在构建中才能使Lambda正确运行

理解了这个问题,答案就变得简单了:不要使用默认配置。不要将任何内容传递给
网页包节点外部
,请按如下方式进行配置:

externals: [nodeExternals({
  whitelist: [
    'babel-runtime/regenerator',
    'regenerator-runtime'
  ]
})], // ignore all modules in node_modules folder EXCEPT the whitelist
这解决了原始的异步/等待问题,以及(可能的)新问题(如果您在构建中没有以前的
依赖项)。希望能有所帮助-快乐的Lambda
等待
ing

只有在使用NodeV6.10运行时才需要Geek股票。它允许您使用
async/await
语法和
babel运行时/再生器
将异步函数转换为ES6生成器,该生成器在Node v4.3.2和更新的运行时上受支持

但在节点v8.10中,情况有所不同
async/await
已受支持,因此无需Babel将
async
函数转换为生成器。你只要正确使用它,它就会工作

至于您的具体情况,我假设您只是将Javascript代码更改为使用
async/await
代码,但您没有告诉巴贝尔不要将
async/await
代码转换为生成器。这就是为什么
babel运行时
抱怨缺少插件的原因

如果是这种情况,您只需将Babel配置为仅以节点v8.10为目标。您可以在
.babelrc
中这样做

{
  "presets": [
    [
      "env",
      {
        "targets": {
          "node": "8.10"
        }
      }
    ]
  ]
}

babel
将停止转换这些
async
函数。由于它没有进行转换,它将不再需要
再生器运行时

在我的例子中,我将它与
nodejs12.x
一起使用。我收到错误未定义再生时间

我使用的是预设的
es2015
stage-0
,带有
node12.x
code。此外,我正在使用较旧版本的
babel

我所做的,安装:

"@babel/cli": "^7.10.1",
"@babel/core": "^7.10.2",
"@babel/preset-env": "^7.10.2"
然后设置此巴别塔预设:

"presets": [
    ["@babel/preset-env", {"targets": { "node": "current" }}]
]

谢谢,

OP问题中的代码是一个巴贝尔版本。你是通过建议完全移除巴别塔来回答这个移民问题的吗?看来你的答案是以不同的方式重新配置巴贝尔,而巴贝尔的建议就在他们的书中。我已经使用您的方法执行了git回滚并再次迁移,但出现了相同的错误(
未定义regeneratorRuntime
)。现在还不清楚你在说什么。我将尝试完全删除Babel,如果可能的话,这会更好。同样,当您为小于8的节点版本构建时,您只需要
再生器运行时
。如果
async/await
是Babel的唯一用例,那么您可以在目标节点v8时将其全部删除。我的答案是如果你还需要的话就留下巴贝尔。如果您只使用
async/await
,那么如果您的目标是节点v8.10,那么删除Babel会更好。提示:如果需要,请确保在开发机器和CI环境中也使用节点v8.10
"presets": [
    ["@babel/preset-env", {"targets": { "node": "current" }}]
]