Golang中使用inertia.js的经验分享与讨论

Golang中使用inertia.js的经验分享与讨论 https://github.com/petaki/inertia-go - 它让你能够将 Golang 与 SPA 框架集成。我是在一个关于 Rails 的播客中听说它的。我认为它允许你无需构建 API 和显式地进行序列化。我对此仍在形成自己的看法。

1 回复

更多关于Golang中使用inertia.js的经验分享与讨论的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Inertia.js 与 Go 的结合确实为全栈开发提供了独特的工作流。以下是基于 petaki/inertia-go 的经验分享:

核心优势

  1. 无需显式 API:直接通过 Go 控制器返回 Inertia 响应,无需手动构建 REST API 端点
  2. 服务端数据传递:使用 inertia.Render 将数据直接注入前端组件
  3. 自动序列化:框架自动处理 Go 结构体到前端 props 的转换

示例代码

// main.go
package main

import (
    "github.com/gin-gonic/gin"
    "github.com/petaki/inertia-go"
    "github.com/petaki/inertia-go/gin"
)

func main() {
    engine := gin.Default()
    
    // 初始化 Inertia
    inertia := inertia.New("", "", "")
    inertia.Share("appName", "My Go + Inertia App")
    
    // 注册中间件
    engine.Use(inertiaGin.Middleware(inertia))
    
    // 定义路由
    engine.GET("/users", func(c *gin.Context) {
        users := []User{
            {ID: 1, Name: "张三", Email: "zhangsan@example.com"},
            {ID: 2, Name: "李四", Email: "lisi@example.com"},
        }
        
        // 直接渲染到前端组件
        inertiaGin.Render(c, "Users/Index", gin.H{
            "users": users,
            "pageTitle": "用户列表",
        })
    })
    
    engine.Run(":8080")
}

// User 结构体会自动序列化为前端 props
type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

前端组件 (Vue 3 + TypeScript)

<!-- Users/Index.vue -->
<script setup lang="ts">
defineProps<{
  users: Array<{
    id: number
    name: string
    email: string
  }>
  pageTitle: string
}>()
</script>

<template>
  <div>
    <h1>{{ pageTitle }}</h1>
    <ul>
      <li v-for="user in users" :key="user.id">
        {{ user.name }} - {{ user.email }}
      </li>
    </ul>
  </div>
</template>

关键特性实践

// 1. 共享数据(全局 props)
inertia.Share("auth", func(c *gin.Context) interface{} {
    return gin.H{
        "user": c.MustGet("user"),
        "permissions": getUserPermissions(c),
    }
})

// 2. 部分重载
engine.POST("/users/update", func(c *gin.Context) {
    // 只更新特定 props
    inertiaGin.Render(c, "Users/Edit", gin.H{
        "user": updatedUser,
    }, []string{"user"}) // 仅重载 user 数据
})

// 3. 服务端渲染支持
inertia.SetSsrEnabled(true)
inertia.SetSsrUrl("http://localhost:13714")

性能优化技巧

// 延迟数据加载
engine.GET("/dashboard", func(c *gin.Context) {
    inertiaGin.Render(c, "Dashboard", gin.H{
        "stats": gin.H{
            "users": func() int {
                // 延迟计算,仅在需要时执行
                return countUsers()
            },
            "revenue": calculateRevenue,
        },
    })
})

// 版本控制(自动刷新资源)
inertia.SetVersion(func() string {
    // 返回文件 hash 或时间戳
    return getAssetVersion()
})

错误处理

engine.GET("/users/{id}", func(c *gin.Context) {
    user, err := getUserByID(c.Param("id"))
    if err != nil {
        // Inertia 会自动处理 404 页面
        c.AbortWithStatus(404)
        return
    }
    
    inertiaGin.Render(c, "Users/Show", gin.H{
        "user": user,
    })
})

与前端框架的深度集成

// 表单处理示例
engine.POST("/users", func(c *gin.Context) {
    var input CreateUserInput
    if err := c.ShouldBind(&input); err != nil {
        // 返回验证错误到前端
        inertiaGin.Render(c, "Users/Create", gin.H{
            "errors": getValidationErrors(err),
            "input": input,
        })
        return
    }
    
    user := createUser(input)
    // 重定向并保持页面状态
    inertiaGin.Location(c, "/users/"+strconv.Itoa(user.ID))
})

这种模式特别适合需要快速迭代的中小型项目,它减少了前后端分离带来的沟通成本,同时保持了现代 SPA 的用户体验。不过需要注意,对于大型复杂应用,可能需要评估其与纯 API 架构的性能差异。

回到顶部