Serverless 部署 Deno 應(yīng)用有那么難嗎 ???
牛年大吉
Serverless 部署 Deno 應(yīng)用有那么難嗎 ???
?Deno 是一個(gè)簡(jiǎn)單、現(xiàn)代且安全的 JavaScript 和 TypeScript 運(yùn)行時(shí)環(huán)境,其基于 V8 引擎并采用 Rust 編程語(yǔ)言構(gòu)建。Deno 自打出生就不乏話題:“Node.js 的替代品,將來(lái)可能就不需要 Node.js 了”、"Deno 并不是下一代 Node.js"、“Deno 已經(jīng)死了嗎?”……而對(duì)于 Copy 攻城獅 來(lái)說(shuō),有趣就行!目前 CloudBase Framework 支持一鍵部署 Deno 應(yīng)用,而我卻踩了不少坑,謹(jǐn)以此文紀(jì)念逝去的那些一文不值的時(shí)光!
?
CloudBase Framework
??? 騰訊云開(kāi)發(fā) ?? 云原生一體化部署工具 ?? CloudBase Framework:一鍵部署,不限框架語(yǔ)言,云端一體化開(kāi)發(fā),基于 Serverless 架構(gòu)。
?
「云開(kāi)發(fā) CloudBase 是騰訊云的熱門(mén)產(chǎn)品,云開(kāi)發(fā)應(yīng)用可以是運(yùn)行在云開(kāi)發(fā)環(huán)境的應(yīng)用,例如一個(gè)包含前后端、數(shù)據(jù)庫(kù)等能力的服務(wù),可以通過(guò)一鍵部署,直接部署在云開(kāi)發(fā)環(huán)境中,使用云開(kāi)發(fā)底層的各項(xiàng) Serverless 資源,享受彈性免運(yùn)維的優(yōu)勢(shì)。」 什么是云開(kāi)發(fā)?什么是 Serverless?Copy 攻城獅心中滿是疑問(wèn),還能不能愉快地切圖!上一次了解到云開(kāi)發(fā)還是看到“小程序·云開(kāi)發(fā)”,印象比較深刻的是云開(kāi)發(fā)提供一個(gè)云函數(shù)環(huán)境,提供云數(shù)據(jù)庫(kù)、鑒權(quán)服務(wù)等,無(wú)需自備服務(wù)器搭建后端服務(wù)。聽(tīng)過(guò)一些老師的課,得益于云開(kāi)發(fā),前端開(kāi)發(fā)尤其是小程序開(kāi)發(fā)者,一個(gè)人就能前后端甚至運(yùn)維也全干,快速上線一款彈性伸縮企業(yè)級(jí)應(yīng)用;而 「Serverles」 是「功能即服務(wù)」(Function-as-a-Service,縮寫(xiě)為 FaaS) 和 「平臺(tái)即服務(wù)」(platform as a service,縮寫(xiě):PaaS 的組合,是當(dāng)前主流的技術(shù)實(shí)現(xiàn);不過(guò),Copy 攻城獅只會(huì)跑跑 Hello World 。在 Serverless 技術(shù)體系中,我們熟知的 Node.js 扮演著舉足輕重的一環(huán),比如 Serverless Framework、Vercel等 Serverless 優(yōu)秀產(chǎn)品都離不開(kāi) Node.js 完善的生態(tài)。CloudBase Framework也是如此,因此我們能夠輕而易舉的想到 CloudBase Framework 的安裝和使用方式。
安裝 CLI 工具
npm?install?-g?@cloudbase/cli@latest?
如遇到權(quán)限問(wèn)題,請(qǐng)使用
?sudo, MacOS 上好像容易出現(xiàn)。help指令cloudbase?-h?
盲猜應(yīng)遵循了國(guó)際慣例, help help help!,當(dāng)然,驚喜發(fā)現(xiàn) cloudbase 還能簡(jiǎn)寫(xiě)為
?tcb。?Tip:?cloudbase?命令可以簡(jiǎn)寫(xiě)為?tcb
CloudBase?CLI?1.5.0
CloudBase?Framework?1.6.18-+
??命令
????login???????????[options]??????????????????登錄騰訊云賬號(hào)
????logout?????????????????????????????????????登出騰訊云賬號(hào)
????env?????????????[cmd]??????????????????????環(huán)境管理操作
????fn??????????????[cmd]??????????????????????操作函數(shù)
????framework???????[cmd]??????????????????????云開(kāi)發(fā)?Serverless?應(yīng)用框架操作
????hosting?????????[cmd]??????????????????????靜態(tài)托管資源管理操作
????new?????????????[appName]?[template]???????創(chuàng)建新的云開(kāi)發(fā)應(yīng)用
????open????????????[link]?????????????????????在瀏覽器中打開(kāi)云開(kāi)發(fā)相關(guān)連接
????storage?????????[cmd]??????????????????????云存儲(chǔ)資源管理操作
????service?????????[cmd]??????????????????????HTTP?訪問(wèn)服務(wù)管理操作
??選項(xiàng)
????--verbose??????????????????????????????????打印出內(nèi)部運(yùn)行信息
????-r,?--region???????????????????????指定環(huán)境地域
????--mode???????????????????????????????指定加載?env?文件的環(huán)境
????--config-file????????????????????????指定配置文件路徑
????-v,?--version??????????????????????????????輸出當(dāng)前版本
????-h,?--help?????????????????????????????????查看命令幫助信息
??Tips:
????–?登錄
??????$?tcb?login
????–?創(chuàng)建新的云開(kāi)發(fā)應(yīng)用
??????$?tcb?new?appName
????–?部署云函數(shù)
??????$?tcb?fn?deploy
????–?查看命令使用介紹
??????$?tcb?fn?-h登錄
看到有登錄的命令,先嘗試一下,由于我之前已經(jīng)登錄過(guò)了,通過(guò) logout 登出,再 login 。
huqi@Mac-mini deno % tcb login
CloudBase CLI 1.5.0
CloudBase Framework 1.6.18
? 您已登錄,無(wú)需再次登錄!
huqi@Mac-mini deno % tcb logout
CloudBase CLI 1.5.0
CloudBase Framework 1.6.18
? 注銷(xiāo)登錄成功!
huqi@Mac-mini deno % tcb login
CloudBase CLI 1.5.0
CloudBase Framework 1.6.18
? 獲取授權(quán)中...此時(shí),會(huì)通過(guò)默認(rèn)瀏覽器打開(kāi)一個(gè) CLI 授權(quán)的頁(yè)面,這讓我想起 Huawei DevEcho Studio 在登錄時(shí)也會(huì)調(diào)用網(wǎng)頁(yè)來(lái)進(jìn)行授權(quán)。登錄邏輯實(shí)現(xiàn)的代碼,我們可以「給 github 加 1s」 來(lái)打開(kāi)在線 VSCode 來(lái)查看:https://github1s.com/TencentCloudBase/cloudbase-cli/blob/HEAD/src/commands/account/login.ts,感興趣的小伙伴可以嘗試通讀源碼。

授權(quán)成功之后,它還會(huì)征求我的意見(jiàn)收集我的使用數(shù)據(jù),為了更好的體驗(yàn) Cloudbase ,我愿意!我愿意奉獻(xiàn)我的使用數(shù)據(jù)!
async?function?askForCollectDataConfirm()?{
????const?agree?=?await?usageStore.get('agreeCollect')
????if?(agree)?return
????//?詢問(wèn)
????const?{?confirm?}?=?await?inquirer.prompt({
????????type:?'confirm',
????????name:?'confirm',
????????message:?'是否同意 Cloudbase CLI 收集您的使用數(shù)據(jù)以改進(jìn)產(chǎn)品?',
????????default:?true
????})
????if?(confirm)?{
????????await?usageStore.set('agreeCollect',?true)
????}
????await?collectAgree(confirm)
}初始化項(xiàng)目及部署
既然前邊已經(jīng)提到可以使用簡(jiǎn)寫(xiě)
tcb來(lái)代替那串冗長(zhǎng)的字母,那肯定使用tcb來(lái)創(chuàng)建初始化項(xiàng)目。tcb?new?deno_hello?deno????#?以?deno?為模板創(chuàng)建項(xiàng)目
cd?deno_hello
tcb????????????????????????#?部署項(xiàng)目非常簡(jiǎn)單明了的命令就實(shí)現(xiàn)了一個(gè) Deno 應(yīng)用的 Serverless 部署。當(dāng)然,也正是三行命令,讓我踩了一個(gè)又一個(gè)的坑,為此還花費(fèi)了我好幾毛錢(qián)的”巨款”,錢(qián)不錢(qián)倒是無(wú)所謂,主要是磨洋工都快把我耐心耗盡了!
先來(lái)看看
tcb new deno_hello deno干了啥,大膽猜測(cè)是創(chuàng)建了deno_hello文件夾,并通過(guò)調(diào)用https://tcli.service.tcloudbase.com/download傳入 os、uin、macMd5、templateId、templateName、version 等參數(shù),獲取到 deno 模板并寫(xiě)入到deno_hello項(xiàng)目中。Cloudbase deno 模板源碼依舊可通過(guò)「給 github 加 1s」 來(lái)查看:https://github1s.com/TencentCloudBase/cloudbase-templates/tree/master/deno。如果您碰巧留意到
cloudbaserc.json,您可能會(huì)想為啥 deno 版本是 1.6.3 呢?:??{
??"version":?"2.0",
??"envId":?"{{envId}}",
??"$schema":?"https://framework-1258016615.tcloudbaseapp.com/schema/latest.json",
??"framework":?{
????"name":?"deno-app",
????"plugins":?{
??????"deno":?{
????????"use":?"@cloudbase/framework-plugin-deno",
????????"inputs":?{
??????????"dockerImage":?"debian:latest",
??????????"runtime":?"1.6.3"
????????}
??????}
????}
??}
}對(duì),這里便是我踩的坑!目前來(lái)看,在執(zhí)行
tcb之前,去掉"runtime": "1.6.3"這行使用 deno 最新的版本能避坑!
Deno 鏡像之“鍋”
很榮幸能遇到 Deno 生態(tài)建設(shè)崎嶇之路的“bug”,云里霧里,這究竟是怎樣一個(gè)故事?請(qǐng)聽(tīng) Copy 攻城獅娓娓道來(lái)。
大概半個(gè)月之前,我嘗試使用 Cloudbase 部署 deno 的 HelloWorld 應(yīng)用,拉的 Cloudbase 官方的模板直接部署,怎么都不成功,部署失敗的關(guān)鍵日志提示如下:
CloudBase CLI 1.2.7
CloudBase Framework 1.6.11
……
step 4/14 : RUN curl -fsSL https://x.deno.js.cn/install.sh | sh
---> Running in df11b9868b9a
?[91m#=#=#
curl: (22) The requested URL returned error: 403
?[0mThe command '/bin/sh -c curl -fsSL https://x.deno.js.cn/install.sh | sh' returned a non-zero code: 22
當(dāng)時(shí)看到https://x.deno.js.cn/install.sh就想到了 justjavac 大大的 Deno 鏡像,不過(guò)沒(méi)想到的居然是「jsdelivr CDN 單文件最大只支持 20M」導(dǎo)致了 Deno 1.7.0 版本在當(dāng)時(shí)的鏡像無(wú)法正常使用,因?yàn)?1.7.0 版本的 zip 包剛好超過(guò)了 20M,參見(jiàn)https://github.com/justjavac/dvm/issues/42:

這間接導(dǎo)致了 Cloudbase 中 Deno 模板使用最新的版本時(shí),通過(guò)鏡像無(wú)法下載;也造就了我這個(gè)注定是巧合的坑!
好在 justjavac 大大及時(shí)修復(fù)了這個(gè)“bug”:
fn?compose_url_to_exec(version:?&Version)?->?String?{
??if?version.major?>=?1?&&?version.minor?>=?7?{
????format!("https://dl.deno.land/release/v{}/{}",?version,?ARCHIVE_NAME)
??}?else?{
????format!(
??????"https://cdn.jsdelivr.net/gh/justjavac/deno_releases/{}/{}",
??????version,?ARCHIVE_NAME
????)
??}
}
當(dāng)然,社區(qū)也有大佬折騰出了"自給自足"的方法--向 Deno 學(xué)習(xí)優(yōu)秀的腳本管理,果真是自己動(dòng)手豐衣足食。
這就結(jié)束了?非也非也,Deno 的生態(tài)目前還不夠強(qiáng)大,同樣是版本升級(jí)帶來(lái)的問(wèn)題,這回輪到了 denon!
Denon 兼容之“鍋”
Denon 之于 Deno 如同 Nodemon 之于 Node.js ;Denon 可以監(jiān)視您的 Deno 應(yīng)用程序中的所有更改并自動(dòng)重新啟動(dòng),避免了每修改一處代碼就要手動(dòng)重啟的繁瑣;此外,對(duì)于 Deno 應(yīng)用來(lái)說(shuō),還提供了體驗(yàn)非常棒的配置。
在我們通過(guò)tcb new deno_hello deno拉取的模板中,也能看到 Denon 的身影,denon.yml:
scripts:
??lint:?deno?fmt?--check?.
??build:
????cmd:?mkdir?dist?&&?deno?bundle?--no-check?src/entry.ts?dist/entry.js
????watch:?false
??start:
????cmd:?deno?run?--no-check?dist/entry.js
????env:
??????PATHNAME:?"/deno-app"
????allow:
??????-?net
??????-?env
??????-?read
??dev:
????cmd:?deno?run?--no-check?src/entry.ts
????env:
??????PORT:?"3000"
????allow:
??????-?net
??????-?env
??????-?read
上邊這個(gè)配置文件將我們可以做的一些事安排得明明白白:代碼檢查、打包構(gòu)建、本地調(diào)試等。
那 Denon 帶來(lái)了什么困擾呢?“罪魁禍?zhǔn)住边€是因?yàn)?Deno 版本升級(jí)。當(dāng)時(shí),Deno 剛升到 1.7.0 ,使用 Denon 就會(huì)報(bào)錯(cuò)permission error,參見(jiàn):fix: permission error on latest deno:
TS2339?[ERROR]:?Property?'url'?does?not?exist?on?type?'NetPermissionDescriptor'.
??`--allow-${pd.name}=${pd.url}`
???????????????????????????????????????????~~~
at?https://deno.land/[email protected]/permissions/mod.ts:18:44
當(dāng)時(shí)普遍認(rèn)為 Deno 1.6.3 是比較穩(wěn)定的版本,至少也不會(huì)導(dǎo)致 Denon 無(wú)法正常使用,我猜大概也是因?yàn)檫@個(gè)原因,我們?cè)谏衔闹刑岬?Cloudbase 中 deno 模板目前也是使用的 1.6.3。
出現(xiàn)類(lèi)似的“鍋”,如果您依舊想使用最新版本,那就只能等等兼容問(wèn)題被處理,或者您親自動(dòng)手處理兼容問(wèn)題。
再回過(guò)頭來(lái)看看這個(gè)兼容問(wèn)題是如何處理的?看上去只是改了一個(gè)版本號(hào),但究竟為何要這樣改,估計(jì)只能深入 Deno 源碼學(xué)習(xí)才能一探究竟了。
牛刀小試
既然所有的問(wèn)題都如愿以償?shù)乇簧鐓^(qū)大佬們解決了,那接下來(lái),我還是想試試 Cloudbase 和 Deno 這兩把“牛刀”,完成我琢磨了很久的一個(gè) Hello World,姑且稱為「一條熱搜」。主要是不想浪費(fèi)之前通過(guò) Deno 獲取的每日熱搜數(shù)據(jù),加上想體驗(yàn)一下 Cloudbase 的一鍵部署功能,難得 Cloudbase 支持 Deno 插件。
按照劇情,上文中初始化?Deno 項(xiàng)目之后,直接輸出 tcb 這三個(gè)字母就能進(jìn)行部署,「請(qǐng)盡量本地調(diào)試好應(yīng)用再部署,每次部署都會(huì)」,當(dāng)然,截止文章發(fā)布前,建議去到指定 Deno 版本的這行配置:
-?"runtime":?"1.6.3"
簡(jiǎn)單修改了一下 HelloWorld 的代碼,讓它變成一個(gè)我想要的「一條熱搜」,數(shù)據(jù)基于「trending-in-one」,我粗暴地在 controller 中獲取熱搜數(shù)據(jù):
????const?response?=?await?fetch(`https://cdn.jsdelivr.net/gh/hu-qi/trending-in-one/raw/toutiao-search/${formatTime(new?Date(),{template:'{{YYYY}}-{{MM}}-{{DD}}'})}.json`)
????const?responseJson?=?await?response.json()
????const?index?=?Math.floor(Math.random()?*?responseJson.length);
????const?pathname?=?Deno.env.get("PATHNAME")?||?'';
????ctx.response.body?=?await?renderFile(`${Deno.cwd()}/views/home.ejs`,?{
??????title:?'一條熱搜',
??????text:?responseJson[index],
??????pathname,
????});
來(lái)看看部署之后慘不忍睹的效果:

在線預(yù)覽地址:http://deno-demo-3ghgaf7pa8d97b90-1253880795.ap-shanghai.app.tcloudbase.com/(PS:如果無(wú)法訪問(wèn),那一定是我欠下巨款跑路了,您可以自行一鍵部署)
一鍵部署:

最后嘮嗑一下 Cloudbase 的一鍵部署,「一鍵部署按鈕可以讓公開(kāi)的 Git 項(xiàng)目一鍵部署到云開(kāi)發(fā) CloudBase 上,大大簡(jiǎn)化用戶部署的門(mén)檻,便用戶快速使用和體驗(yàn)應(yīng)用。一鍵部署功能支持 Github,Gitlab,Coding,Gitee 等 Git 倉(cāng)庫(kù)地址。」 簡(jiǎn)直是 Copy 攻城獅的福音,復(fù)制粘貼都不用了,一鍵部署!(PS: 其實(shí)還是需要手動(dòng)進(jìn)行配置)
一鍵部署按鈕的生成可以訪問(wèn):https://docs.cloudbase.net/framework/deploy-button.html,只需填入倉(cāng)庫(kù)地址、目錄和分支,這點(diǎn)和 Vercel 部署也有些類(lèi)同:

總體體驗(yàn)還是不錯(cuò)的,不過(guò)最后還是遇到了一個(gè)訪問(wèn)地址的坑,還沒(méi)來(lái)得及填,不過(guò)影響不大。大概是一鍵部署成功之后,訪問(wèn)地址*.ap-shanghai.app.tcloudbase.com/deno-app在瀏覽器中打開(kāi)時(shí)變成了文件下載,而實(shí)際服務(wù)的地址是沒(méi)有deno-app這個(gè)服務(wù)名稱路徑的,大概率是我的配置有點(diǎn)偏差,棄坑棄坑!
小結(jié)
總得來(lái)說(shuō),隨著 Deno 生態(tài)的不斷完善,Serverless 部署 Deno 應(yīng)用變得越來(lái)越簡(jiǎn)單。借助云開(kāi)發(fā) Cloudbase,您無(wú)需關(guān)注 Deno 的安裝實(shí)現(xiàn)、服務(wù)的運(yùn)維等等,還能以最低的成本運(yùn)行 Deno 應(yīng)用。希望我的踩坑能夠給您啟發(fā),請(qǐng)多多指教,感謝!
