Skip to content

Instantly share code, notes, and snippets.

@mitranim
Last active October 20, 2023 22:12
Show Gist options
  • Save mitranim/1e358e51b75812d25f4fcba7262df1ac to your computer and use it in GitHub Desktop.
Save mitranim/1e358e51b75812d25f4fcba7262df1ac to your computer and use it in GitHub Desktop.
Watches templates and reinitializes them on changes without fully restarting the app (excerpt from real app)
package main
import (
"fmt"
"html/template"
"time"
"github.com/pkg/errors"
"github.com/rjeczalik/notify"
)
var templateFuncs = map[string]interface{}{}
func initTemplating() error {
err = reinitHtmlTemplates()
if err != nil {
return err
}
if DEVELOPMENT_MODE {
htmlEvents, err := watchHtmlTemplates()
if err != nil {
return err
}
go reinitHtmlTemplatesOnChange(htmlEvents)
}
return nil
}
func reinitHtmlTemplates() error {
templates := template.New("")
templates.Funcs(template.FuncMap(templateFuncs))
_, err := templates.ParseGlob("templates/html/*")
env.htmlTemplates = templates // Writing a pointer is atomic.
return errors.WithStack(err)
}
func reinitHtmlTemplatesOnChange(events chan notify.EventInfo) {
for range events {
t0 := time.Now()
err := reinitHtmlTemplates()
if err != nil {
fmt.Printf("HTML template error: %+v\n", err)
} else {
t1 := time.Now()
fmt.Printf("reinited HTML templates in %v\n", t1.Sub(t0))
notifyInternalSubscriptions(InternalNotification{Type: InternalNotificationTypeReload})
}
}
}
func watchHtmlTemplates() (chan notify.EventInfo, error) {
events := make(chan notify.EventInfo, 1)
err := notify.Watch("templates/html", events, notify.All)
return events, errors.WithStack(err)
}
<script>
{
function reinit() {
const url = 'ws://' + window.location.host + '/ws'
const ws = new WebSocket(url)
ws.onmessage = onmessage
ws.onclose = onclose
}
reinit()
function onmessage({data}) {
let message
try {message = JSON.parse(data)}
catch (__) {return}
if (message && message.type === 'reload') {
window.location.reload()
}
}
function onclose() {setTimeout(reinit, 1000)}
}
</script>
@mitranim
Copy link
Author

mitranim commented Jun 8, 2020

Notes

env.htmlTemplates is a global which is used to render templates by name.

The subscription notification (notifyInternalSubscriptions) broadcasts a message to websocket clients. The HTML pages include a snippet which connects to the server via a websocket, and reloads the page when receiving the appropriate message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment