首頁  >  文章  >  後端開發  >  Go 的模板引擎「templ」很方便(它也適用於 TinyGo)

Go 的模板引擎「templ」很方便(它也適用於 TinyGo)

Barbara Streisand
Barbara Streisand原創
2024-10-30 20:31:30999瀏覽

概要

我想在 Go 中運行一個返回純 HTML 的應用程序,
我決定使用 Cloudflare Workers,它可以將其轉換為 Wasm 並部署它。

我推薦 sumai/workers 的模板,用於將 Go 應用程式部署到 Cloudflare Workers。

sumai/workers:Go 套件以在 Cloudflare Workers 上執行 HTTP 伺服器。

前往文字/模板

首先,讓我們以簡單的方式使用文字/模板進行建構。

❯ ls -lh . /build
   total 15656
   -rwxr-xr-x 1 ergofriend staff 7.6M 8 8 20:12 app.wasm
   -rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:12 shim.mjs
   -rw-r--r-- 1 ergofriend staff 16K 8 8 20:12 wasm_exec.js
   -rw-r--r-- 1 ergofriend staff 160B 8 8 20:12 worker.mjs

差不多 8 MB。

https://developers.cloudflare.com/workers/platform/limits/#account-plan-limits

Cloudflare Workers 依照計畫有工作人員大小限制。

免費插槽為1MB,付費插槽($5~)為10MB。

即使有基於壓縮後大小的最終限制,也很難滿足從 8MB 開始的免費配額。

TinyGo 文字/模板

所以我決定切換到 TinyGo,它應該是為 WebAssembly (Wasm) 設計的。

建造後,大小約為 0.75 MB,似乎適合免費框架。

❯ ls -lh . /build
total 1160
-rwxr-xr-x 1 ergofriend staff 556K 8 8 20:23 app.wasm
-rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:23 shim.mjs
-rw-r--r-- 1 ergofriend staff 15K 8 8 20:23 wasm_exec.js
-rw-r--r-- 1 ergofriend staff 160B 8 8 20:23 worker.mjs

哎呀!

但這就是悲劇發生的地方。

當我嘗試存取建置的應用程式時,出現錯誤。

[wrangler:inf] GET / 200 OK (35ms)
✘ [ERROR] Uncaught (in response) RuntimeError: unreachable

      at main.runtime._panic (wasm://wasm/main-0022bc46:wasm-function[35]:0x2b4a)
      at main.(*text/template.state).evalField
  (wasm://wasm/main-0022bc46:wasm-function[540]:0x6c5f4)
      at main.(*text/template.state).evalFieldChain
  (wasm://wasm/main-0022bc46:wasm-function[531]:0x697fe)
      at main.(*text/template.state).evalFieldNode
  (wasm://wasm/main-0022bc46:wasm-function[530]:0x6959a)
      at main.(*text/template.state).evalPipeline
  (wasm://wasm/main-0022bc46:wasm-function[535]:0x6a1d2)
      at main.(*text/template.state).walk (wasm://wasm/main-0022bc46:wasm-function[569]:0x72cdd)
      at main.(*text/template.state).walk (wasm://wasm/main-0022bc46:wasm-function[569]:0x730b0)
      at main.main (wasm://wasm/main-0022bc46:wasm-function[261]:0x2ac52)
      at main.(net/http.HandlerFunc).ServeHTTP
  (wasm://wasm/main-0022bc46:wasm-function[463]:0x5973a)
      at
  main.interface:{ServeHTTP:func:{named:net/http.ResponseWriter,pointer:named:net/http.Request}{}}.ServeHTTP$invoke
  (wasm://wasm/main-0022bc46:wasm-function[459]:0x56f72)

panic: unimplemented: (reflect.Value).MethodByName()

在 template.ExecuteTemplate() 傳遞模板變數時呼叫的方法 MethodByName 尚未實作。

由於 TinyGo 是原始版本的子集,因此有許多不支援的功能,
我發現文字/模板正在調用不受支援的方法。

https://github.com/tinygo-org/tinygo/blob/1154212c15e6e97048e122068730dab5a1a9427f/src/reflect/type.go#L1086-L1088

現在,我想冷靜地為 TinyGo 說聲好話,但這次我要尋找一個快速的替代方案。

TEMPL

所以我正在尋找另一個模板引擎來替換文字/模板,並遇到了templ

Go 啊 / 寺廟

一種用 Go 編寫 HTML 使用者介面的語言。

Go

Go 的 HTML 範本語言,具有出色的開發人員工具。

Go

文件

請參閱 https://templ.guide 上的使用者文件

Go Go Go Go

任務

建造

建立本機版本。

❯ ls -lh . /build
   total 15656
   -rwxr-xr-x 1 ergofriend staff 7.6M 8 8 20:12 app.wasm
   -rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:12 shim.mjs
   -rw-r--r-- 1 ergofriend staff 16K 8 8 20:12 wasm_exec.js
   -rw-r--r-- 1 ergofriend staff 160B 8 8 20:12 worker.mjs
進入全螢幕模式 退出全螢幕模式

nix-update-gomod2nix

❯ ls -lh . /build
   total 15656
   -rwxr-xr-x 1 ergofriend staff 7.6M 8 8 20:12 app.wasm
   -rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:12 shim.mjs
   -rw-r--r-- 1 ergofriend staff 16K 8 8 20:12 wasm_exec.js
   -rw-r--r-- 1 ergofriend staff 160B 8 8 20:12 worker.mjs
進入全螢幕模式 退出全螢幕模式

安裝快照

建置並安裝目前版本。

❯ ls -lh . /build
total 1160
-rwxr-xr-x 1 ergofriend staff 556K 8 8 20:23 app.wasm
-rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:23 shim.mjs
-rw-r--r-- 1 ergofriend staff 15K 8 8 20:23 wasm_exec.js
-rw-r--r-- 1 ergofriend staff 160B 8 8 20:23 worker.mjs
進入全螢幕模式 退出全螢幕模式

建構快照

使用 goreleaser 使用 goreleaser 建置命令列二進位檔案。

❯ ls -lh . /build
   total 15656
   -rwxr-xr-x 1 ergofriend staff 7.6M 8 8 20:12 app.wasm
   -rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:12 shim.mjs
   -rw-r--r-- 1 ergofriend staff 16K 8 8 20:12 wasm_exec.js
   -rw-r--r-- 1 ergofriend staff 160B 8 8 20:12 worker.mjs
進入全螢幕模式 退出全螢幕模式

生成

使用本機版本執行 templ generated。

❯ ls -lh . /build
total 1160
-rwxr-xr-x 1 ergofriend staff 556K 8 8 20:23 app.wasm
-rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:23 shim.mjs
-rw-r--r-- 1 ergofriend staff 15K 8 8 20:23 wasm_exec.js
-rw-r--r-- 1 ergofriend staff 160B 8 8 20:23 worker.mjs
進入全螢幕模式 退出全螢幕模式

測試

運行 Go 測試。

❯ ls -lh . /build
   total 15656
   -rwxr-xr-x 1 ergofriend staff 7.6M 8 8 20:12 app.wasm
   -rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:12 shim.mjs
   -rw-r--r-- 1 ergofriend staff 16K 8 8 20:12 wasm_exec.js
   -rw-r--r-- 1 ergofriend staff 160B 8 8 20:12 worker.mjs
進入全螢幕模式 退出全螢幕模式

測試短

運行 Go 測試。

❯ ls -lh . /build
total 1160
-rwxr-xr-x 1 ergofriend staff 556K 8 8 20:23 app.wasm
-rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:23 shim.mjs
-rw-r--r-- 1 ergofriend staff 15K 8 8 20:23 wasm_exec.js
-rw-r--r-- 1 ergofriend staff 160B 8 8 20:23 worker.mjs
進入全螢幕模式 退出全螢幕模式

測試封面

跑…


在 GitHub 上查看


特徵

這是 TEMPL 的摘要。

自己的DSL

寫一個獨特的程式並不難,但是可以像 templ ≈ Go JSX 那樣寫。

❯ ls -lh . /build
   total 15656
   -rwxr-xr-x 1 ergofriend staff 7.6M 8 8 20:12 app.wasm
   -rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:12 shim.mjs
   -rw-r--r-- 1 ergofriend staff 16K 8 8 20:12 wasm_exec.js
   -rw-r--r-- 1 ergofriend staff 160B 8 8 20:12 worker.mjs

看起來很熟悉的寫作風格。

❯ ls -lh . /build
total 1160
-rwxr-xr-x 1 ergofriend staff 556K 8 8 20:23 app.wasm
-rw-r--r-- 1 ergofriend staff 1.2K 8 8 20:23 shim.mjs
-rw-r--r-- 1 ergofriend staff 15K 8 8 20:23 wasm_exec.js
-rw-r--r-- 1 ergofriend staff 160B 8 8 20:23 worker.mjs

使用它時,您可以逐個元件地呼叫由 templ generated 從 DSL 產生的 Go 函數。

[wrangler:inf] GET / 200 OK (35ms)
✘ [ERROR] Uncaught (in response) RuntimeError: unreachable

      at main.runtime._panic (wasm://wasm/main-0022bc46:wasm-function[35]:0x2b4a)
      at main.(*text/template.state).evalField
  (wasm://wasm/main-0022bc46:wasm-function[540]:0x6c5f4)
      at main.(*text/template.state).evalFieldChain
  (wasm://wasm/main-0022bc46:wasm-function[531]:0x697fe)
      at main.(*text/template.state).evalFieldNode
  (wasm://wasm/main-0022bc46:wasm-function[530]:0x6959a)
      at main.(*text/template.state).evalPipeline
  (wasm://wasm/main-0022bc46:wasm-function[535]:0x6a1d2)
      at main.(*text/template.state).walk (wasm://wasm/main-0022bc46:wasm-function[569]:0x72cdd)
      at main.(*text/template.state).walk (wasm://wasm/main-0022bc46:wasm-function[569]:0x730b0)
      at main.main (wasm://wasm/main-0022bc46:wasm-function[261]:0x2ac52)
      at main.(net/http.HandlerFunc).ServeHTTP
  (wasm://wasm/main-0022bc46:wasm-function[463]:0x5973a)
      at
  main.interface:{ServeHTTP:func:{named:net/http.ResponseWriter,pointer:named:net/http.Request}{}}.ServeHTTP$invoke
  (wasm://wasm/main-0022bc46:wasm-function[459]:0x56f72)

panic: unimplemented: (reflect.Value).MethodByName()
go run ./get-version > .version
cd cmd/templ
go build

產生的元件的函數繼承了模板中定義的參數類型,因此可以安全地呼叫。
與某些 ExecuteTemplate 不同,這是安全的。

VSCode 擴充

https://marketplace.visualstudio.com/items?itemName=a-h.templ

語法突出顯示和 LSP 補全將非常有用。

TinyGo 寺廟

為了確定,我查了一下,發現它只依賴reflect的TypeOf,它已經在TinyGo中實現了。

https://github.com/tinygo-org/tinygo/blob/1154212c15e6e97048e122068730dab5a1a9427f/src/reflect/type.go#L494-L500

現在讓我們試試使用 templ。
建築似乎有足夠的空間。

gomod2nix

這是實際應用。

goworkers-demo.ergofriend.workers.dev

訪問時可以正常返回HTML。

<span class="pl-c"># Remove templ from the non-standard ~/bin/templ path</span>
<span class="pl-c"># that this command previously used.</span>
rm -f ~/bin/templ
<span class="pl-c"># Clear LSP logs.</span>
rm -f cmd/templ/lspcmd/*.txt
<span class="pl-c"># Update version.</span>
go run ./get-version > .version
<span class="pl-c"># Install to $GOPATH/bin or $HOME/go/bin</span>
cd cmd/templ && go install

最終部署的大小也是187.91 KiB,因此有足夠的空間來擴展應用程式。

此驗證保留在此儲存庫中。
ergofriend/goworkers-demo


本文是日文譯本。
https://ergofriend.hatenablog.com/entry/2024/08/08/230603

以上是Go 的模板引擎「templ」很方便(它也適用於 TinyGo)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn