shinsenter / defer.js

🥇 A lightweight JavaScript library that helps you lazy load (almost) anything. Defer.js is dependency-free, highly efficient, and optimized for Web Vitals.
https://shinsenter.github.io/defer.js/
MIT License
277 stars 45 forks source link

Adding a way to programmatically load JS and CSS using conditions #108

Closed DahmaniAdame closed 2 years ago

DahmaniAdame commented 2 years ago

Is your feature request related to a problem? Please describe. It would be great if we could control when a JS or CSS exits from deferring.

For example, loading a script only when clicking on a specific button. Or after scrolling down the page or starting typing.

Describe the solution you'd like A 4th parameter similar to [observeOptions] but with more freedom to hook it to a specific logic using a function to be added.

Describe alternatives you've considered Manually wrapping scripts inside the specific logic. But it will be tedious modification work to do. An automated way that can be managed through a function linked to defer.js would be great :)

Additional context N/A

shinsenter commented 2 years ago

@DahmaniAdame Thank you for your suggestion.

The purpose of the Defer.js library aims to help your site improve the speed when a webpage IS RENDERING (which affects score that you get from some site speed test tools).

Helper function like Defer.dom is just an additional feature for helping your site defer the load of resources, thereby helping your servers save bandwidth and it may help your users save their billed cellular data.

Regarding your idea, after careful consideration, I realize that it is not the main goal that the library is aiming for.

You can easily achieve what you wanted by using the addEventListener method of the browser, or using jQuery, then you may combine with Defer.js to lazyload JS, CSS files when there is user interaction. However, triggering loading resources on user interactions can bring poor user experiences to the user.

You may try these examples (with jQuery):

$('button.my-button').on('click', function() {
    Defer.js('//third-party-library/script.js', 'script-id');
});
$('input.my-input').on('input', function() {
    Defer.js('//third-party-library/script.js', 'script-id');
});
shinsenter commented 2 years ago

@DahmaniAdame By the way, I would like to tell that I am recreating the examples of using this library to more practical use cases. Please wait until v3.0 comes out.

If you love this library, please give me a star or recommend it to your friends. It would be appreciated.

DahmaniAdame commented 2 years ago

@shinsenter thank you for having a look :)

The purpose of the Defer.js library aims to help your site improve the speed when a webpage IS RENDERING (which affects score that you get from some site speed test tools).

Stopping the execution until specific conditions are met will benefit the user experience (no noisy scripts executed if they shouldn't) and have an even greater impact on testing tools ;)

That's the foundation of plugins like WP Meteor or Flying Scripts or WP Rocket's Delay JS feature :)

I realize that it is not the main goal that the library is aiming for.

I totally get that. But it doesn't hurt to extend it to something that will benefit performance :)

But I will understand if it's not something you will be interested in implementing. I just feel like it will be a shame to miss that!

I would like to tell that I am recreating the examples of using this library to more practical use cases.

That would be great! Looking forward to checking 3.0 👍

If you love this library, please give me a star or recommend it to your friends. It would be appreciated.

Star added ;) sharing my thoughts about it whenever I can ;)

Keep up the good work!

shinsenter commented 2 years ago

@DahmaniAdame Sorry I haven't had much time to go through the plugins you're recommending (btw, I remember that I have got an offer to collaborate from one of the owners of those plugins).

Regarding lazyloading resources when a certain tag appears on the page, I think you can also use the Defer.dom function.

I have a few examples as follows, hope you have more suggestions.

Lazy load AddThis add-on when any div with class="demo-addthis" appears.

<div class="demo-addthis addthis_inline_share_toolbox"></div>

<script>
    var addthis_loaded = false;
    Defer.dom('.demo-addthis', 500, '', function() {
        if (!addthis_loaded) {
            Defer.js('https://s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5c68e61cf456f1cb', 'addthis-js');
            addthis_loaded = true;
        }
    });
</script>

Lazy load Prism.js library when any pre>code block appears.

<pre><code class="language-html"><!-- Your HTML snippet --></code></pre>

<script>
    // turns on manual mode
    window.Prism = window.Prism || {};
    Prism.manual = true;

    // inits code tags using Defer.dom()
    Defer.dom('pre code', 100, 'ide-loaded', function() {
        var self = this;

        if (Prism.highlightElement) {
            Prism.highlightElement(self);
        } else {
            // this script will lazy load Prism.js library and its dark theme.
            // when loading done, Defer.dom init code formatting to every <code> tags.
            var origin = 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.28.0';
            Defer.css(origin + '/themes/prism-tomorrow.min.css', 'prism-css');
            Defer.js(origin + '/prism.min.js', 'prism-js', 0, function () {
                Prism.highlightElement(self);
            });
        }
    }, {rootMargin: "150%"});
</script>

Run a script when a div with id="surprise-me" appears.

<div id="surprise-me">Hello DahmaniAdame</div>

<script>
    Defer.dom('#surprise-me', 1000, 'seen', function(node) {
        alert('Yay!\n\nYou have seen all examples.\nHave fun coding with @shinsenter/defer.js!');
    });
</script>

By the way, thank you for giving this library one star.

shinsenter commented 2 years ago

@DahmaniAdame Delaying the load of scripts and stylesheets will be available in v3.0 (#106).

DahmaniAdame commented 2 years ago

Thank you for considering that, @shinsenter 🙏 Looking forward to v3.0

shinsenter commented 2 years ago

@DahmaniAdame It is appreciated for any idea contributing to source code. 😄 BTW, I also need helps with improving readability of the documentation, all suggestions are welcome!

shinsenter commented 2 years ago

@DahmaniAdame v3.0.0 has been released. Please take a look. You can archive the feature that you requested by setting Defer.lazy to true.

<script>/* the script tag containing defer.min.js is here */</script>
<script>
    Defer.lazy = true;
</script>