我有一个用 React 编写的 SPA(单页应用程序)与一个用 nodejs 编写的 REST JSON API 通信,并以 monolith 的形式托管在 Heroku 上。
我迁移到 AWS Lambda 并将整体拆分为 3+ AWS Lambdas micro services 在 monorepo 内
如果您的 SPA 要求用户登录才能执行任何操作,则以下项目结构很好。
我使用了一个 git 存储库,其中每个服务都有一个文件夹:
在每个服务的文件夹中,我都有一个 serverless.yml 定义部署到单独的 AWS Lambda。
每个服务仅映射到 1 个函数 index,它接受所有 HTTP 端点。我确实使用了 2 个环境 staging 和 production。
我的 AWS Lambda 是这样命名的:
- 示例-api-staging-index
- 示例-api-生产-index
- 示例-应用程序-staging-index
- 示例-应用程序-生产-索引
- 示例-www-staging-index
- 示例-www-生产-索引
我使用AWS Api Gateway's Custom Domain Names 将每个 lambda 映射到公共域:
您可以使用 serverless.yml 资源或插件定义域映射,但您只需执行一次,因此我从 AWS 网站控制台手动完成。
我的 .com 域托管在 GoDaddy 上,但我将其迁移到 AWS Route 53 since HTTPS certificates are free。
应用服务
- /bundles-生产
- /bundles-staging
- src(此处为 React/Angular 单页应用程序)
- handler.js
- package.json
- serverless.yml
应用服务包含一个文件夹 /src,其中包含单页应用程序代码。 SPA 基于环境在我的计算机上本地构建在 ./bundles-production 或 ./bundles-staging 中。 build 生成 .js 和 .css 包以及 index.html。当我运行 serverless deploy -v -s production 时,使用 serverless-s3-deploy 插件将文件夹的内容部署到 S3 存储桶。
我只为 serverless.yml 中的所有端点定义了 1 个函数(我使用 JSON 而不是 YAML):
...
"functions": {
"index": {
"handler": "handler.index",
"events": [
{ "http": "GET /" },
{ "http": "GET /{proxy+}"}
]
},
},
handler.js 文件返回 /bundles-staging 或 /bundles-production 中定义的 index.html
我使用 webpack 构建 SPA,因为它与带有 serverless-webpack 插件的无服务器集成得非常好。
API 服务
我使用aws-serverless-express 定义所有 REST JSON API 端点。 aws-serverless-express 与普通快递一样,但您不能执行 express.static() 和 fs.sendFile() 之类的操作。
我最初尝试为每个端点使用单独的 AWS Lambda 函数而不是 aws-serverless-express,但我很快就点击了 CloudFormation mappings limit。
www 服务
如果您的单页应用程序的大部分功能都需要登录,那么最好将 SPA 放在单独的域中,并将 www 域用于针对 SEO 优化的服务器端渲染登录页面。
奖金:
graphql 服务
使用微服务架构可以很容易地进行实验。我目前正在使用apollo-server-lambda 重写graphql 中的REST JSON API