In this talk, we’re going to discuss polyfills and their role in moving the web forward. We’ll also talk about how Chrome thinks about the maintenance and scalability of polyfills. This deck builds on many previous articles and share-outs by others.
piece of JavaScript code that is intended to exactly simulate a native, interoperable feature of the web platform, for the purpose of allowing website developers to use modern web features in older browsers. Polyfilling the web forward
syntax that older browsers won’t understand (e.g. classes, ‘const’, arrow functions), and transforms them into syntax they will understand (functions, ‘var’, functions). Polyfilling the web forward
out to canary/dev request beta approval request stable approval enable by default identify + understand design write it down ship standard intent to implement enable by default intent to ship if web-facing if failed intent to deprecate intent to remove remove adoption check-in landed web platform launch chrome launch web platform removal first TAG check-in external blink contributors old/existing features (2nd impl ships) final TAG sign-off grow + iterate intent to experiment if need to experiment chromium intent to implement Life of a browser feature
principles for Web features Discuss & Design Idea discussion and Incubation. The first step is identifying a specific need, or use case. An Explainer may be written at this phase. Implement First native implementations (as trial/behind flag). Specification should be iterated on. Web Platform Tests. Interop Multiple interoperable implementations across browsers. Universal support Stable support for the feature across all major browsers and platforms. Polyfills bridge this gap
are developing a new feature for the web, polyfills can be hugely beneficial in helping to roll out that feature. • Don't be constrained by what is 'polyfillable' [discuss?] • Make your feature easily detectable • Work with polyfill authors Polyfills and the evolution of the Web Platform
151851850485185200000 ❌ 1234567890123456789n * 123n; // → 151851850485185185047n ✅ // Originally, BigInt was only supported in Chrome. // Hard to transpile to ES5 with Babel et al. Changes behavior of operators (like +, >= etc).
and polyfills can’t do everything. • A good general rule is this: ◦ If it’s new syntax, you can probably transpile it ◦ If it’s a new object or method, you can probably polyfill it ◦ If it’s something clever that the browser does outside of your code, you may be out of luck.
generally better to optimize for modern browsers, so performing efficient client-side feature detection and waiting for an extra script to load on older browsers is usually a good trade off. However, if the full set of polyfills you might need in the worst case constitutes a negligible overhead, then you could choose to serve the full set to all browsers. • Polyfill authors may choose to throw a warning if a polyfill is loaded when not needed, though care should be taken not to create unnecessary noise. If unnecessarily loading a particular polyfill creates a significant performance or security concern, a warning is appropriate.
a service that inspects the browser’s User-Agent and serves a script with polyfills targeted specifically at that browser. ◦ The polyfill.io script will add 50-300 ms to your Time to Interactive. The script is (obviously) hosted on a server different from yours, and loading stuff from a different server is costly. The browser will have to spend extra 50-300 ms to setup a connection to the server, and this means adding 50-300 ms to your Time to Interactive. • module/nomodule is a pattern when you serve scripts for modern browsers with <script type="module">, and scripts for older browsers with <script nomodule>: ◦ This pattern relies on the fact that old browsers – ones that don’t support ES2015 – will not load type="module" scripts – and will load nomodule ones. Which means you can use nomodule to serve ES2015 polyfills exactly to browsers that need them! • @babel/preset-env has an option called useBuiltIns. With this option, you can make Babel cherry-pick polyfills for specific browsers
<script nomodule src="/polyfills/full.min.js"></script> <!-- Smaller polyfill bundle for browsers with ES2015+ support --> <script type="module" src="/polyfills/modern.min.js"></script> <!-- Bundle script. `defer` is required to execute this script after the `type="module"` one --> <script src="/bundle.min.js" defer></script>
the standards process. However, any JavaScript library that defines a property of the global object or extends a prototype of a global constructor using a proposed or generically useful name, risks creating problems for the development of the Web if that library becomes widely used, prior to the standardization and implementation of the feature it seeks to create or emulate. • EXAMPLE: Mootools Array.prototype.contains => .includes ◦ The standardization of Array.prototype.contains in JavaScript ran into problems. • Polyfill authors can avoid these problems if their version of the feature can be used under a custom name, regardless of the existence of any native implementation of the same or similar feature under a different name.
runtime nature of more complex polyfills can sometimes mean their performance in browsers is significantly different to browsers that natively support a feature, so this is always worth keeping an eye on. • Historically, developers used solutions like Modernizr and Yepnope to conditionally load polyfills in supported browsers, while in modern times developers often take a lighter weight approach to checking (or defer to configuration steps like present-env and conditional polyfill loading to handle such checks for them). • As the number of web platform features increases, the amount of polyfill code required to make website developers' application code run in older browsers may become extremely large - in some cases exceeding the size of the application code that depends on it. This has implications for performance, both in terms of parsing the polyfill code, and the time required to download it. • Consideration should be given to whether excessively large polyfill bundles place a punitive cost burden on users with the least ability to pay that cost: those with older devices which may be on metered connections paying for data in very small increments.
Comprehensive test suite, especially if it includes relevant Web Platform Tests • Effects on the performance profile of your site, measured using in-browser profiling tools or other auditing or monitoring tools or services Additional recommendations for polyfill authors Understand stability Some features are not worth polyfilling. Instead, consider: • Progressive enhancement • Transpilation (eg. Babel) • Lo-fi mode (aka. "Basic" mode, "m." etc) Consider the least capable devices
deciding whether to ship polyfill-like code inside your library, you should consider questions such as: ◦ How much of the feature are you using? If you want a large feature but your use of it could be emulated in naive 10-line implementation, then it's better to do that than to bundle a spec-compliant polyfill. ◦ How large is the polyfill code relative to your library code? If it's a tiny polyfill (such as for a Number.isNaN implementation) then the overheads are negligible and not worth any concern. However, in some cases a polyfill might exceed the size of the library. ◦ Are there multiple polyfills available? If developers have a choice of polyfills for this feature, you may want to choose the one that works best with your library. If there's only one canonical option, it's easier to assume that the developer will use it. ◦ Does your library provide a good experience only when the feature is available natively? If a polyfill allows your library to work but in an unacceptably slow or buggy way, it probably should not ship as part of the library. Polyfills and the evolution of the Web Platform
by Remy Sharp • Polyfills and the evolution of the Web Platform was influential. • Polyfills are a part of the web • Inspiration for the term replica: The Eiffel Tower in Las Vegas • Useful clarification of “polyfill” and related terms: “Polyfills and the evolution of the Web”. Edited by Andrew Betts. • Polyfills, shims and Ponyfills