云端一体化部署工具 CloudBase Framework (简称 CBF)自开源发布以来迭代迅速,不仅支持 Vue、React 等前端框架,也支持 Nuxt 等 SSR 框架,基于 Node 开发的应用如 Express、Koa 等也可以一键托管。除此之外,借助底层 Serverless 云应用的能力,也可以部署其他后端的应用(PHP、Java、Go 等),值得一提的是可以部署 Dart Server,可以配合 Flutter 实现 Dart 语言的云端一体化,这也是国内云厂商对 Dart 语言和生态的一大补充。

现在,CloudBase Framework 已支持部署Deno,可能是首个支持部署Deno的前后端一体化部署工具!下面就来介绍下 Deno 插件的开发流程。

Deno是基于V8引擎和Rust语言所创建的JavaScriptTypeScript运行环境,由Node.js的原始开发者Ryan Dahl所创造,目前 github star 66.7k+。

来自 justjavac 大神的点赞

开发准备

云开控制台:https://console.cloud.tencent.com/tcb

当 CloudBase Framework 正式推出后,一直觉得 Deno 和云开发应该是绝配,所以尝试为其贡献了 Deno 插件与模板,并调研感受了下 Deno 开发过程。

相关产出:

开始着手 deno 插件开发时,CloudBase Framework 插件开发的文档暂缺,不过好在其他插件代码清晰易懂,可以参考其他插件进行开发。

考虑到 deno 运行状态,应该就是需要打通容器部署环节,于是根据 CloudBase Framework 作者建议,参考了 framework-plugin-nodeframework-plugin-dart 两款插件的代码来进行开发。

整个 CloudBase Framework deno 插件开发,主要需要编写代码的文件就 3 个:

调研基本示例

由于需要进行容器部署,所以在 dockerhub 找了个 docker image aredwood/deno 作为参考镜像进行改造。来编写 CloudBase Framework 插件所需 的 Dockerfile 。

为方便验证 Dockerfile 和 deno 应用如何整合,构建了一个简单项目来验证镜像构建流程:deno-docker

deno 生态有一个类似 node koa 的应用框架 oak 直接使用它的官方示例,存为一个 entry.ts ,很快就完成了本地示例的搭建。执行示例也非常简单 deno run entry.ts

插件开发

接下来考虑如何部署的问题,开始开发 CloudBase Framework deno 插件,src/index.ts 主要需要提供一个插件类给 CloudBase Framework 命令行组件使用。这个类需要继承自 @cloudbase/framework-core 的 Plugin。

参考其他插件写法,Plugin 是抽象类,需要自行实现抽象类的各个方法。其中在 build 方法中,需要构建中间产物,主要是编译过后的 Dockerfile 和需要包装到镜像的文件,然后通过 framework-plugin-container 提供 docker container 构建产物。

import { plugin as ContainerPlugin } from '@cloudbase/framework-plugin-container';
/*** code:other ***/
class DenoPlugin extends Plugin {
/*** code: 初始化处理 ***/
async build() {
// 构建 deno 中间产物
this.buildOutput = await this.denoBuilder.build(
this.resolvedInputs.projectPath || '.',
{ /*** code: 给 buider 提供选项 ***/ }
); // 提供 containerPlugin 对象
const container = this.buildOutput.containers[0];
this.containerPlugin = new ContainerPlugin(
'container',
this.api,
resolveInputs(
{ localAbsolutePath: container.source },
this.resolvedInputs
)
); // 构建 container 最终产物
await this.containerPlugin.build();
}
/*** code: other ***/
}

而 deploy 方法看来主要是在部署之后,提供最终部署结果的日志呈现。参考其他 2 个插件,大部分代码改动主要用来做配置项的处理和日志的区别,整体与其他插件相比,改动不大。

class DenoPlugin extends Plugin {
async deploy() {
/*** code: 日志处理 ***/
// 实际部署能力调用
await this.containerPlugin.deploy();
await this.denoBuilder.clean();
/*** code: 日志处理 ***/
}
}

src/builder.ts 中,主要扩展 Builder 类,提供中间产物构建方法。其中 build 方法,参考其他插件,给出容器构建所需的固定返回即可。

import { Builder } from '@cloudbase/framework-core';
/*** code: other ***/
export class DenoBuilder extends Builder {
/*** code: 初始化 ***/
async build(localDir: string, options: BuilderBuildOptions) {
/*** code: 选项处理,路径处理 ***/
// 生成中间产物需要调用的方法
await Promise.all([
this.generator.generate(
path.join(__dirname, '../assets'),
appDir,
spec
),
fs.copy(path.join(projectDir, localDir), appDir),
]); // 对于容器部署,是固定的返回
return {
containers: [
{
name: containerName,
options: {},
source: appDir,
},
],
routes: [
{
path: options.path,
targetType: 'container',
target: containerName,
},
],
};
}
}

this.generator.generate 方法调用时,Dockerfile 会作为 ejs 模板被进行编译,传递的选项将会作为编译参数。结合这个能力,可以实现 docker image 的精细配置。

本地部署调试

调试 CloudBase Framework deno 插件时,需参考 cloudebase-framework 贡献指南 提供的本地调试流程。

本地需要部署的代码,需要提供一个 cloudbaserc.json 作为部署配置。如果是开发模板,需要配置属性 "envId": "{{envId}}"cloudbaserc.json 参考 CloudBase Framework 配置文档 来配置属性。其中 inputs 属性将作为参数传递给插件。

以我个人模板调试为例,插件编写完毕后,需要在插件目录执行 npm run build 编译插件代码。然后在 cloudbase-framework 根目录执行 npm run link 实现插件的本地指向。最后在模板目录执行 CLOUDBASE_FX_ENV=dev cloudbase framework:deploy -e test-1gxe3u9377a09734 来进行部署。

test-1gxe3u9377a09734 为我个人的 envId,将会替换 cloudbaserc.json 中的 "{{envId}}" 部分。

deno 开发体验

开发

deno 可以直接运行 typescript,示例代码跑在开发模式,报错时可以直接看到清晰的调用栈,这弥补了 typescript 在 node 开发中的弊端。好感度 +1 !

部署

初次部署时经常碰到部署失败,经过沟通与调试,发现问题主要出在 docker image 编译和 app 应用执行环节中,由于网络环境问题,部分远程文件未能成功加载或者缓存。

再次审视 deno 项目介绍与说明,发现最佳实践是进行本地打包(或者 ci 打包)后提供无依赖的入口文件。

deno 提供了 deno bundle 命令,可以将代码打包为一个 js 文件来执行。然后找到 denon 这个工具,直接解决了开发部署配置问题,其类似 nodemon 。舒服的是,包括 deno 应用的执行权限,环境变量,都可以在它的配置文件中配置。所以直接修改了 CloudBase Framework deno 插件,使用 denon 来提供启动应用能力。

使用先打包,后部署的方案后,云开发部署 deno 应用的成功率大幅上升。

依赖

值得一提的是,虽然示例应用简陋,但是依然能感受到 deno 打包执行流畅易用。好感度 +1!

脱离了 node_modules 这层设计,deno 内置的打包部署这方面的体验远超 node 开发。本地应用开发设计时,推荐使用固定版本的文件引用方式,这样可以避免依赖更新导致的应用 bug。

/* @see https://github.com/oakserver/oak/blob/main/application.ts */
import { reset } from "https://deno.land/std@0.62.0/fmt/colors.ts";

模板引擎

在使用 dejs 模板时,发现示例中的 cwd() 不能使用。

(async () => {
const output = await renderFile(`${cwd()}/views/main.ejs`);
await copy(output, stdout);
})();

需要改为 Deno.cwd()

(async () => {
const output = await renderFile(`${Deno.cwd()}/views/main.ejs`);
await copy(output, stdout);
})();

而嵌套模板代码直接报错,只提示文件未找到,却并未给出更详细提示。

<%- await include('views/header.ejs') %>
<h1>hello, world!</h1>
<%- await include('views/footer.ejs') %>

反复调试后发现,需改为:

<%- await include(`${Deno.cwd()}/views/header.ejs`) %>
<h1>hello, world!</h1>
<%- await include(`${Deno.cwd()}/views/footer.ejs`) %>

IO

在 deno 应用中,使用 fetch 方法获取远程资源时,该方法与浏览器规范实现一致,使用起来莫名亲切。由于 deno 默认直接读取了环境变量的 http_proxy,node 开发中碰到的内网代理配置问题,在 deno 开发中也不再存在。好感度 +1 !

总结

联系到 Deno 的愿景是设计一款服务端运行的浏览器,忽然有了一些大胆的想法,想来在 SSR、测试、Web资源编辑与创建方面,Deno 未来可能会有一些独到的优势。

总体来说,即便 Deno 并非 Node 的替代者,依靠其顺滑的开发部署体验,未来极有可能分走 Node 相当一部分使用场景。而这个项目在 github 上的 star 数量,与社区参与人数的快速上涨,也证明其具有相当大的潜力。

Deno is coming!

参与贡献

  • 积极参与 Issue 的讨论,如答疑解惑、提供想法或报告无法解决的错误;
  • 撰写和改进项目的文档;
  • 提交补丁优化代码;
  • 认领待办任务中的事项。

CloudBase Framework丨第一个 Deno 部署工具是如何打造的?的更多相关文章

  1. Openstack部署工具

    Openstack发展很猛,很多朋友都很认同,2013年,会很好的解决OpenStack部署的问题,让安装,配置变得更加简单易用. 很多公司都投入人力去做这个,新浪也计划做一个Openstack的is ...

  2. OpenStack部署工具总结

    目前感觉比较简单直观的部署工具有RDO.devstack.Fuel等: 1. RDO https://openstack.redhat.com/Quickstart REDHAT出品,支持Redhat ...

  3. Capistrano初探--Ruby快速部署工具

    1.Capistrano介绍 是什么?---一种部署工具.(部署就是在生产服务器上安装应用程序,或是更新最新版本:web服务器的启动重启与停止:使网站进入维护状态或将其恢复为常态) 在进行 Rails ...

  4. Capsule:开源的 JVM 应用部署工具

    [编者按]本文作者 Ron Pressler 是 Parallel Universe 公司的创始人,拥有着丰富的高性能开发经验.通过这篇文章,Ron 向大家详细介绍了全新的开源 JVM 部署工具--C ...

  5. seajs打包部署工具spm的使用总结

    相信使用seajs的好处大家都是知道的,接触seajs好像是在半年前,当时还不知道页面阻塞问题,这里不带多余的话了. seajs实现了模块化的开发,一个网站如果分了很多很多模块的话,等开发完成了,发现 ...

  6. NodeJS热部署工具 — supervisor

    NodeJS热部署工具 — supervisor 大家都在开发nodejs应用时遇到过这样的情况,修改nodejs应用中的程序文件后必须重启nodejs才能重新加载应用代码.这是因为nodejs加载过 ...

  7. 使用ASP.NET Core MVC 和 Entity Framework Core 开发一个CRUD(增删改查)的应用程序

    使用ASP.NET Core MVC 和 Entity Framework Core 开发一个CRUD(增删改查)的应用程序 不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻 ...

  8. 超级简便的容器化部署工具(使用 ASP.NET Core 演示)

    Docker 改变了我们部署网站的方式,从原先的手动编译打包上传,到现在的构建镜像然后推送部署,让我们在配置环境上所花费的时间大大减少了.不仅如此,通过一系列相关的工具配合,可以很轻松的实现 CI.C ...

  9. 简化kubernetes应用部署工具之Helm应用部署

    介绍 微服务和容器化给复杂应用部署与管理带来了极大的挑战.Helm是目前Kubernetes服务编排领域的唯一开源子项目,做为Kubernetes应用的一个包管理工具,可理解为Kubernetes的a ...

随机推荐

  1. PHP fileowner() 函数

    定义和用法 fileowner() 函数返回指定文件的用户 ID(所有者). 如果成功,该函数返回用户 ID.如果失败,则返回 FALSE. 语法 fileowner(filename) 参数 描述 ...

  2. Dynmaics 365 scale group

    关于scale Groups的概念,在看Dynamics crm online的时候,一直不理解缩放组scale group的概念,后来查到GP也在用这个概念,想想不就是动态扩展嘛,马上顿悟了,原来如 ...

  3. 关于tf.cond函数中“正确”与“错误”函数中的普通python语句始终执行的问题

    import tensorflow as tf import numpy as np x = tf.constant(2) y = tf.constant(3) global mask0 mask0 ...

  4. Redis好文章推荐

    文章来源:掘金   作者:敖丙 Redis-避免缓存穿透的利器之BloomFilter <我们一起进大厂>系列- Redis基础 <我们一起进大厂>系列-缓存雪崩.击穿.穿透 ...

  5. Spring 基于注解的 IOC 配置

    创建 spring 的 的 xml 配置 文件 <context:component-scan base-package="com.itheim"/> 指定创建容器时要 ...

  6. 2020牛客暑期多校训练营(第八场)K-Kabaleo Lite题解

    K-Kabaleo Lite 题目大意: 给出每种菜品的利润以及碟数,要求我们给每个客人至少一碟菜,要求从1号菜品开始给,给的菜品的号码是连续的,每个客人同号码的菜都只能给一碟.求能招待客人的最大数量 ...

  7. C#算法设计排序篇之11-二叉树排序(附带动画演示程序)

    二叉树排序(Binary Tree Sort) 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/695 访问. 二叉树排序 ...

  8. 用WindowsAPI实现文件复制功能

    用WindowsAPI实现文件复制功能 1. c代码 注释也在里面 文件名为 copyfile.c 运行出来的exe为 copyfile.exe #include <windows.h> ...

  9. elementUI 表单清空问题

    在使用表单的清空方法时,我们需要注意几个问题: 1.我们需要为每个form-item加上prop属性,要不然无法清空(大部分的问题就是出在这) 2.resetFields()方法是重置表单,重置为默认 ...

  10. 看完就能掌握的PHP核心技术 - ​​​​​​​​面向对象

    继承和多态 类的组合与继承 假设我们有两个类,一个 person,另外一个是 family:在 family 类中我们创建 person 类中的对象,并且我们把这个对象视为 family 类的一个属性 ...