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 方法,来包装一些异步函数。
{
"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
→ 编译后结果
三、成果 简单展示下代码线上运行后的结果。