Skip to content
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

Should next.js be deferred (common.js, main.js) #1436

Closed
khrome83 opened this issue Mar 15, 2017 · 13 comments
Closed

Should next.js be deferred (common.js, main.js) #1436

khrome83 opened this issue Mar 15, 2017 · 13 comments
Assignees

Comments

@khrome83
Copy link
Contributor

khrome83 commented Mar 15, 2017

Should next.js defer parsing of JS for the common.js and main.js bundles?

Not familiar with the architecture or how to do this, but it came up as a performance issue.

"382.6KiB of JavaScript is parsed during initial page load. Defer parsing JavaScript to reduce blocking of page rendering."

All but 1.5kb was from common.js and main.js code.

@sergiodxa
Copy link
Contributor

🤔 AFAIK If you defer the parsing of common.js and main.js and try to parse (and execute) the code for your view you are going to have an error because your view code depends on common.js and main.js code to work

@khrome83
Copy link
Contributor Author

First page load is server rendered. So do need common.js and main.js to run until, after the site downloads? I am just curious.

@arunoda
Copy link
Contributor

arunoda commented Mar 16, 2017

@khrome83 You are correct. We can't async those scripts since they need to be load in sequence. But we can defer them.

@wagerfield
Copy link

wagerfield commented Mar 16, 2017

@arunoda the most bulletproof solution to deferring scripts that I've come across is this:

https://varvy.com/pagespeed/defer-loading-javascript.html

As the article explains, adding the the defer or async attributes to script tags doesn't actually allow the page to fully load. You can see the results of different approaches in the various demos he's put together.

Hope this helps :)

@arunoda
Copy link
Contributor

arunoda commented Mar 16, 2017

@wagerfield thanks.

defer is all what we need. Since we are not supporting IE9 that's work for us great.

@khrome83
Copy link
Contributor Author

Thank you @arunoda for getting this in.

@wagerfield
Copy link

@arunoda did you read the article? Adding the defer attribute doesn't actually solve the problem.

This isn't an archaic method for supporting IE9—this is a behaviour that the latest version of Chrome and other modern browsers experience.

If you take a look at the various examples he put together, you will see that adding the defer attribute doesn't prevent a loaded script from blocking the critical rendering path. If a deferred script starts executing as soon as it loads, it will stop the page from fully loading.

https://varvy.com/pagespeed/defer/defer-example-defer.html

In Chrome you will see the loading spinner on the tab where the favicon normally is persist for 2-3 seconds while the deferred script setTimeout is waiting to return—and is thus blocks the critical rendering path.

1

Furthermore if you open Chrome dev tools and go to the Network tab, you will also see that the page doesn't Load for ~2-3secs.

2

If you then take a look at the 'solved' example you will see that a) the browser tab loading spinner doesn't stall and b) that the Load event fires in the dev tools Network tab after ~3-400ms.

https://varvy.com/pagespeed/defer/defer-example-solved.html

3

@arunoda
Copy link
Contributor

arunoda commented Mar 17, 2017

@wagerfield yep. I didn't read the article well.
What's available here is correct.

I don't like it's use of window.onload but I'll try to use 'DOMContentLoaded'.
I'll re-work my PR.

@arunoda
Copy link
Contributor

arunoda commented Mar 17, 2017

@wagerfield Actually, I had to use setTimeout(fn, 0) hack to make it work with DOMContentLoaded.

I think, it's not started rendering yet at that point. Here's the code:

<html>
<head>
<script type="text/javascript">

// Add a script element as a child of the body
 function downloadJSAtOnload() {
   setTimeout(function() {
     var element = document.createElement("script");
     element.src = "/defer-example-solved_files/defer.js";
     document.body.appendChild(element);
   }, 0)
 }

 // Check for browser support of event handling capability
 document.addEventListener("DOMContentLoaded", downloadJSAtOnload, false);
</script>
</head>
<body>

<h1>I wait 2 seconds then ...</h1>
<p id="inner"></p>

</body>
</html>

@ptomasroos
Copy link
Contributor

In what way would it be better to use setTimeout, 0 with DomContentLoaded than relying onLoad @arunoda ?

What is there not to like about onLoad? Its been proven since 1999 or something.

@arunoda
Copy link
Contributor

arunoda commented Mar 19, 2017

onload is working properly and it runs after all the resources in the page completed. That's good for external scripts.

But this for our main JS bundle. We need to load as soon as possible without rendering the bundle.

I face an issue currenly because I nees to load two scripts in sequence. But I can't download them in parallel. I am thinking ways to do it now

@ptomasroos
Copy link
Contributor

I think react server uses LABjs. Load and block for them to get correctly sequenced. You might take a look at that. It's from yahoo.

@arunoda
Copy link
Contributor

arunoda commented Mar 19, 2017

Thanks @ptomasroos Yeah! Labjs is kind a interesting and something I was looking for.
But the thing is, we need to test a bit more and it'll take time.

So, I'm going with the defer attribute for now.

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

No branches or pull requests

5 participants