乐趣区

关于前端:更灵活的-serverless-framework-配置文件

更灵便的 serverless framework 配置文件

前言

再通过前置教程的部署之后,不晓得你有没有留神这样一个问题,就是咱们部署的函数名,以及 API 网关endpoint,它们的名称和门路都带一个 dev?

这个就是 stage 导致的了,咱们执行 sls deploy 部署的时候,因为没有指定 --stage 的参数,导致它默认就是 dev,所以咱们之前部署的函数名称,网关外面都带它。

那么它有什么作用呢?实际上这个值就是用来给你的函数,以及对应的服务去辨别阶段 / 环境的。

比方咱们一个提供 web 服务的函数,咱们本人人为划分出三个环境:

  1. dev 用于给开发者自行测试
  2. sit 用于进行集成测试
  3. prod 生产环境

不同的环境,它们各自的 API 网关 调配的 endpoint 也是不同的。

如果你有一个域名,你就能够把域名多配置一些主或多级域名,把它们的 CNAME 解析到指定的 API 网关 地址来应用。当然你仅仅在域名控制台,间接解析是不失效的,因为API 网关 有个双重验证,你必须进入 API 网关自定义域名 界面,创立自定义域名,并绑定 ACM 证书,审核通过后解析能力失效。

什么是 ACM 证书 ACM 残缺名称为Amazon Certificate Manager,点击这里查看更多

释怀,ACM 证书 申请和颁发非常简单,它的性能和申请流程和咱们申请收费的 SSL/TLS 证书是统一的,都是咱们域名多解析一个 CNAME 的事件。

这时候咱们天然能够利用 cli option 去设置:

"scripts": {
  "deploy:dev": "sls deploy",
  "deploy:sit": "sls deploy -s sit",
  "deploy:prod": "sls deploy -s prod"
},

然而随着我的项目的日益简单,你会发现应用 CLI 命令,一直的去减少配置项,这种形式既繁琐,又效率低下,有什么形式能够用一个变量去管制大量的配置呢?

<!– 一般的 nodejs 我的项目咱们通常会想到 dotenv,侥幸的是,serverless framework 同时也给咱们提供了更多的抉择。–>
serverless framework 里,通常咱们能够应用 动静变量 的形式去解决这个问题。

动静变量

什么是动静变量?实际上它们就是非凡写法的字符串罢了。变量常见的写法如下所示:

${variableSource}
${sls:stage}-lambdaName
${env:MY_API_KEY}
${file(create_request.json)}
${self:service}:${sls:stage}:UsersTableArn

serverless.yml 反对应用上述变量的形式,来实现配置的援用与读取,它们是十分有用的,毕竟你不可能把某些配置项,诸如 secret 什么的间接 inline 写在 yml 文件里。

其中 ${} 就是变量援用的写法,会在 sls cli 运行的时候,把它们替换成真正的值。

# ${} 第二个参数是默认值
otherYamlKey: ${variableSource, defaultValue}

这里介绍一些罕用的变量:

self

首先必须要讲的就是 self 了,它是咱们利用配置本身其余值的要害,self 指向的就是咱们 yml 配置的根节点。这里我给出一个示例,置信聪慧的你能够一眼看出它的用法。

service: new-service
provider: aws
custom:
  globalSchedule: rate(10 minutes)
  # 援用的第一行 service: new-service
  serviceName: ${self:service}
  # 援用的上一行 serviceName: ${self:service}
  exportName: ${self:custom.serviceName}-export

functions:
  hello:
    handler: handler.hello
    events:
      # ${self:someProperty} 
      # self 指向的就是 yml 配置的根节点,所以能力 
      - schedule: ${self:custom.globalSchedule}
resources:
  Outputs:
    NewServiceExport:
      Value: 'A Value To Export'
      Export:
        Name: ${self:custom.exportName}

env

顾名思义,应用系统配置的环境变量:

service: new-service
provider: aws
functions:
  hello:
    name: ${env:FUNC_PREFIX}-hello
    handler: handler.hello

这个个别配合 dotenv 等工具比拟好用。

sls

这个变量能够获取一些 Serverless Core 值,比方 instanceIdstage,用例如下

service: new-service
provider: aws
 
functions:
  func1:
    name: function-1
    handler: handler.func1
    environment:
      APIG_DEPLOYMENT_ID: ApiGatewayDeployment${sls:instanceId}
      STAGE: ${sls:stage}

其中 ${sls:stage} 指令的本质实际上是 ${opt:stage, self:provider.stage, "dev"} 的缩写模式,所以你也明确为什么默认值是 dev 了。

opt

这个变量就是去取 CLI 传入的 Options 外面的值:

service: new-service
provider: aws
functions:
  hello:
    name: ${opt:stage}-hello
    handler: handler.hello

file

模块化配置的外围办法 / 变量,应用这个变量办法能够去读取文件,并进行援用,例如咱们能够在这里引入另外的 yml,json,js文件:

# 你甚至能够引入整个 yml 文件作为配置
custom: ${file(./myCustomFile.yml)}
provider:
  name: aws
  environment:
    # 引入 json 文件
    MY_SECRET: ${file(./config.${opt:stage, 'dev'}.json):CREDS}
 
functions:
  hello:
    handler: handler.hello
    events:
      - schedule: ${file(./myCustomFile.yml):globalSchedule} # Or you can reference a specific property
  world:
    handler: handler.world
    events:
      # 甚至能够引入 `js` 文件
      - schedule: ${file(./scheduleConfig.js):rate}

这时候它就会依据咱们传入的 stage 参数,去读取相对路径下不同的配置文件了。

其中引入 js 文件的代码有肯定的限度,它必须是 commonjs 格局,且必须导出一个 js 对象,或者是导出一个function。导出对象形式很简略且泛用性不强,咱们这里以办法为例:

// 目前必须是 commonjs 格局,且返回一个对象作为值
// 办法同步 / 异步的都能够
module.exports = async ({options, resolveVariable}) => {
  // We can resolve other variables via `resolveVariable`
  const stage = await resolveVariable('sls:stage');
  const region = await resolveVariable('opt:region, self:provider.region,"us-east-1"');
  ...
 
  // Resolver may return any JSON value (null, boolean, string, number, array or plain object)
  return {
    prop1: 'someValue',
    prop2: 'someOther value'
  }
}

咱们能够在外面获取到其余的变量,并进行额定的计算解决,或者咱们能够在这里申请远端获取数据作为部署的额定配置。

更多

除此之外,它还能援用到更多服务的变量,诸如 CloudFormation,S3SSM 等等服务,更多更全面的变量详见:官网的变量大全地址

配置反对的其余格局

实际上目前的 serverless cli 不止能够承受 serverless.yml,也能够承受包含 serverless.ts, serverless.json, serverless.js 格局。

这里笔者只举荐两种格局 serverless.ymlserverless.js

为什么不是 serverless.json?因为 json 文件表现力弱,甚至要 jsonc 才反对正文,所以放弃。

为什么不是 serverless.ts,因为间接应用会出错,详见 issues/48,不够省心。这点不如应用 js + jsdoc 的组合,智能提醒有了,灵活性也有了。

所以咱们总结一下 serverless.ymlserverless.js 的长处:

  • serverless.yml: 足够简略,配合动静变量比拟灵便
  • serverless.js: 能够应用 nodejs api,也能够配合动静变量,更加灵便,而且配置能够应用原生 js 写法。

这里咱们以 serverless.js 配置文件为例:

智能提醒, 须要 npm i -D @serverless/typescript

/**
 * @typedef {import('@serverless/typescript').AWS} AWS
 * @type {AWS}
 */
const serverlessConfiguration = {
  service: 'aws-node-ts-hello-world',
  frameworkVersion: '3',
  provider: {// ...},
  functions: {// ...},
}

module.exports = serverlessConfiguration

当然因为它是 nodejs 运行时的缘故,你能够把配置文件拆分成多个文件,再应用 commonjs 原生的形式去援用它们。你也能够应用环境变量,node:fsnode:path 等等模块去按条件动静去生成配置文件,甚至应用某些第三方库做一些额定的工作,这切实是太灵便了!

Next Chapter

当初你曾经浅尝辄止了 serverless framework 动静配置文件。

下一篇,《与传统 nodejs web 框架的联合》中,将会具体介绍如何部署 express/koa 和以它们 2 个为基底的 serverless 利用,欢送浏览。

残缺示例及文章仓库地址

https://github.com/sonofmagic/serverless-aws-cn-guide

如果你遇到什么问题,或者发现什么勘误,欢送提 issue 给我

退出移动版