基于Golang、Templ和HTMX实现浏览器热重载
解决Golang+Templ+HTMX开发中浏览器自动刷新的问题
以下是几种规范且实用的解决方案,无需依赖不规范的HTMX hack:
方案1:配合Livereload工具实现浏览器自动刷新
Livereload可监听文件变更并通知浏览器刷新,和wgo的服务端重启完美配合:
- 安装Livereload命令行工具:
go install github.com/livereload/livereload/v2/cmd/livereload@latest - 在项目根目录启动Livereload,监听模板文件、静态资源或templ生成的Go文件:
livereload -w "./templates" -w "./static" -w "./generated_templates" - 在基础templ模板中添加Livereload脚本注入代码:
当Livereload检测到文件变更会自动触发浏览器刷新,同时wgo负责重启Go服务,两者协同完成全流程自动刷新。<script> document.write('<script src="http://' + (location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1"></' + 'script>'); </script>
方案2:通过SSE(服务器发送事件)实现服务端驱动的浏览器刷新
利用HTMX对SSE的原生支持,实现服务端主动通知浏览器刷新,无需第三方工具:
在Go服务中添加SSE端点:
var refreshChan = make(chan struct{}) func sseRefreshHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/event-stream") w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Connection", "keep-alive") flusher, ok := w.(http.Flusher) if !ok { http.Error(w, "SSE not supported", http.StatusInternalServerError) return } for { select { case <-r.Context().Done(): return case <-refreshChan: fmt.Fprintf(w, "event: refresh\ndata: {}\n\n") flusher.Flush() } } }记得将该端点注册到路由,比如
http.HandleFunc("/sse/refresh", sseRefreshHandler)。在templ模板中添加SSE监听逻辑,收到刷新信号时重载页面:
<script> const sseSource = new EventSource('/sse/refresh'); sseSource.addEventListener('refresh', () => { window.location.reload(); }); </script>配置文件变更监听:使用
fsnotify等库监听Go文件、templ模板的变更,检测到变更时向refreshChan发送信号;或者在wgo的重启钩子中触发信号,确保服务重启后通知所有客户端刷新。
方案3:结合Templ的Watch模式+Livereload
Templ本身支持监听模板变更并自动生成Go代码,配合wgo和Livereload实现端到端自动刷新:
- 启动Templ的watch模式,自动重新生成模板对应的Go代码:
templ generate --watch - 启动wgo监听Go文件变更,自动重启服务:
wgo run main.go - 启动Livereload监听生成的模板Go文件或静态资源(同方案1的Livereload配置),触发浏览器刷新。
关键注意事项
- 确保wgo正确配置监听路径,能检测到Go代码变更并重启服务;
- 使用SSE方案时,要处理客户端断开连接的情况,避免服务端goroutine泄漏;
- 避免使用定时刷新这类不规范方案,优先选择事件驱动的自动刷新逻辑。
内容的提问来源于stack exchange,提问作者MaximilianFullStack
相关产品推荐
相关产品推荐

