-
-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Deferred script loading v2 #3696
Deferred script loading v2 #3696
Conversation
@michaelletzgus, thanks for your PR! By analyzing the history of the files in this pull request, we identified @LukasReschke, @nickvergessen and @ChristophWurst to be potential reviewers. |
<?php if (isset($_['inline_ocjs'])): ?> | ||
<script nonce="<?php p(\OC::$server->getContentSecurityPolicyNonceManager()->getNonce()) ?>" type="text/javascript"> | ||
<script nonce="<?php p(\OC::$server->getContentSecurityPolicyNonceManager()->getNonce()) ?>"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this change required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know, for me both version work faster.
But: HTML5 does not require the type
attribute. My intention was to prevent current or future browsers triggering any kind of legacy or compatibility mode which might interrupt the concurrent resource loading.
In short: The change is possibly not required for defeating the performance problem...
Wow! This is amazing. The page loads significantly faster. Thank you very much 😍 |
@@ -18,15 +18,15 @@ | |||
<?php foreach($_['printcssfiles'] as $cssfile): ?> | |||
<link rel="stylesheet" href="<?php print_unescaped($cssfile); ?>" media="print"> | |||
<?php endforeach; ?> | |||
<?php foreach ($_['jsfiles'] as $jsfile): ?> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we really have to move those lines up? This could potentially change/break the loading order with the scripts below (inline_ocjs)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, it changed the order. inline_ocjs will be executed first (while parsing), the deferred scripts after parsing but before the DOMContentLoaded
event comes up.
The standard states: "The defer attribute is only for external scripts (should only be used if the src attribute is present)."
I have found no code in the inline_ocjs which depends on other.
If the old order of execution (first inline, then extern) is desired the inline script code must become external. So why do we have internal code here at all? I think all these variables could be loaded form extern as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ChristophWurst
In fact this does NOT change the order of execution when using defer
for the external script, it only allows Firefox to download css and js in parallel.
With the inline_js block placed between css and js downloading of css and js happens synchronously. This seems to be a "feature" of at least Firefox...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, thanks for the explanation :-)
@@ -19,15 +19,15 @@ | |||
<?php foreach($_['printcssfiles'] as $cssfile): ?> | |||
<link rel="stylesheet" href="<?php print_unescaped($cssfile); ?>" media="print"> | |||
<?php endforeach; ?> | |||
<?php foreach($_['jsfiles'] as $jsfile): ?> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same problem/question here
@@ -26,15 +26,15 @@ | |||
<?php foreach($_['printcssfiles'] as $cssfile): ?> | |||
<link rel="stylesheet" href="<?php print_unescaped($cssfile); ?>" media="print"> | |||
<?php endforeach; ?> | |||
<?php foreach($_['jsfiles'] as $jsfile): ?> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same
lib/private/legacy/template.php
Outdated
@@ -233,6 +233,9 @@ public function fetchPage($additionalParams = null) { | |||
$headers = ''; | |||
foreach(OC_Util::$headers as $header) { | |||
$headers .= '<'.\OCP\Util::sanitizeHTML($header['tag']); | |||
if ( strcasecmp($header['tag'], 'script') == 0 and in_array('src', array_map('strtolower', array_keys($header['attributes']))) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use ===
for comparison and &&
as logical and
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK!
@michaelletzgus A rebase will automatically remove them ;) |
1ec849c
to
e3a4e4c
Compare
e3a4e4c
to
b5a6f03
Compare
@michaelletzgus you don't need to close your PR, you can do a rebase easily on the same PR:
|
Sorry for the confusion, but git will definitively not my friend, I'm grown up with CVS&SVN ;-) |
Sorry for that, thanks anyway for trying and it seems to have worked 🎉 |
@nickvergessen No problem, maybe git will be my friend in a few days... ;) |
@michaelletzgus Give https://try.github.io a try 😉 It helps to understand the concepts :) |
02d0768
to
e5fe6ab
Compare
Can someone explain what caused this to break? I have an installation of 11.0.1 that doesn't have the same behavior as 11.0.2. Somehow 11.0.1 did not need the defer tag, yet it loads quickly. |
I observed no difference between 11.0.1 and 11.0.2 when using Firefox, both are "slow" without |
@nickvergessen @MorrisJobke |
When it doesn't get slower than it is at the moment, I'm fine with merging it |
1. Remove type attribute from inline_js 2. Add defer attribute to external script 3. Move inline_script down Date: Wed Mar 8 09:43:51 2017 +0100 Committer: Michael Letzgus <michaelletzgus@users.noreply.github.com> Signed-off-by: Michael Letzgus <michaelletzgus@users.noreply.github.com>
6d5b8cb
to
a39b996
Compare
Codecov Report
@@ Coverage Diff @@
## master #3696 +/- ##
============================================
- Coverage 54.24% 54.24% -0.01%
- Complexity 21112 21114 +2
============================================
Files 1304 1304
Lines 80655 80657 +2
Branches 1275 1275
============================================
Hits 43752 43752
- Misses 36903 36905 +2
Continue to review full report at Codecov.
|
Tested and works, applied on top of 11.0.2. This is marked for version 12, any chance this can be applied for 11.0.3? It is really a difference of night and day with and without this patch. |
No. We do only backport critical patches. This here has the potential to breaking stuff and I'm still keen on feedback at https://bugzilla.mozilla.org/show_bug.cgi?id=1342781 |
I've found the first problem with
This results in "ReferenceError: marked is not defined". Problem seems to be related to this: |
I've applied these changes to my nextcloud 11.0.0 and the difference of loading is a lot. After few days of usage I've noticed that my external calendars (for example webcal://www.calendarlabs.com/templates/ical/International-Holidays.ics) aren't loading anymore. Checking the console it says:
I haven't tried this under the v11.0.2 |
Works fine here on 12. (with the very same url |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just commenting here so that nobody merges this. I don't feel entirely confident here.
- This breaks some apps as some people pointed out.
- I still am curious about a feedback at https://bugzilla.mozilla.org/show_bug.cgi?id=1342781
I think it's better to go with #3988 instead. This achieves probably the same without too much dark magic. :)
Replaced by #3988 |
Sure we saved some requests by combining js, but still FF loads stuff pretty slowly, which this PR actually addressed nicely. Can we re-open this and wait for FF dev's response? 🙏 |
I agree – combining CSS and JS is rather a workaround for HTTP/1.1. And since every current version of nginx and Apache provides HTTP/2 support it's (IMHO) the Linux distributions' issue to support that and not Nextcloud's. ;) Hence I would advise to not deny this PR. |
Actually, I use HTTP/2 and firefox still takes half a minute to load the files app on my firefox instance, so that's not really a fix. |
@ajs124 Could also be a configuration or setup issue. |
I should point out that HAProxy do not support HTTP/2 (maybe 6-12 months away, or more), with is a really popular proxy software to load balance if you have a larger site (or, special needs). It's is also likely that a larger cooperation will be stuck with proprietary load balances that only support HTTP/1 for years. So support for HTTP/1 is relevant still. I did some dark magic to enable HTTP/2 and it was faster, but still, it takes me 15-20 seconds on an empty cache and that's not a good user experience. Nextcloud feels "heavy and slow", not the experience we like to expose to users. It makes it harder to sell the idea to replace proprietary solutions with Nextcloud if it feels really slow. Still, I agree that this can't be merged if applications breaks, that is a worse user experience. If I understood this correctly most breakage is because libraries, like JQuery, are buggy with defer. I assume that will be fixed in the future. In the future I think defer should be enabled (even if nice things like #3988 succeeds to limit the requests). Defer is a standard way to do things and it will speed up the user expertise for everyone. Maybe enable it by default in Nextcloud 13, 14 or 15, ... Suggestion |
I applied this a few seconds ago, on my NextCloud 11.0.1 behind HTTP/2 server. I know, this is a useless comment, but I think congrats should be written sometimes. |
I'm still using it on my productive system. |
No problems in current master anymore. :-) |
Update: Current master still working with almost all apps enabled. :) Loading file app, 130 js requests (208 total): |
Even with concatenation, this would provide a speed improvement by allowing the browser to load the rest of the images and markup while downloading the single script file. Concatenation is definitely welcome, but deferring loading seems like a good thing to have. If the worry is making things |
Still fully operational with current master and all apps except ownBackup - but ownBackup does not work either. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does anyone know if this applies to version 12? Or do these only apply to version 11 of Nextcloud server?
@lawtechsupport See #4854, in Nextcloud 13 there is a patch included which enables deferred script loading. 😉 But you also can have it earlier: wget https://patch-diff.githubusercontent.com/raw/nextcloud/server/pull/4854.patch -O/tmp/deferred-script-loading.patch
cd /your/nextcloud/document/root
patch -p1 < /tmp/deferred-script-loading.patch |
Slightly improved version of #3656
Problem before this PR:
<script>
loading was performed asynchronously, loading 50-100 external js scripts an executing them sequentially was slow.Example:
Full reload of "Files" app with almost all AddOns activated lasts 12.1 sec, loading 125 external .js.
Full discussion: #2272
Fix provided by this PR:
Script loading is done deferred with
<script defer>
.That means:
Modifications:
Templates:
Placed loading of all external resources close together without any interruption by inline script or other code. The inline script code is placed last in the document - but will be executed first(!) because all other external script are deferred (see above).
Unnecessary
type=
has been removed from inline<script>
template.php:
<script>
tags injected by AddOns take the 'defer' attributes here, but only whensrc
attribute is present, otherwisedefer
is not allowed.<script defer>
:https://www.w3schools.com/tags/att_script_defer.asp
https://developer.mozilla.org/de/docs/Web/HTML/Element/script
https://varvy.com/pagespeed/defer-loading-javascript.html
http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html
http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/
https://www.html5rocks.com/en/tutorials/speed/script-loading/
New behavior:
Full (re)loading of NC webpages is now 3-10 times faster, depending on link latency and the underlying protocol (http1, http2) .
When using http2 (or http1 pipelining...) huge amounts of external resource should not be a problem any more.
=> Full reload of "Files" app with almost all AddOns activated now lasts 2.3 sec, loading 125 external .js.
Possible drawback of this solution:
IE<=9 does not support
defer
properly, order of execution is NOT guaranteed. This may cause problems with script dependencies!