valyala / quicktemplate

Fast, powerful, yet easy to use template engine for Go. Optimized for speed, zero memory allocations in hot paths. Up to 20x faster than html/template

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

{% flush %} tag for progressive rendering of HTML?

stereosteve opened this issue · comments

Hello valyala -

Was interested in doing "progressive rendering" where the first part of a page is flushed before slower content is loaded and rendered. This is possible by decomposing page into chunks and rendering them in order, but requires that you split any existing templates / layouts in half.

It seems like it would be possible to add a {% flush %} tag that would emit this in the middle of the template:

        if f, ok := w.(http.Flusher); ok {
		f.Flush()
	}

I was able to verify this works in practice by adding this code to a .qtpl.go:

        qw422016.N().S(`<h1>Before flush...</h1>`)
	if f, ok := qw422016.W().(http.Flusher); ok {
		f.Flush()
	}
	time.Sleep(5 * time.Second)
	qw422016.N().S(`<h1>After flush...</h1>`)

I started to implement here but the use of http in the middle of the emitted file would require that net/http be imported at the top, and by that point the emitImportsUse function has already run.

One option is to just require user to do {% import "net/http" %} if they plan to use {% flush %}. The hero project relies on goimports to solve this problem.

If the import issue could be fixed, would you be interested in adding a tag like this?

After typing this out I realized this can be done by passing the ResponseWriter into the template and doing something like:

        {% import "net/http" %}

        ...

        {% code
		if f, ok := page.ResponseWriter.(http.Flusher); ok {
			f.Flush()
		}
	%}
        // slow code here

So... problem solved!