2

I am trying to optimize an OpenCart website speed. Unfortunately non of the extensions did any good, so I decided to do everything manually.

I am optimizing the css files for example :

<link href="catalog/view/javascript/jquery/magnific/magnific-popup.css" type="text/css" rel="stylesheet" media="nope!" onload="this.media='all'">

This is working perfectly fine for me, since I build a preloader that waits for all the css to be loaded and then show my page. In that case PageSpeed is happy and I'm happy.

The problem is that the preloader basically works :

     <script>
        document.onreadystatechange = function() {
            if (document.readyState !== "complete") {
                document.querySelector(
                  "body").style.visibility = "hidden";
                document.querySelector(
                  "#loader").style.visibility = "visible";
            } else {
                document.querySelector(
                  "#loader").style.display = "none";
                document.querySelector(
                  "body").style.visibility = "visible";
            }
        };
    </script>

This way every time I open the page it shows the loader, and I want to show it only the first time / while the page is still rendering and showing pure html due the the blocking of the css /.

So I am wondering if there is a way to do that..

Thanks in advance!

milen
  • 73
  • 8
  • https://stackoverflow.com/questions/10537039/how-to-determine-if-css-has-been-loaded – aravind Jan 31 '20 at 11:22
  • @aravind sorry this isn't really answering my question, this just tells if css is loaded or not / every time it refreshes / I need something that helps me realise a preloader if the files are cached/not. – milen Jan 31 '20 at 11:41
  • Even if your css is cached it still needs to be loaded, have you tried measuring how long the loader is 'on' for with and without the cached file? – Florian Humblot Jan 31 '20 at 13:11
  • @FMashiro this is a really good idea, however when I'm trying to get the execution time https://prnt.sc/qvlzb8 like that, it pretty much gets me same results, when I put it inside the function it's not measuring it at all.. – milen Jan 31 '20 at 13:25
  • Are you sure you've cleared the cache correctly between the loads? Because it looks like either your CSS isn't getting cached correctly or that you are doing your "before/after" measurements without clearing the cache (so both measurements would be with cache) – Florian Humblot Jan 31 '20 at 13:26
  • If you're using Google Chrome, you can open the developer tools (F12), go to "Network" and check the box that says 'Disable cache' on your development page. – Florian Humblot Jan 31 '20 at 13:27
  • I'm using Safari but i've just tried with chrome : https://prnt.sc/qvm3dp so first triy is on cleared cache, then next 2 are on cached version, and then next 2 are on cleared cache, but it's pretty similar, and I don't think it's measuring it correctly, because I'm checking the time on my phone and on cached version it tooks between 1-2 seconds, and on cleared cache it tooks between 2-4 seconds.. – milen Jan 31 '20 at 13:31
  • @milen , why do you bother if it is cached or not. If a css file is loaded then hide your "loader". If browser caches your css file then your "loader" will be visible for 1 sec . If it is not cached then your "loader" is visible for 3 sec (based on bandwidth). I personally feel, we should not bother about browsers caching, If you really need custom caching logic , you should look at https://developer.mozilla.org/en-US/docs/Web/API/Cache – aravind Jan 31 '20 at 16:06
  • @aravind I am only afraid that I will ruin the user experience, if they always see loader / even for 1sec or a milisec / when they click through the site on every page... that's why I wanted to avoid that, but I guess there is not a solution for that.. – milen Feb 01 '20 at 17:03

3 Answers3

0

You can use interactive state instead of complete. It works when the DOM is built, but additional resources are still loading. Full code:

switch (document.readyState) {
  case "loading":
    document.querySelector("body").style.visibility = "hidden";
    document.querySelector("#loader").style.visibility = "visible";
    break;
  case "interactive":
  case "complete":
    document.querySelector("body").style.visibility = "visible";
    document.querySelector("#loader").style.visibility = "hidden";
    break;
}
Alexander
  • 1,220
  • 6
  • 12
  • thanks for the suggestion, but unfortunately with the interactive state it breaks the page, after the loader is hidden the page gets blanked, and still shows the loader every time I click refresh... – milen Jan 31 '20 at 11:12
  • @milen you need to change your condition. *else* will trigger by complete and loading. – Alexander Jan 31 '20 at 11:17
  • hmm it's still the same result -> https://prnt.sc/qvjq8m here is how I changed it, after the loader I'm seeing the content for a millisecond and then everything is white – milen Jan 31 '20 at 11:22
  • @milen Because triggered event 'complete' by else case. Then you speak in your code: "hide my document". – Alexander Jan 31 '20 at 11:25
  • makes sense, I've added elseif condition for the complete state, but I still have the loader when I switch through pages or refresh .. – milen Jan 31 '20 at 11:27
  • yes, I've tried with it but then I am always seeing the loader and it doesn't go away... – milen Jan 31 '20 at 11:33
0

You can go 3 ways: 1. Use Cookie 2. Use localStorage 3. Use sessionStorage

I would recommend you use sessionStorage or localStorage, 1st for security reasons, and 2nd = cookies are slowly going away.

To use sessionStorage you can do something like this:

//set sessionStorage
if (!sessionStorage.alreadybeenthere) {

    document.onreadystatechange = function() {
        if (document.readyState !== "complete") {
            document.querySelector(
                "body").style.visibility = "hidden";
            document.querySelector(
                "#loader").style.visibility = "visible";
        } else {
            document.querySelector(
                "#loader").style.display = "none";
            document.querySelector(
                "body").style.visibility = "visible";
        }
    };

    sessionStorage.alreadybeenthere = 1;

    console.log(Loader_executed)
}
else {
    console.log(Loader_not_executing)
}

You can experiment with localStorage if you are sure the users browser is set to keep browser cache.

More info can be found here: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage

0

I would use Workbox to build a service worker to aggressively cache your assets and load them from the cache.

You can even check or pull items out of the cache as needed.

Jordan Cauley
  • 353
  • 1
  • 5