New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use defer attribute in gopherjs serve default HTML. #570

Closed
wants to merge 1 commit into
base: master
from

Conversation

Projects
None yet
2 participants
@dmitshur
Member

dmitshur commented Jan 10, 2017

Note, because the implementation was trivial, this PR serves as both a proposal (up for discussion) and implementation in one.


The defer attribute specifies that the script is executed when the page has finished parsing.

This affects the default HTML served by gopherjs serve command when there
isn't an index.html provided. Advanced users who want custom behavior will be
specifying their own HTML anyway. For beginners or people looking to write
a quick snippet, having the script be deferred makes it easier to not worry about
the script running before the body is available. It allows writing:

var document = dom.GetWindow().Document().(dom.HTMLDocument)

func main() {
	body := document.Body()
	// ... use body right away
}

Instead of having to write:

var document = dom.GetWindow().Document().(dom.HTMLDocument)

func main() {
	switch readyState := document.ReadyState(); readyState {
	case "loading":
		document.AddEventListener("DOMContentLoaded", false, func(dom.Event) {
			go setup()
		})
	case "interactive", "complete":
		setup()
	default:
		panic(fmt.Errorf("internal error: unexpected document.ReadyState value: %v", readyState))
	}
}

func setup() {
	body := document.Body()
	// ... use body right away
}

Which is more user friendly.

References:

Use defer attribute in gopherjs serve default HTML.
It specifies that the script is executed when the page has finished parsing.

This affects the default HTML served by gopherjs serve command when there
isn't an index.html provided. Advanced users who want custom behavior will be
specifying their own HTML anyway. For beginners or people looking to write
a quick snippet, having the script be deferred makes it easier to not worry about
the script running before the body is available. It allows writing:

	var document = dom.GetWindow().Document().(dom.HTMLDocument)
	
	func main() {
		body := document.Body()
		// ... use body right away
	}

Instead of having to write:

	var document = dom.GetWindow().Document().(dom.HTMLDocument)
	
	func main() {
		switch readyState := document.ReadyState(); readyState {
		case "loading":
			document.AddEventListener("DOMContentLoaded", false, func(_ dom.Event) {
				go setup()
			})
		case "interactive", "complete":
			setup()
		default:
			panic(fmt.Errorf("internal error: unexpected document.ReadyState value: %v", readyState))
		}
	}
	
	func setup() {
		body := document.Body()
		// ... use body right away
	}

Which is more user friendly.

References:

-	http://www.w3schools.com/tags/att_script_defer.asp
-	https://developer.mozilla.org/en/docs/Web/HTML/Element/script
-	http://caniuse.com/#feat=script-defer
@neelance

This comment has been minimized.

Show comment
Hide comment
@neelance

neelance Jan 10, 2017

Member

Hmm. So with vecty I avoided that "body not yet available" situation by setting document.body explicitly, see https://github.com/gopherjs/vecty/blob/master/dom.go#L356. What I'd like to avoid is flickering when refreshing the page, e.g. the browser first rendering a blank page before running the script. How does defer affect that?

Member

neelance commented Jan 10, 2017

Hmm. So with vecty I avoided that "body not yet available" situation by setting document.body explicitly, see https://github.com/gopherjs/vecty/blob/master/dom.go#L356. What I'd like to avoid is flickering when refreshing the page, e.g. the browser first rendering a blank page before running the script. How does defer affect that?

@dmitshur

This comment has been minimized.

Show comment
Hide comment
@dmitshur

dmitshur Jan 10, 2017

Member

From my testing in Chrome 55, doing something like this without defer has no blank page during refresh:

func main() {
	body := js.Global.Get("document").Call("createElement", "body")
	body.Set("innerHTML", "Some body.")
	js.Global.Get("document").Set("body", body)
}

But adding defer causes the blank page to show up momentarily during refresh. It's visible from the moment the page finishes loading, until the script has finished running.

I'll withdraw this proposal as-is because it has this disadvantage, and think more about it if there's a way to not have it.

Even if there's no way to have both, it might still be better for gopherjs serve to optimize for beginners and short snippets, rather than performance and advanced features (like avoiding a flash of empty body).

Member

dmitshur commented Jan 10, 2017

From my testing in Chrome 55, doing something like this without defer has no blank page during refresh:

func main() {
	body := js.Global.Get("document").Call("createElement", "body")
	body.Set("innerHTML", "Some body.")
	js.Global.Get("document").Set("body", body)
}

But adding defer causes the blank page to show up momentarily during refresh. It's visible from the moment the page finishes loading, until the script has finished running.

I'll withdraw this proposal as-is because it has this disadvantage, and think more about it if there's a way to not have it.

Even if there's no way to have both, it might still be better for gopherjs serve to optimize for beginners and short snippets, rather than performance and advanced features (like avoiding a flash of empty body).

@dmitshur

This comment has been minimized.

Show comment
Hide comment
@dmitshur

dmitshur Jan 10, 2017

Member

Closing because I've withdrawn this particular implementation attempt for now, due to the above problem.

I've opened #571 to track the issue and continue the discussion in.

Member

dmitshur commented Jan 10, 2017

Closing because I've withdrawn this particular implementation attempt for now, due to the above problem.

I've opened #571 to track the issue and continue the discussion in.

@dmitshur dmitshur closed this Jan 10, 2017

@dmitshur dmitshur deleted the defer-serve branch Jan 10, 2017

@neelance

This comment has been minimized.

Show comment
Hide comment
@neelance

neelance Jan 10, 2017

Member

Maybe try to add this before the other script tag:
<script>document.body = document.createElement("body");</script>

Member

neelance commented Jan 10, 2017

Maybe try to add this before the other script tag:
<script>document.body = document.createElement("body");</script>

hajimehoshi added a commit that referenced this pull request Oct 4, 2018

hajimehoshi added a commit that referenced this pull request Oct 4, 2018

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