banner
Jason

Jason的碎碎念

Jason的碎碎念
github

Service Workers First Screen Optimization

Note

This article assumes you already know how to use sw to accelerate your website.

Introduction#

Recently, I started using the sw acceleration scheme by the great CYF. I have used three different sw acceleration solutions developed by different authors, but due to the complexity of CYF's code (I'm not very skilled), I opted for the code by the great Yfun to ensure the webpage is updated on the front end.

Why Optimize the First Screen#

While using CYF's solution, I discovered CYF's first screen optimization plan.

In fact, the most significant drawback of ServiceWorker is that it needs to be installed on the first load of the webpage and requires a refresh to activate. In other words, the first visit by a visitor is not controlled by sw. In other words, the first screen is not accelerated, and its loading speed is directly related to your server [although it takes off after installation, it’s slow before installation].

Even more frustrating is that during the first screen loading, static resources are fetched directly and not cached, while after sw activation, a second fetch is forced, slowing down the speed. However, we can minimize this disadvantage as much as possible. We can use JS to interrupt all requests to ensure that only one HTML and one sw.js are loaded for the first screen, preventing other resources from loading and reducing the first screen loading delay.

So I tried using CYF's first screen optimization, and who doesn't love a stylish sw installation page?

I have used two styles of first screen optimization, and I will share them here.

Solution 1 (by cyfan)#

<!-- sw front-end racing -->
<script>
(async () => {// Use an anonymous function to ensure the body is loaded
    /*
    QYBlogHelper_Set is stored in LocalStorage to indicate the sw installation status
    0 or does not exist - Not installed
    1 - Interrupted
    2 - Installed
    3 - Activated and necessary files are cached (not detailed here, no need to care)
    */
    if ('serviceWorker' in navigator) { // If sw is supported
        if (Number(window.localStorage.getItem('QYBlogHelper_Set')) < 1) {
            setTimeout(async () => {
                console.log('Detected that your browser has not installed QYBlogHelper, starting registration')
                window.stop()
                window.localStorage.setItem('QYBlogHelper_Set', 1)
                const replacehtml = await fetch('https://npm.elemecdn.com/chenyfan-blog@1.0.13/public/notice.html')
                document.body.innerHTML = await replacehtml.text()
                $('#info').innerText = 'Trying to install QYBlogHelper...';
            }, 0);
        }
        const $ = document.querySelector.bind(document);// Syntactic sugar
        navigator.serviceWorker.register(`/sw.js?time=${new Date().getTime()}`)// Random number, force update
            .then(async () => {
                if (Number(window.localStorage.getItem('QYBlogHelper_Set')) < 2) {
                    setTimeout(() => {
                        $('#info').innerText = 'Installation successful, please wait a moment...';
                    }, 0);
                    setTimeout(() => {
                        window.localStorage.setItem('QYBlogHelper_Set', 2)
                        console.log('Preparing to redirect')
                        window.location.reload()// Refresh to load sw
                    }, 500)// Wait 500ms after installation to activate
                }
            })
            .catch(err => console.error(`QYBlogHelperError:${err}`))
    } else {
        setTimeout(() => {
            $('#info').innerText = 'Sorry, we no longer support your browser.';
        }, 0);
    }
})()
</script>

Solution 2 (by yfun)#

<!-- sw front-end racing -->
<script>
(async () => {// Use an anonymous function to ensure the body is loaded
    /*
    QYBlogHelper_Set is stored in LocalStorage to indicate the sw installation status
    0 or does not exist - Not installed
    1 - Interrupted
    2 - Installed
    3 - Activated and necessary files are cached (not detailed here, no need to care)
    */
    if ('serviceWorker' in navigator) { // If sw is supported
        if (Number(window.localStorage.getItem('QYBlogHelper_Set')) < 1) {
            setTimeout(async () => {
                console.log('Detected that your browser has not installed QYBlogHelper, starting registration')
                window.stop()
                window.localStorage.setItem('QYBlogHelper_Set', 1)
                const replacehtml = await fetch('https://npm.elemecdn.com/qycdn@0.9.13/html/swinstall.html')
                document.body.innerHTML = await replacehtml.text()
            }, 0);
        }
        const $ = document.querySelector.bind(document);// Syntactic sugar
        navigator.serviceWorker.register(`/sw.js?time=${new Date().getTime()}`)// Random number, force update
            .then(async () => {
                if (Number(window.localStorage.getItem('QYBlogHelper_Set')) < 2) {
                    setTimeout(() => {
                        window.localStorage.setItem('QYBlogHelper_Set', 2)
                        console.log('Preparing to redirect')
                        window.location.reload()// Refresh to load sw
                    }, 500)// Wait 500ms after installation to activate
                }
            })
            .catch(err => console.error(`QYBlogHelperError:${err}`))
    } else {
        setTimeout(() => {
            console.log('Sorry, we no longer support your browser');
        }, 0);
    }
})()
</script>

Notes#

Warning

We try to move the interruption code to the <head> to ensure it is not blocked by other resources. For Hexo, open the theme's head.ejs and add it near the top of the <head> tag; otherwise, it may not achieve the desired acceleration effect.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.