[譯] 選擇 Go 嵌入靜態資源的庫

來源:互聯網
上載者:User

原文:《Choosing A Library to Embed Static Assets in Go》

作者:Tim Shannon

譯者按:文章介紹了 Go 嵌入靜態檔案的幾種方法,接著講自己在使用某一個庫期間遇到的麻煩,最後比較不同庫的特點。對於想要將靜態資源構建到可執行檔裡的開發人員來說,有一定參考意義。在徵得原文作者同意的前提下,我開始了翻譯工作。

背景

Go 中一個常被吹捧的特性是 Go 應用容易部署,原因是 Go 寫的程式是靜態編譯的。但在你運行一個 Web 應用程式時,如果需要管理一系列檔案的路徑和許可權的話,這個優勢就基本不複存在了。

解決方案是把必要的檔案編譯到應用二進位裡去。在 Go 中可以用位元組切片存放檔案中String literals 形式的位元組內容。

 fileData := []byte("\x1f\x8b\ ... \x0f\x00\x00")

但這種方法最大的幾個壞處是:

  • 更大的二進位檔案
    • 對我當前的項目 Lex Library 而言,在沒嵌入靜態檔案之前,可執行檔大小為 20MB,嵌入後為 21MB。
  • 更長的編譯時間
    • 最新 Go 編譯器的緩衝機制能有效減少構建時間。
  • 編譯時間更占記憶體
    • 如果你在用小記憶體的裝置開發,這會影響到你。但對我個人來說,還無需關心。

你需要在開發效率和營運行政時間上作取捨。如果你的應用受眾是普羅福士(或者是那些有個人網上應用的極客使用者),就更值得權衡利弊了。

嵌入方式選擇

第一個處理 Go 嵌入靜態檔案的庫,或者說第一個真正知名的,應該是 jteeuwen 的 Go-BinData。這是個命令列應用,你輸入一個檔案路徑,它會產生包含靜態檔案的 .go 檔案。

然而,作者 jteeuwen 似乎離開了星球,並在走時候把 GitHub 上這個倉庫中所有東西刪了。幸運的是,他的代碼是開源的,並在社區被廣泛 fork。你在 GitHub 能找到好幾個維護得很好的 fork。我起初選的 fork 是 shuLhan 的,但後來又選了別的方案,原因下面會講。

更多有關 jteewen 項目的細節在這裡:https://github.com/jteeuwen/go-bindata/issues/5

備選方案

既然 jteewen 的庫有很多很多替代品。下面是我搜尋並整理的一個不完全列表:

  • vfsgen - https://github.com/shurcooL/vfsgen
  • go.rice - https://github.com/GeertJohan/go.rice
  • statik - https://github.com/rakyll/statik
  • esc - https://github.com/mjibson/esc
  • go-embed - https://github.com/pyros2097/go-embed
  • go-resources - https://github.com/omeid/go-resources
  • packr - https://github.com/gobuffalo/packr
  • statics - https://github.com/go-playground/statics
  • templify - https://github.com/wlbr/templify
  • gnoso/go-bindata - https://github.com/gnoso/go-bindata
  • shuLhan/go-bindata - https://github.com/shuLhan/go-bindata
  • fileb0x - https://github.com/UnnoTed/fileb0x
  • gobundle - https://github.com/alecthomas/gobundle
  • parcello - https://github.com/phogolabs/parcello

本文目的是幫你弄明白這些庫的差別,並幫你在選擇上面的某個庫時決定所需要考慮的特性。

去蕪存菁

有了這麼多選項,當決定要用哪一個才最適合需求時,就讓人頭大。你的程式和我的可能不一樣,但如果是 Web 應用程式的話,那會有很多可借鑒的地方。如果你需要做同樣的選擇,下文的比較將會很有用。

判斷標準

壓縮

上文提到的,嵌入靜態檔案一個缺點是增加了可執行檔大小。你可以在嵌入靜態檔案之前,用一個庫去壓縮,這樣能減少一些空間。同時也需要花點小功夫去解壓縮,但這通常是值得的,因為除了節省空間的外,構建時記憶體佔用量也會減少。此外,網頁靜態檔案壓縮率較高(相比圖片),這就是為什麼大多數瀏覽器支援 gzip 壓縮的原因。這就引入了下一個標準。

可選解壓縮

如果你的可執行檔中存有 gzip 壓縮的靜態檔案,並且你想把這些檔案按 gzip 格式提供給用戶端,那為何不直接發送這些已經壓縮的檔案呢?理想的庫應該支援一個選項,讓你在運行時去設定直接接受壓縮後的檔案,而不需要先解壓。

從本地檔案系統載入

在你開發 Web 應用程式時,在你修改代碼與看到改變之間,任何增加了時間或困難的事都應該被避免。如果在你每次修改 CSS 或 HTML 程式碼時,都必須重新構建 Go 程式來靜態嵌入檔案,你很快(就會放棄並)會選別的方案。

理想的庫應該允許我們輕鬆切換開發中構建的程式,從本地快速載入靜態檔案;在生產中,靜態檔案已經嵌入可執行程式並準備好發布了。

可重現的構建

這個準則讓我很意外,在我著手開發 Lex Library 時,我起初都沒有考慮過。前面提到的,我第一個選擇的庫是 shuLhan fork 的 go-bindata。我選擇它主要是因為我對原始的 go-bindata 庫熟悉,而且這個 fork 看起來維護得很好。

這個庫用起來很贊,不過出乎意料的事,我的持續整合(CI)構建開始失敗。像每一位碰到測試失敗的開發人員一樣,我想到的是改動了什麼。我立刻去檢查最新提交的改動,並試著弄明白為什麼這些改動導致模版處理失敗。在我困惑一陣後,並沒有找到原因,於是我重新跑了一次測試套件,這次測試是基於最後一次構建成功的代碼的,但也失敗了。這說明改動在於環境,而不是My Code。不過這引出了更多了問題。

我是在 Docker 容器中跑持續整合測試的。測試環境應該是自我包好的、嶄新的並且可複現的。但我的假設並不正確。在我看 Dockerfile 時,找到了問題所在:

RUN go get -u github.com/shuLhan/go-bindata/...

庫 go-bindata 有一次小的更新,這影響了我傳靜態檔案路徑的過程。突然間我內嵌檔案路徑就和我的預期不一樣了。這可能怪一些因素,比如 go get 總是擷取預設的分支。最後,歸結為這樣簡單的事實:程式中產生代碼的模組版本沒有被確定並讓我的 git 倉庫追蹤。程式依賴的外部代碼如果改動了,就會在不知不覺時,導致我的構建或測試失敗。

一種解決辦法是存個預先編譯的 go-bindata 可執行檔到我的 git 項目中,但是:

  1. 通常 git 倉庫中不宜存二進位檔案。
  2. 如果依賴的庫修複了漏洞,我每次都需要手動更新 go-bindata。
  3. 如果換一個平台,將會使構建變得困難。

此外,我找到了一個無需獨立二進位檔案的庫,完全依賴代碼版本,這可以用 vendor 來管理。意思是有一個支援 go-generate 的庫,但不同的是,不需要依賴外部程式運行。

附加的標準

上文講你可能有不同的需求,所以在我的下面的對比表中,還添加了一些額外的標準,這或許對你有用。

設定檔

如果你有大量不同的目錄和檔案需要管理,使用設定檔並放到你的源碼裡,這樣管理就輕鬆多了。

http.FileSystem 介面

實現 http.FileSystem 介面的庫能讓嵌入檔案更容易處理。

GitHub 超過 200 星

這有點武斷,星數不一定是衡量代碼品質的方法。不過項目星數能說明庫的活躍性,起碼能說明是不是一個在多處被引用的庫。這反過來也說明很多人都在測試它,和(或)反饋問題。我選的庫,僅僅超過了這個星數,注意一下。

對比

壓縮 可選解壓 本地檔案系統 go generate 無可執行檔 設定檔 http.FS 多於 200 星
vfsgen ✓*
go.rice
statik
esc
go-embed ✓*
go-resources ✓*
packr
statics
templify
gnoso/go-bindata
shuLhan/go-bindata
fileb0x
gobundle
parcello

* 需要額外代碼

我使用這些庫的經驗是它們在寫程式和部署時各有不同,要去看對應項目的 README 和文檔。如果你看到上表中不準確之處,請在評論中讓我知道,我會更新。

我的選擇

通過上面的比較表,就很清楚為什麼我最終會用 vfsgen,並且我高度推薦它,尤其在你需要可複現的構建時。稍遜一點的是 fileb0x,它需要獨立的可執行檔才能使用 go generate

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.