此页面需要javascript支持,请在浏览器中启用javascript

serverless/components 代码简析

serverless
阅读 

@serverless/components 代码简析

文章仅代表作者本人的认知,如有谬误,欢迎指正。 本篇文章建议配合 @serverless/components 源码 食用

前言

对于我们使用 Serverless Framework 的开发人员来说 sls 无疑是最常用的命令了

然而,当我们翻开 serverless 的源码一看,就会发现,cli 入口处实际上做了一个分支选项

const componentsV1 = require('@serverless/cli')
const componentsV2 = require('@serverless/components')
// Serverless Components v1 CLI (deprecated)
if (componentsV1.runningComponents()) return () => componentsV1.runComponents()
// Serverless Components CLI
if (componentsV2.runningComponents()) return () => componentsV2.runComponents()

@serverless/cli 作为 components v1 版本,目前已经废弃

@serverless/componentscomponents v2 版本 ,也是 Serverless Framework 推出的最新解决方案

@serverless/components@serverless/cli 相比有很多的优势:

  • Components v1 版本是本地版本,组件部署后, 产生的状态存储在本地, 如果切换开发机,会导致状态丢失,而且使用前都需要从 npm 拉到本地,依赖本地的开发环境。

  • Components v2 版本是云端版本,解决了这些痛点, 状态在云端, 模板在云端, 我们只需要选择我们的组件,调用云服务就能轻松的完成部署工作

从源码入口开始

我们先把 @serverless/components clone 到本地, (笔者为 3.9.2版本)

package.json

这个文件中,有 2 个需要注意的地方:

1.bin

 "bin": {
    "components": "./bin/bin"
  },

这也就是说 当我们全局安装 @serverless/components 的时候,就可以直接使用components 命令了, 它的本质其实就是 sls 的 v2 版本(见上面的代码块)

假设我们的项目,完全是使用 components v2 版本构建的,那么大可直接安装此包,并且使用 components 命令来取代 serverless 命令

2.依赖

  • @serverless/platform-client
  • @serverless/platform-client-china
  • @serverless/utils
  • @serverless/utils-china

在这里插入图片描述

ps:这些包 Github 上没有,我们可以直接在 node_modules/@serverless 中发现他们

platform-client 这类包实际上就是真正核心的 Sdk

utils 则是工具类

不过有意思的是, 看上去名字长得差不多,包里面的内容却大相径庭

这里我把它分类为: 国内国外

国外:
  • 借用 online 的 web 服务来达成适配多个云厂商的功能,这块对于我们来说,就是黑箱 , 具体表现在: 对他们 *.serverless-dev.com, *.serverless-platform.com 域名的请求上,他们自己也提供了很多的特色服务.
国内:
  • china 的包,我们可得,serverless in china 就是一套 @tencent-sdk/capi 能力的封装 , 同时我们也可以在 utils-china/sdk 中发现很多的官方的 api 网关的地址 (地域:上海&广州)

Cli

在这里插入图片描述

通过之前的 bin/bin 这个入口,我们来到了 src/cli/index.js

值得注意的是 isChinaUser() 国内有自己的 loadTencentGlobalConfig 逻辑和我们自己的 commands-cn 命令 (笑~)

我们为了更加贴合国内的使用方式,就只看 commands-cn/index.js 部分代码

可以看到目前主要有一下代码:

  • run 包含 deploy remove bind role login 等等一系列命令
  • infoorg/stage/app/name 从服务端拉信息
  • init 模板项目初始化
  • dev 单实例调试模式
  • registry 注册模板地址 , 默认地址目前可以去 utils-china/sdk/serverless/index.js 找到 , 还有就是 publish , unpublish 最终都会转换为此命令。
  • help 使用帮助
  • param (目前似乎没啥用 components -h 也没有显示此命令)
  • credentials 全局凭证 , 是时候抛弃扫二维码和 .env 了 (笑~)

我们挑选 2 个典型来讲,一个是 run 一个是 dev

run

deploy

deploy 就是我们最常用的部署命令了

从代码上看,先是做了一些验证格式化 validateAndFormat

然后用 preRunSrcHook 来处理 inputs.srcobject/string 的各种情况

接着走 cache方法,压缩上传我们的代码包,先 fast-glob匹配一波,然后 adm-zip 压缩成 zip and axios.put 上传 cos

最终在 utils-china/library/sls/v20200205/sls_client.js 中发请求告诉服务端这些信息,完成部署

remove / bind role

deploy 一样,最终被转化为 library 的调用

TencentCAM.BindRole.BindRole -> forceBindQCSRole

dev

先调用是否支持调试的 doesRuntimeSupportDebug , 从代码上看,只支持 nodejs 且版本大于等于 10.15 的版本

不得不说 nodejs 在这方面就是有天然优势

支持在线调试的,就 使用 tencentDebuggger.remoteDebug ,然后创建 WshubClient 进行调试

不支持就利用 ws 创建一个 WebSocket 链接,和服务端的 log 打通,输出到本地的命令行

在这里插入图片描述

比较值得一说的就是 startTencentRemoteLogAndDebug

在线调试这里也利用 socket.io-client 连接远程服务端

在这里插入图片描述

我猜内部应该是,单实例 nodejs 通过 inspect 把调试的 ws link 暴露在外部, 通过 token 鉴权,然后通过本地的 ws client 连接上,再映射到本地的 9222 端口:

const Client = function (options) {
  const {
    Url,
    Token,
    logType = 'error',
    localPort = 9222,
    debugRemotePort = 9000,
    logRemotePort = 3332,
    timeout,
  } = options;
  // 日志类型,verbose或者info,测试阶段建议verbose
  this.logger = createLogger(logType);
  // 映射的本地端口,默认9222
  this.localPort = localPort;
  // 远端调试端口,默认9000
  this.debugRemotePort = debugRemotePort;
  // 远端日志端口,默认3222
  this.logRemotePort = logRemotePort;
  // 连接wshub的超时时间
  this.timeout = timeout;
  this.Url = Url;
  this.Token = Token;
};

总结

看了这么多的代码,我们了解了这个 命令行工具 的本质

这样,我们可以利用这一点,创建出符合我们自己需求的,CLI,Web 和 Gui 客户端

附录:

代码路径参考:

platform-client-china/src/instance.js -> deploy -> run -> api.instance.run

再到 platform-client-china/src/api.js -> run

又到了 utils-china/sdk/serverless/index.js -> runComponent

再到了 utils-china/library/sls/v20200205/sls_client.js -> RunComponent

调试方法

在 vscode 中创建自己的 workspace.code-workspace , 添加 global 级别的 serverless@serverless 路径

使用 npm -g bin / yarn global bin 输出全局 bin 路径

ps: npm 和 yarn 的全局包安装位置有可能不同,取决于当时安装serverless的工具

然后使用 vscode JavaScript Debug Terminal , 直接敲命令 components dev / npm run sls:dev 等等, 就可以直接命中断点 npm -g bin / yarn global bin 输出全局 bin 路径 ps: npm 和 yarn 的全局包安装位置有可能不同,取决于当时安装serverless的工具

然后使用 vscode JavaScript Debug Terminal , 直接敲命令 components dev / npm run sls:dev 等等, 就可以直接命中断点

© 2021 icebreaker 苏ICP备19002675号-2
version:1.2.2