Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Use defer attribute in gopherjs serve default HTML. #570

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

Closed
wants to merge 1 commit into from

Conversation

dmitshur
Copy link
Member

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:

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
Copy link
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?

@dmitshur
Copy link
Member Author

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
Copy link
Member Author

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 January 10, 2017 19:44
@neelance
Copy link
Member

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants