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
Add spinner to be shown before content is completely rendered #590
Conversation
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.
- This spinner is shown briefly on every page load - will this be annoying to the user?
A good way to lessen the annoyance to the user would be:
- To show the spinner only after the loading has taken more than a second.
- To not fade out when the loading is complete (i.e. remove the fading, regardless of how long it is loading).
- CSS for the spinner is taken from https://www.w3schools.com/howto/howto_css_loader.asp - do we need to attribute this in the source code?
Bootstrap already has their own spinner. Please use that one instead. Thanks!
asset/css/markbind.css
Outdated
background: white; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; |
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.
Attributes should be listed in the alphabetical order.
asset/js/setup.js
Outdated
@@ -33,10 +33,15 @@ function setupAnchors() { | |||
}); | |||
} | |||
|
|||
function fadeOutSpinner() { | |||
jQuery('#spinner-overlay').fadeOut(100); |
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.
As stated earlier, this should be .remove()
rather than fade out, to make it more pleasant for the user to navigate.
src/Page.js
Outdated
|
||
Page.prototype.insertSpinner = function (pageData) { | ||
return `${pageData}\n${SPINNER_HTML}`; | ||
}; |
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.
The addition of the spinner need not be done through code, because the HTML content is always going to be the same.
Please add the spinner directly inside page.ejs
instead.
Thanks for tackling this issue @marvinchin As @yamgent the current implementation somehow gives the impression that the website is 'slow'. The main factor is there is a blank page (and a spinner) shown for a while; other websites don't usually do that. Although this solution was suggested by me, now I wonder if the current status quo (i.e., showing partial content) is actually better than the solution (w.r.t. user perception)? The main problem with the current status is that the partially rendered menus look ugly/broken. Is there a way to fix that instead so that the partial rendering doesn't look so bad? |
The main cause of the unstyled content appears to be waiting for the vue and vue-strap files to load. This delay is more prominent in dev environment as we aren't doing compression or caching (if this is where the original observation came from, this may be the reason). The delay doesn't seem too visible to me in production. Users on a slow network might still face this problem. If this is a concern, we could take the approach suggested by @yamgent and show the spinner only if the assets have not been loaded after 1 second. Happy to further discuss how else we can tackle this problem, or if we should handle it at all! |
It depends on the site I think. e.g., this always show a broken page briefly when loading for the first time https://nus-cs2103-ay1819s2.github.io/cs2103-website/ |
That's true, first loads might always face this issue as the scripts aren't cached locally yet. Do you have any thoughts about showing the spinner only after loading for some time then? We should also hide the content until it is fully rendered. This should avoid the user seeing the unstyled content without showing the spinner unless loading is taking too long. |
Try viewing a different page using the |
We can add temporary classes to the components, before vue-strap finishes loading and starts to replace the components with actual implementations. In the case of a $('navbar').addClass('navbar navbar-expand-md fixed-top'); |
Do you think we should hide the content entirely until the required assets are done loading? Or is there some other way we should style them? Transitioning from temporary styles to the fully rendered styles may look strange otherwise. On the note of reducing the time taken to fully render the page, I've taken a closer look at the CS2103 website, and it seems like rendering is blocked until |
We can add on top of the styles I have mentioned with I think it is fine to not hide the words, since the user will still be allowed to get a basic sense of the website's content, regardless of whether the style has finished rendering or not. When I visit websites, things that appear "hidden", only to show up later, are usually always ads. :P |
Noted, will make a separate PR for these changes! Thanks for the inputs! 🙂 |
0c191cd
to
4c9afce
Compare
src/template/page.ejs
Outdated
<link rel="stylesheet" href="<%- asset.bootstrapVue %>"> | ||
<link rel="stylesheet" href="<%- asset.fontAwesome %>" > | ||
<link rel="stylesheet" href="<%- asset.glyphicons %>" > | ||
<link rel="stylesheet" href="<%- asset.highlight %>"> |
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.
These should not be moved to the bottom:
- The convention is to put stylesheets at the head.
- Authors may need to override the stylesheets, and they currently do that by adding additional stylesheets in head. Moving it to the bottom prevents them from overriding the stylesheets.
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.
The reason I moved them to the bottom is to reduce the time taken to start showing the spinner. Otherwise, we have to wait for the other much larger assets to load before the spinner is shown. On slower connections this delay can be several seconds.
If this issue is not a concern, I will remove these changes!
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.
The main bottleneck of the loading process is vue-strap and bulky/embedded page content and assets (e.g. youtube videos). Stylesheets themselves are fine and do not usually take up most of the loading time.
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.
Will remove these changes!
src/template/page.ejs
Outdated
<link rel="stylesheet" href="<%- asset.markbind %>"> | ||
<link rel="stylesheet" href="<%- asset.layoutStyle %>"> | ||
<% if (siteNav) { %><link rel="stylesheet" href="<%- asset.siteNavCss %>"><% } %> |
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 comment as previous
3355782
to
d7f63cc
Compare
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.
My apologies, I missed this PR because I didn't realise that it has been updated.
Thanks for looking at it! Also, just to update - @damithc wants to compare the difference in perceived load times between showing the spinner vs just showing the semi-rendered page. If showing the spinner makes the page load look slower, we may choose not include this feature. I'll keep you posted once he has decided whether or not to go ahead with this! |
@damithc has given the go ahead to include this. Thanks everyone for looking at this! |
Does this mean the website will "forever be loading" if Javascript is disabled? Not sure how I feel about that, the SE-EDU website currently works without Javascript so it'll be sad if the learning resources page can't be viewed just because the reader has javascript disabled :-/ |
@yamgent I believe we spoke about this and the decision was that we can assume our users use JavaScript. Do you think this use case is something we should account for? If it is, we can modify the CSS and use some inline JavaScript to show this spinner only to users with JavaScript enabled. |
afaik usually server side rendering is used to deal with the FOUC problem.
|
Vue, a major framework used by MarkBind, is using JavaScript. Website visitors can be assumed to be using JavaScript. If the concern is that users with JavaScript disabled do not know why the web page is blank, we can add a warning message on the overlay to ask the user to enable JavaScript. |
No, the concern is that this unnecessarily handicaps MarkBind and prevents it from being used in websites that do not need any of the flashy Javascript-required features. https://vuepress.vuejs.org/ doesn't need the reader to have Javascript, why should MarkBind? |
If supporting users who have javascript disabled is a concern, we may also need to think about how to make the other parts of the site work without javascript (e.g. dropdowns and search). In the meantime, we could make the overlay and spinner visible only on browsers with javascript enabled to avoid having the page be entirely unusable for these users using the approach I suggested above. Alternatively, if we don't foresee this enhancement bringing much value to users we could just shelve it for now. SSR might be a possible approach to avoid FOUC, but I think that may require further investigation on how to integrate it into MarkBind. However, I'm not sure where that lies in the current priorities for the 2.0 release. Just my $0.02! |
Yes, you are right in that we can be more gentle to website that generally do not rely on dynamic content or dynamic features that MarkBind provides.
Thanks for mentioning the vuepress project. I checked their project and I think their idea of using Vue as a server-side rendering, rather than client-side rendering, is pretty nice since it allows them to reduce their reliance on JavaScript to purely just dynamic features. This is certainty an idea we can consider exploring in the future, so that Vue and vue-strap no longer need to be bundled together with MarkBind websites.
Pardon me for forgetting if we discuss this before, but if we do it in this order, the un-rendered content will flash for a second before the overlay is enabled right? I don't think that will look very nice to the user.
Thanks for offering to shelve the enhancement, if we indeed end up doing so, do check with Prof to see if you can claim credit for the work you have done for this PR. For the issue of the partial rendering temporary "breaking" the website, you can still consider the method that I have suggested earlier to make the website less ugly:
|
It's worth investigating, especially if it can solve the FOUC probem, which is a pretty serious problem as it affect adoption. |
Sure, that seems like a reasonable start. @marvinchin interested? |
Sure, I could look at that and hopefully have something up by this/next week! Also, I've updated the PR to only show the loading overlay for users with javascript enabled, without having the flash of content before the spinner is shown (thanks @yamgent for pointing me in the right direction). |
@marvinchin there is a merge conflict with this PR, would need you to resolve it, thanks! |
813ec6c
to
1098687
Compare
4bd8215
to
68bebb1
Compare
68bebb1
to
6ac5c1c
Compare
@yamgent fixed! |
What is the purpose of this pull request? (put "X" next to an item, remove the rest)
• [x] New feature
Resolves #484
What is the rationale for this request?
Time taken for the page to render causes flash of unstyled content. To avoid having the user see the partially rendered page, we instead show a spinner until content is ready.
What changes did you make? (Give an overview)
fadeOutSpinner
tosetup.js
to remove the overlay when the page is done renderingExample of spinner being shown (slow!)
Is there anything you'd like reviewers to focus on?
Testing instructions:
Load any page. The spinner should appear while the page is rendering, and fade out when the page is done rendering.