別再用 bash 寫前端自動化腳本了!

導讀

Vladimir[1] 發現自己一直討厭 bash 編寫的自動化流程腳本,並且在機緣巧合下發現同事們都有類似的想法,因此他分享了他認爲 JavaScript 編寫自動化腳本的優勢,看看能不能說服大家去共建更好的生態。

與之相關的是,谷歌的 zx[2] 項目正是爲此而生,並且在去年的 JavaScript 工具流行趨勢調查中獲得了第一名。

今年最受歡迎的項目是谷歌的 zx,可在 JavaScript 或 TypeScript 中編寫簡單的命令行腳本。

zx 支持在代碼中嵌入任何 bash 表達式(ls、cat、git 等等),並藉助 JavaScript 模板字面量獲得結果。

zx 涵蓋了多個軟件包提供的功能:

node-fetch:使用與瀏覽器中相同的 API 發出 HTTP 請求

fs-extra:運行文件系統

Globby:匹配給定用戶友好模式的文件名

接下來是他所分享的一些看法:

我在日常的工作中也體會到,大家彷彿有共識一般默認寫自動化構建腳本時要去用 bash,希望這篇文章可以帶給大夥一些不一樣的思考,也許 JavaScript 來寫會更好?

先看看幾個可能的優點:

如果你時間不多的話,不妨看看快速比較表格:

這是你團隊的主要語言

相比於 bash,大多數前端團隊都更熟悉 JS。Node 是具有特殊的 API,但總的來說它有函數一等公民,循環和 promise 等熟悉特性。bash?我搞了幾年下來還是不確定它是咋工作的 —— 語法很熟悉,但在意想不到的地方又不一樣,大多數變量是字符串,到底存在模塊不?如果我錯了,也不要糾正我,我不關心了。我一直只是用的時候去谷歌……

每個體面的程序員都需要學習 bash?這是病態的!如果你的後端同事需要在你的項目中做一些緊急改動,那他應該學習一些 JS。C 語言風格的語法讓任何人都能大概瞭解代碼的意圖。當然從這個角度來看 bash 也差不多,但 JS 在這裏起碼並不比它差。

在 JS 優先的團隊中使用 JS 進行自動化腳本的編寫,是最合乎邏輯的選擇。

runtime 大概率已經安裝了

你的 bash 腳本即使成功運行了,麻煩也沒有結束,因爲它通常會在另一臺機器上失敗(說你呢,Alpine Docker 容器……)。各種 shells[3](SH,ASH,BASH,ZSH)都略有不同,在不同的 Linux 發行版上也不完全通用。你當然可以手動挑選必要的包,或者重新手寫邏輯,但是真的很浪費時間。

用 Node 的話,丟失的 runtimes 的問題非常少見 - CI 機器無論如何都可以運行 npm / yarn,這些和 node 綁在一起。此外,一旦 node 程序編寫完成,通常每臺計算機上都可以運行。

開箱即用的跨平臺特性

這就引出了下一點 —— node 是一個跨平臺的運行時,在 linux、mac 和 windows 上運行良好。對,MacOS 是兼容 POSIX 的,但是許多命令在選項和輸出格式上仍然有細微的差異。現在,你需要 Windows 支持嗎?雖然大多數前端開發人員都使用 Mac,而且存在 Win 的 bash 端口。但是,免費支持開箱即用總是很好的:

Node 團隊花了大量時間抽象出操作系統之間的差異。忽視這一點,而去堅持使用 bash,會適得其反。

直接訪問其他 JS 工具

前端工作流(webpack/parcel/babel/PostSS)中的大多數工具都開放了 node APIs。甚至像 esbuild 和 swc 這樣的非 JS 工具也提供 node bindings。如果你的自動化編排在 node 上運行,那麼訪問這些 API 就很簡單:只需導入包並調用函數。

在 bash 中,有兩個麻煩的選項可以與基於 node 的工具集成:

另外一個好處是,由於許多工具的 CLI 位於單獨的軟件包中(如 @babel/CLI),如果直接使用 node API,可以跳過安裝,從而節省一點 npm i 時間。

體面的進程間通信

node 作爲自動化運行時的一個很棒的方面是它的 IPC 能力。有時候你更喜歡通過 CLI 而不是 node API 使用其他工具。也可以 —— 在 node 中,這可以通過 child_process[4] 異步且跨平臺地完成!你甚至可以在不同的進程之間使用管道輸出,就像 shell 的管道操作符 |。雖然內置的 Streamchild_process API 可能不太符合人體工程學,但你可以根據自己的口味使用包裝器——我比較喜歡execa

bash 也擅長於流程管理,但對我來說,有太多的可能性了——參考這個 stackoverflow 問題:裏面提到有五種不同的並行運行命令的方式 [5],如果你不知道自己在做什麼,這就很容易讓你搬起石頭砸自己的腳。

龐大的生態系統

npm 爲各種各樣的問題提供了很好的解決方案。我最喜歡的是管理子進程的 execa[6]、處理 CLI 選項的 yargs[7] 和輸出樣式的 chalk[8]。

是的,也存在類似的許多命令行工具,但必須使用特定於操作系統的軟件包管理器(apt?brew?apk?)安裝它們。大夥真的不想處理這種問題。此外,您安裝的任何 CLI 軟件包也可以通過 spawn/exec 在 node 中使用。


因此,以下是我選擇 JS/node 來管理複雜自動化工作流的主要原因:

當然也有理由避免使用 node(比如缺少關於自動化用例的教程,對於不熟悉 node 的人來說,異步的複雜性),但我仍然相信它是 JS 項目中構建自動化流程最可靠的選擇。

Vladimir

https://thoughtspile.github.io/2022/02/14/js-automation

參考資料

[1]

Vladimir: https://twitter.com/thoughtspile

[2]

zx: https://github.com/google/zx

[3]

各種 shells: https://en.wikipedia.org/wiki/Shell_script

[4]

child_process: https://nodejs.org/api/child_process.html

[5]

裏面提到有五種不同的並行運行命令的方式: https://stackoverflow.com/questions/3004811/how-do-you-run-multiple-programs-in-parallel-from-a-bash-script

[6]

execa: https://github.com/sindresorhus/execa

[7]

yargs: https://github.com/yargs/yargs

[8]

chalk: https://github.com/chalk/chalk

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/4BLXvRaVMS4-kPZ39DhRIg