Node.js async/await中断了我为AWS Lambda构建的网页包;如何迁移到节点8.10?
注意:这是一个关于将AWS Lambda Webpack版本从v6.10迁移到v8.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,这太棒了!直到它立即破坏了我的网页包构建。经过
一段时间以来,在阅读了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" }}]
]