简体   繁体   中英

Grunt usemin not working after optimizations for Pagespeed

I recently did some optimizations to improve the score of the application I'm working on (AngularJS) in the Pagespeed tool from the Google webmaster tools.

Specifically, Google was asking to "Eliminate render-blocking JavaScript and CSS in above-the-fold content". So I removed the declarations and moved them into a script that loads when the page finishes loading, so I went from:

<link rel="stylesheet" href="/bundles/vendor.css"/>
<link rel="stylesheet" href="/bundles/common.css"/>
<script src="/bundles/vendor.bundle.js"></script>

to this:

    <script type="text/javascript">
    function downloadJSAtOnload() {

        var stylesheet1 = document.createElement('link');
        stylesheet1.href = "https://fonts.googleapis.com/css?family=Poppins";
        stylesheet1.rel = 'stylesheet';
        stylesheet1.type = 'text/css';
        document.getElementsByTagName('head')[0].appendChild(stylesheet1);

        var stylesheet2 = document.createElement('link');
        stylesheet2.href = "/bundles/vendor.css";
        stylesheet2.rel = 'stylesheet';
        stylesheet2.type = 'text/css';
        document.getElementsByTagName('head')[0].appendChild(stylesheet2);

        var stylesheet3 = document.createElement('link');
        stylesheet3.href = "/bundles/common.css";
        stylesheet3.rel = 'stylesheet';
        stylesheet3.type = 'text/css';
        document.getElementsByTagName('head')[0].appendChild(stylesheet3);

        var element1 = document.createElement("script");
        element1.src = "/bundles/common.bundle.js";
        document.body.appendChild(element1);

    }
    if (window.addEventListener)
        window.addEventListener("load", downloadJSAtOnload, false);
    else if (window.attachEvent)
        window.attachEvent("onload", downloadJSAtOnload);
    else window.onload = downloadJSAtOnload;
</script>

at the bottom of the body element.

It worked great and improved my score a lot, but, it caused problems with the distribution.

We use grunt for building the assets, we do the usual uglify, minify, etc. We call the filerev grunt task to generate a cache buster version id in the asset files, and then we call usemin to replace the references of the original asset files for the ones with the version number to bust the cache.

The problem is that usemin only acts on elements with a src element, and because of the way I'm loading these assets now, it keeps the reference to the original asset name. This means I would have to manually change it after the build during releases, which is not acceptable.

So I'm looking for ways to make it work or alternatives but no luck so far.

In my opinion, you should not be doing this in the first place.

You're loading all of your CSS after your HTML has been loaded and rendered on the page. This means you will almost certainly have a flash of unstyled content . To prevent this from happening, your styles should be intially loaded in your <head>

Note that window.onload waits for your document's window to be ready for presentation, meaning all external resources have been loaded. If you have images on the page for example, your CSS and JS will not be loaded until all of your images have been loaded. This is most likely longer than you should be waiting to load your JS.

Since <script> tags block the building of the DOM (since it needs to execute that JS), a better approach could be to use the async or defer attributes so you can still add the <script> tag to the end of your <body> but it will not prevent your page from being rendered.

There is such a thing as over-optimizing. Is getting a better Pagespeed score worth degrading your user experience? That's up to you to determine, but I tend to learn towards "no" :)

Well, finally I was able to solve this. I used the filerev-apply grunt plugin which is applied to all string, not just those inside script elements with src properties as usemin seems to be doing.

It worked great

I use grunt with aliases, so this is the filerev_apply.js task file:

module.exports = function(grunt, options) {
    return {
        dist: {
            files: [{
                '<%= dist %>/index.html': '<%= dist %>/index.html',
            }]
        }
    };
};

Call it after filerev and you are done.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM