gin+templ实现高性能ssr网页渲染


templ文档:https://templ.guide/

安装templ插件前提:
go get -tool github.com/a-h/templ/cmd/templ@latest # 安装 templ 命令行
go tool templ

vscode插件

templ 作者a-h
Templ Go To Definition 可选插件

tailwindcss安装配置

npm install tailwindcss @tailwindcss/cli 安装最新版
创建tailwind.css

css
@import "tailwindcss";

npx @tailwindcss/cli -i ./tailwind.css -o ./static/css/app.css --watch 开发环境监听
npx @tailwindcss/cli -i ./tailwind.css -o ./static/css/app.css --minify 生产构建压缩`

vscode配置tailwind识别templ

VS Code 设置搜索tailwindCSS.includeLanguages,设置"templ": "html"
搜索设置files.associations,设置"*.templ": "templ"

生成go代码(每次修改了templ页面都需要执行)

templ generate

templ原理和示例

假设自定义了一个views包
views/share.templ:

go
package views // 1. 声明包名,生成的 Go 代码将位于此包下

// 2. 定义组件函数 Share,接收参数用于动态渲染
templ Share(fileName string) {
    <!-- 3. 标准 HTML 结构 -->
    <html>
        <head><title>分享页面</title></head>
        <body>
            <!-- 4. 使用 { 变量名 } 嵌入 Go 变量 -->
            <h1>正在下载文件:{ fileName }</h1>
        </body>
    </html>
}

假设定义了一个ssrs包,用来写ssr路由的逻辑

go
package ssrs

import (
    "github.com/gin-gonic/gin"
    "<项目路径>/views" // 导入views包
)

func RouterShare(c *gin.Context) {
    // 实例化组件 (调用生成的 Go 函数),并传入变量
    component := views.Share("演示文件.zip")

    // 核心步骤:将组件渲染到 Gin 的 ResponseWriter
    // context 用于控制流程(如超时),w 是写入目标
    err := component.Render(c.Request.Context(), c.Writer)
    if err != nil {
        c.String(500, "渲染错误")
    }
}

注册这个路由
r.GET("/share", ssrs.RouterShare) // 绑定 GET 请求到 handler

模板语法讲解

Templ本质是“把模板编译成 Go 代码”,计算、比较、判断、循环:几乎就是写 Go 语法,Templ 的角色:把“Go 逻辑”与“HTML 结构”拼成一个可渲染组件

go
package views

templ Cheatsheet(a int, b int, items []string) { 
  // ---------- 计算:都是 Go 表达式/语句
  sum := a + b // 加法
  diff := a - b // 减法
  mul := a * b // 乘法
  div := 0 // 防止除零
  if b != 0 { // 判断
    div = a / b // 整数除法
  }

  // ---------- 比较:也是 Go 表达式
  gt := a > b // 大于
  eq := a == b // 等于

  <!doctype html>
  <html lang="zh-CN">
    <head>
      <meta charset="utf-8">
      <title>Templ 速记</title>
    </head>
    <body>
      <h2>算术</h2>
      <div>a={ a }, b={ b }</div>
      <div>sum={ sum }, diff={ diff }, mul={ mul }, div={ div }</div>

      <h2>比较</h2>
      <div>a>b ? { gt }</div>
      <div>a==b ? { eq }</div>

      <h2>判断 if</h2>
      if a > b { 
        <div>结论:a 大于 b</div>
      } else if a == b {
        <div>结论:a 等于 b</div>
      } else {
        <div>结论:a 小于 b</div>
      }

      <h2>遍历 for</h2>
      <ul>
        for i, it := range items {
          <li>{ i }: { it }</li>
        }
      </ul>

      <h2>经典 for</h2>
      <ul>
        for i := 0; i < 3; i++ { 
          <li>row { i }</li>
        }
      </ul>
    </body>
  </html>
} 

尊重人不应该胜于尊重真理。-- 柏拉图