首页 > 后端开发 > Golang > 正文

Go 的模板引擎'templ”很方便(它也适用于 TinyGo)

Barbara Streisand
发布: 2024-10-30 20:31:30
原创
1062 人浏览过

概要

我想在 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中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板