How to provide ECMAScript 5 (ES 5)-shim?

15,312

Solution 1

ES5-Shim will only shim parts that the browsers don't implement, so just give it to all browsers. It'll handle the detection of what needs to be shimmed and what doesn't.

But pay attention to the caveats listed on what shims don't work correctly in some instances. I've had issues with that in the past and it causes a ton of pain until you realize the answer was super simple...

Solution 2

This seems to work for me:

<!--[if lt IE 9]><script src="java/es5-shim.min.js"></script><![endif]-->

Solution 3

At present, the solution that works best with ES5-Shim is to use the library in all environments and allow it to detect which features it needs to patch at run-time. It would be even better to deliver it from a community CDN to maximize cross-site cache hits.

That being said, there is an open opportunity to create systems that combines feature detection, agent fingerprinting, and dynamic bundling to automatically generate and deliver targeted shim subsets. The scope of the problem extends far beyond just ES5-Shim and could be applied to all sorts of shims.

Share:
15,312
Šime Vidas
Author by

Šime Vidas

I write dailies for the "Open Web Platform Daily Digest" at webplatformdaily.org. E-mail: [email protected] Twitter: http://twitter.com/simevidas

Updated on June 07, 2022

Comments

  • Šime Vidas
    Šime Vidas about 2 years

    ECMAScript Fifth Edition (released December 2009) introduces a bunch of new methods (see this table for details). However, there still are older browsers out there which do not implement those new methods.

    Luckily, there exists a convenient script (written in JavaScript) - ES5-shim - which implements those methods manually in environments where they don't exist.

    However, I am not sure how to provide ES5-shim... Should I just "give" it to all browsers, like so:

    <script src="es5-shim.js"></scipt>
    

    Or should I include a check in order to only "bother" those browsers which really need it, like so:

    <script>
        if ( !Function.prototype.hasOwnProperty( 'bind' ) ) {
            (function () {
                var shim = document.createElement( 'script' );
                shim.src = 'es5-shim.js';
                var script = document.getElementsByTagName( 'script' )[0];
                script.parentNode.insertBefore( shim, script );
            }());
        }
    </script>
    

    (I'm using Function.prototype.bind to check if a browser implements all new ECMAScript 5 methods. According to the compatibility table which I linked above, bind is the "last bastion" when it comes to implementing ECMAScript 5 methods.)

    Of course, for this shim to be effective, it has to be executed before all other scripts, which means that we want to include the above mentioned SCRIPT elements early in the page (in the HEAD, before all other SCRIPT elements).

    So, would this second example be a good way to provide ECMAScript 5-shim to browsers? Is there a better way to do it?

  • Šime Vidas
    Šime Vidas over 12 years
    But that would force ES5-compatible browsers (latest IE, Chrome, Firefox, soon Opera) to download and execute the shim which slows down the web-page unnecessarily. If I can avoid this with a little JavaScript check, I'll gladly do it.
  • You
    You over 12 years
    @ŠimeVidas: It's 8kB. With proper caching, that's nothing to worry about.
  • JaredMcAteer
    JaredMcAteer over 12 years
    The performance hit is negligible, the ES5 Shim already does what it can to avoid unnecessary code execution.
  • Šime Vidas
    Šime Vidas over 12 years
    @OriginalSyn I don't worry about the execution of the shim. It's the unnecessary HTTP-request which bothers me. The idea of forcing all browsers to make this request... (especially since the share of fully compatible browsers increases constantly)
  • epascarello
    epascarello over 12 years
    8k can be a big hit depending on your platform.
  • JaredMcAteer
    JaredMcAteer over 12 years
    As @You said, it's 8kb (before gzip compression) and easily cache-able. If the extra HTTP request is really a problem combine it with your main script.
  • tkone
    tkone over 12 years
    @epascarello really? 8k can be a big hit? That is 6 seconds on a 9600baud MODEM. The file is 4k when gzipped. That's 3 seconds. What platform is 8k a big hit?
  • epascarello
    epascarello over 12 years
    Ks add up and if I am on my mobile with crappy reception, I do not need extra bytes. It is one http hit that is not needed. It also requires browsers to look it up, see if it cached, process it, execute code. It is not minimal. Modern day browsers are better at this.
  • tkone
    tkone over 12 years
    @epascarello you're right. Modern day browsers are better than this. But if you're trying to support older browers, you have to do something. The issue is that Chrome, Safari, Firefox and IE9 all have varying support for the ES5 feature set, so aside from testing for ALL features (which is going to add 1k to the size, you'd have to do user-agent & version detection and maintain this to keep track of the insane Chrome & Firefox release schedule. If the extra HTTP hit is really bothersome, inline it and save yourself the hit. Your mobile network is still much faster than a 9600 baud modem
  • PeterToTheThird
    PeterToTheThird almost 11 years
    If you're concerned about the extra HTTP request, simply compress and combine your JS scripts into one (or a few) files. In a production system, you should be doing this anyway to minimize HTTP calls.
  • Bergi
    Bergi almost 11 years
    What about the non-IE browsers that are not supporting ES5?
  • gen_Eric
    gen_Eric almost 11 years
    @Bergi: I don't think those actually exist.
  • Bergi
    Bergi almost 11 years
    @RocketHazmat: I suppose you mean "those are barely used", but they exist for sure. Take pre-ES5 versions of the popular browsers, or some embedded or mobile browsers.
  • Eugene Kuzmenko
    Eugene Kuzmenko almost 10 years
    @silversky: why is it in a "java" folder :) ?
  • Jon z
    Jon z over 8 years
    For reference, here's a compatibility table for ES5 kangax.github.io/compat-table/es5