Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to reload html templates after app is started?

Tags:

go

Right now I currently parse all the templates into a variable like so:

var templates = template.New("Template")

func LoadTemplates() {
    filepath.Walk("view/", func(path string, info os.FileInfo, err error) error {
        if strings.HasSuffix(path, ".html") {
            templates.ParseFiles(path)
        }
        return nil
    })
}

func Render(w http.ResponseWriter, tmplName string, data interface{}) {
    if err := templates.ExecuteTemplate(w, tmplName, data); err != nil {
        log.Println(err)
    }
}

So if I make any changes, I need to restart the entire app. Is there any way I can make it so that the changes are reflected when they're made

like image 209
Datsik Avatar asked Dec 18 '22 17:12

Datsik


1 Answers

It is completly OK to reload your templates on every request when developing / in debug mode.

You can define an interface and two "template executors" like so

type TemplateExecutor interface{
    ExecuteTemplate(wr io.Writer, name string, data interface{}) error
}

type DebugTemplateExecutor struct  {
    Glob string
}

func (e DebugTemplateExecutor) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
    t := template.Must(template.ParseGlob(e.Glob))
    return t.ExecuteTemplate(wr, name, data)
}

type ReleaseTemplateExecutor struct  {
    Template *template.Template
}

func (e ReleaseTemplateExecutor) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
    return e.Template.ExecuteTemplate(wr, name, data)
}

that wrap template.Execute(). Pick which one you want at runtime e.g.

const templateGlob = "templates/*.html"
const debug = true

var executor TemplateExecutor

func main() {
    if debug {
        executor = DebugTemplateExecutor{templateGlob}

    } else {
        executor = ReleaseTemplateExecutor{
            template.Must(template.ParseGlob(templateGlob)),
        }
    }

    http.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
        executor.ExecuteTemplate(w, "test.html", nil)
    })

    http.ListenAndServe(":3000", nil)
}

If you need hot reload in production, i'd suggest watching the directory for changes instead of compiling it on every request.

like image 53
fl0cke Avatar answered Mar 16 '23 13:03

fl0cke