前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >云函数 + TypeScript + Node.js 最佳实践探索

云函数 + TypeScript + Node.js 最佳实践探索

作者头像
腾讯云serverless团队
发布2019-08-09 11:40:17
2.9K0
发布2019-08-09 11:40:17
举报
文章被收录于专栏:Tencent Serverless 官方专栏

目的

最近 Serverless 愈来愈火,我刚好在培训,比较有时间去尝试一些新东西,所以趁这个时候去使用下 Serverless,尝试使用 Typescript 和 nodejs 开发,部署在腾讯云 SCF 上的一个小工具,探讨下 Typescript+ Node.js + SCF 的最好实践模式,并同时抛钻引玉,希望有同学提供更好的方案。


项目介绍

一、想法

本人有时候会追剧,但是剧集更新时,我一般都是不知道的。只有空闲的时候,才会特地去查看它们有没有更新。如果有这么一个工具,能够在剧集更新的时候,主动告诉我,那么我就不用时不时去查询,对我来说就会方便很多。

在我没有接触到 Serverless 之前,我的想法是这样的 —— 写这样的程序并不难,但是我得买个机器部署啊?如果有问题不能及时发现,还得上机器查日志,或者自己去控制程序定时爬取的逻辑等等。

总的来说就是,实现与维护一个这样的程序的成本远大于了其带给我的便利,让我有想法却懒于行动。

但是有了 Serverless 后,以上问题将不再是问题。例如部署难题,使用 Serverless 就是使用云供应商提供的开发者工具,用它创建函数,打包上传代码即部署成功;又例如定时爬取逻辑,使用其提供的定时触发器能力即可。这让我能更专注于代码实现。

在此,我不会很官方地去讲 Serverless 的概念以及好处,仅仅是从一个开发者的角度来阐述我的想法。

二、实践

1、流程图

程序的整个流程图如下图所示,逻辑很简单,这个项目的目的不在于实现一个多厉害的功能,而在于 Typescript + Node.js + SCF 的实践方式的探索。

2、开发

开发能在 SCF 运行的Node.js 程序的其实与传统的开发Node.js 程序在语言编写上并没有太大区别。比较明显的不同在于,我们开发时得有一个入口的函数,比如像这样:

更具体的入门文档,可以看此处[1],跟着文档一步步学习编写一个简单的函数。接下来回归正题。

a. 环境搭建

首先为了方便开发,建议安装腾讯云 SCF 提供的命令行工具或者 vscode 插件。但是这里我开发的时候 vscode 插件还没发布,所以这里主要使用命令行工具,命令行工具的安装与使用的文档,具体可以看此处[2]。

安装好后,使用 scf init(具体参数得去看文档填写,这个提个建议,scf init提供交互式操作,采取问答的模式去创建)创建一个项目、项目文件很简单,一共就四个文件,前三个,应该不多做介绍。第四个文件 template.yaml 称为模板文件,简单来说是描述这个函数的文件,比如函数的环境变量,触发器类型等等,具体还是前往文档[3]处查看吧。

接下来,就是正常配置 tsconfig.json,如果没有安装 typescript 的同学请去官网安装,然后 tsc --init 就可以快速生成一个 tsconfig.json,然后根据自己的需求配置即可。

然后,就是编写 npm scripts。

主要就三个操作,build,dev,deploy。

可以使用 npm scripts 把 typescript 的编译和 SCF CLI 的本地调试,打包和部署串联在一起,使需要敲打的命令简洁和语义化

最后,将本地仓库与远程仓库关联起来。(这里提一个优化:有一种场景是用户已经创建了一个 git 仓库,现在需要将仓库里的代码写成 SCF 模式下的代码,并配合 SCF CLI 使用,目前 SCF CLI 只支持 init 一个完整的项目,如果支持在一个已有项目中快速生成调试和部署的 yaml,对开发者来说是一个比较方便的功能

b. 编码

我的主要逻辑代码分为上面的文件。

  • index,没什么好说的,就是一个入口文件,负责组合其余模块的逻辑。
  • config 以及 config_extra,config_extra 文件放了我的隐私配置,例如 redis 的 host,port 和密码以及邮件服务的授权码等,这些配置通过配合 .gitignore 是不会提交到远程 git 仓库,而 config 文件 则是引入 config_extra 文件中的配置,并与一些通用配置进行 merge,然后输出到各个模块。(注:此处也可以好好利用scf提供的环境变量功能,很适合这种场景,具体文档[4])
  • config_extra_demo,告诉别的开发者,config_extra 文件应该如何编写
  • mailer,封装邮件服务的初始化以及发送邮件方法
  • redis,封装 redis 的连接以及同步 set 以及 get 方法
  • task,暂时简单封装了下初始化以及执行的通用逻辑。但日后该工具扩展,此处仍得考虑如何抽象以及通用化。
  • util,封装了一些公用方法,例如封装了 retry 方法,来包装一些异步函数。

上面简单介绍下主要逻辑代码的文件,具体的实现,有兴趣可以移步到 Github 地址[5] 查看

3、调试

上面也有提到我编写的 npm scripts 里有 npm run dev 的一条。本人开发这个项目时,调试都执行 npm run dev 来进行调试。这里提一下,测试环境一般是需要和正式环境隔离的。所以可以新建一个 env.json 文件,里面填写

代码语言:javascript
复制
  {    "NODE_ENV": development  }

并将 npm script 中的 dev 命令改成 npm run build && scf local generate-event timer timeup | scf native invoke --template template.yaml --env-vars env.json

然后在配置文件中根据 process.env.NODE_ENV 变量来判断是测试环境还是正式环境,并填写对应环境依赖的服务的配置即可。

4、部署

上面讲了这么多,其实都不是我最想表达的,因为我并没有在上面遇到一些很棘手的问题。而在部署的时候,我才发现在使用 typescript 时,无法在腾讯云 SCF 目前的部署要求以及项目的文件目录管理中做到完美的配合

后面和同事讨论后,还是有不错的方法是达到两者的平衡。下面是我的多次尝试的一个过程

如果不使用 typescript,仅使用 js 编写 nodejs 程序,则不需要编译的过程,部署函数时,只需要打包然后部署即可;但是使用 typescript 后,则多了一步将 ts 代码编译成 js 代码的步骤。为了管理好项目的文件目录,我倾向于 ts 和 js 文件分别存放在不同的文件夹,例如,src 文件夹存放 ts 文件,dist 则是编译后得到的 js 文件。我一开始的文件目录便是如此。

第一次尝试

→ 文件目录:

→ tsconfig.json 指定编译 src 文件夹下的 ts 文件,输出到 dist 文件夹

→ template.yaml CodeUri 指向 dist 文件夹

根据上面的配置,在本地调试是可以的。但是当部署到云上,测试是失败的。如果大家熟练的话可以立刻发现问题所在,打包没有把 node_modules 打包进去。主要逻辑代码依赖的第三方库全都找不到,测试当然失败了。

第二次尝试

根据第一次尝试,我使用 npm scripts 的 pre 钩子,在执行部署前,编辑 ts 代码,同时把 node_modules 拷贝到 dist 文件夹,然后再打包部署解决了这个问题。

→ package.json

→ copy_node_modules.js

→ dist 文件夹下的文件

虽然这样做可以运行了,在本地文件目录管理合理,但是提交到云上的代码是编译后的,基本没啥可读性,就是一坨能运行的东西,项目代码也不完整。所以个人认为,最完美的是本地开发的项目代码和交到云上的项目代码是一致的,不需要通过额外的脚本去阉割。虽然目前腾讯云 SCF 控制台的 webIDE 还只是能看入口文件,不过之后会接入 Cloud Studio,起码可以看到整个代码文件夹的每个文件,说不定以后就支持在线支持 typescript 编译(虽然不知道可不可能)。所以本人开始了第三次尝试。

第三次尝试

我有一个想法:template.yaml 中指定的 Handler,即入口函数,从 index.main_handler 写成 文件夹 /index.main_handler,即入口函数可以在某个文件夹里

我在 template.yaml 处的 Handler 写成 dist/index.main_handler,CodeUri 写成了根目录,这样就可以打包整个文件夹,然后指定 Handler 为 dist 文件夹的 index 文件的 main_handler 函数。

→ template.yaml

本地调试时,是成功的!

但是在部署的时候,

额,好吧,我觉得是这个方案是不行的了,因为不符合 SCF 的要求,通过不了校验。

第四次尝试

这是我第四次尝试。但是不是最完美的,在文件管理退了一步,允许 ts 和编译后的 js 放在一起。这样能做到把整个项目都打包上去,而且可运行,但是 ts 和 js 放在一起,文件管理不太合理。修改的地方如下:

index.ts 文件从 src 文件夹移动到根目录

→ tsconfig.json

编辑根目录下的 index.ts 和 src 文件夹下的 ts 文件,剔除 node_modules,输出到根目录

→ template.yaml

CodeUri 改成根目录,Handler 改成 index.main_handler,即跟 CLI 生成的一样

编译后结果

最后部署到云上 SCF,是可以运行的,而且是把整个项目都打包了上去,日后腾讯云 SCF 接入了 Cloud Studio,WebIDE 看到的文件架构和本地看到的文件架构是一致的。

第五次尝试

兜兜转转,有时候问题解决很简单。和组内同事讨论后,一位大佬同事点出 —— 可不可以在根目录写一个 index 文件,然后调用编译后的 index 文件的入口方法?

一语惊醒梦中人!是的,一开始就没注意到,还可以这样解决,思维一直在一个圈子里绕来绕去,没有跳出来。这样做的成本很低,而且能达到了我之前说到的理想状态:

本地开发的项目代码和交到云上的项目代码是一致的,不需要通过额外的脚本去阉割

实施方法即是,把 typescript 文件放在 src 文件夹下,编辑后的 js 文件放在 dist 文件夹下,在根目录编写一个 index.js 文件,文件里的 main_hanlder 方法调用编译后的 index 文件的入口函数,下面是一些核心代码。

→ index.js

→ tsconfig.json

→ template.json

→ 编译后结果

三、成果

简单展示下代码线上运行后的结果。


总结

上面说了这么多,这里给一个总结就是 —— 虽然腾讯云 SCF 没有原生支持 TypeScript,但是经过一些方法还是可以做到两者的完美配合。

首先本地开发是没啥问题的,上面提到的尝试,都是为了能够在本地调试成功的同时可以部署到云上。

主要是部署的问题,其中可行的三个尝试:

第一个 是通过一些额外的方法去适配,但是做不到云上的项目和实际的项目的一致,如第二次尝试。

第二个 是文件管理上退了一步,不做到极致的分明,如第四次尝试。

第三个 是在根目录写一个 index.js 文件,调用具有真正逻辑的入口函数,做个转发,如第五次尝试,也就是本人认为目前最好的实践方式。

最后,以上的五个尝试,是本人开发的时候的想法与实践,也许不太正确,有误欢迎大家来批评。如果大家有更好的方法,欢迎讨论。五次尝试的源码都在 Github 地址[6],前四次尝试均有对应分支,master 分支为第五次尝试。


References

[1]https://cloud.tencent.com/product/scf/getting-started

[2]https://cloud.tencent.com/document/product/583/33445 [3]https://cloud.tencent.com/document/product/583/33454 [4]https://cloud.tencent.com/document/product/583/30228 [5]Github 地址: https://github.com/Juliiii/scf-crawler [6]Github 仓库: https://github.com/Juliiii/scf-crawler


想了解更多?

Hello Serverless 技术沙龙「深圳站」来了!

这场沙龙将围绕腾讯云 Serverless 2.0 的运行原理、应用场景,腾讯云云函数的架构设计、冷启动优化、本地开发调试,以及 Serverless 在乐凯撒新餐饮服务上的应用实践,从 0 到 1 介绍 Serverless 2.0,与开发者一同交流未来的无服务器形态。

活动时间:2019 年 8 月 17 日 13:00-17:30

活动地点:深圳市南山区深南大道 10000 号腾讯大厦 2F 多功能厅

点击文末 阅读原文 即可报名参会

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-08-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ServerlessCloudNative 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云函数
云函数(Serverless Cloud Function,SCF)是腾讯云为企业和开发者们提供的无服务器执行环境,帮助您在无需购买和管理服务器的情况下运行代码。您只需使用平台支持的语言编写核心代码并设置代码运行的条件,即可在腾讯云基础设施上弹性、安全地运行代码。云函数是实时文件处理和数据处理等场景下理想的计算平台。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档