w3c / IntersectionObserver

Intersection Observer
https://www.w3.org/TR/intersection-observer/
Other
3.62k stars 523 forks source link

Is there a way to ponyfill IntersectionObserver? #393

Closed mreinstein closed 5 years ago

mreinstein commented 5 years ago

hello!

My software runs as a 3rd party library that is included on other people's websites. One of the requirements they impose is I can't modify global objects in the browser. I would like to be able to do something like this:

import Observer from 'intersection-observer';

const instance = new Observer(callback, options);
// in ie, window.IntersectionObserver === undefined at this point

Is this possible?

philipwalton commented 5 years ago

In general, I don't think 3rd party libraries should be embedding this polyfill. Ideally, third-party libraries should indicate which APIs are required for them to work, and then they should include installation instructions explaining how to add polyfills for the required APIs if wider browser support is needed.

The problem with including a polyfill in a 3rd party library is you could easily imagine a situation in which a site that loads lots of third-party widgets end up including the same polyfill several times.

I understand that this raises the barrier to adoption for lots of widgets, but I do think it's the best approach for polyfills.

As for the ponyfill approach, the issues goes into a bit of the history as to why that wasn't used here (logic is conditionally added based on the browser's existing support).

mreinstein commented 5 years ago

Ideally, third-party libraries should indicate which APIs are required for them to work, and then they should include installation instructions explaining how to add polyfills for the required APIs if wider browser support is needed.

We're talking about different audiences for 3rd party. In my case, I'm not shipping code that other developers integrate with at a low level. I have a bundle of javascript that runs on very large retail websites. Walmart, Costco, Lowes, Staples, and more. They all require ie 10+ support and they all integrate by dropping a javascript tag from us onto their page. The sites vary wildly from each other as you might imagine. There's no standard polyfill system available across any of them.

The problem with including a polyfill in a 3rd party library is you could easily imagine a situation in which a site that loads lots of third-party widgets end up including the same polyfill several times.

I can appreciate the desire to reduce the number of duplicated bits. This is something we have to deal with every day. (many times we see multiples copies of jquery loaded on websites! yuck!)

A counter-point to consider: if the feature being polyfilled is half-baked, there is a lot of potential for killing website performance. This is especially true for features that tend to involve change detection in the dom.

If one has to choose between some duplicated bytes in polyfill libraries vs having multiple implementations with non-uniform behavior (or worse a really bad abuse of polling/mutation events/mutation observer internally in one of these that kills page performance) a lot of use cases would accept the duplication.

Of course this is a balancing act, if the intersection observer is above some size, then the cost of duplication isn't worth it (e.g., can't have a 1mb polyfill duplicated several times.)

Anyway, I don't expect this to be changed just for my particular use case, but just want to present an alternate viewpoint based on real-life usage.

Integration issues aside, thanks for a great polyfill by the way!

philipwalton commented 5 years ago

I understand. And size concerns aside, in many cases I'd be in favor of exposing both a ponyfill as well as a polyfill, but in this case it's not really possible since this polyfill gets conditionally applied and re-uses existing globals based on browser support—it's not just a 100%, self-contained module that can be imported/exported.

anilanar commented 4 years ago

There are use cases in which multiple iframes are used with multiple window objects involved. E.g. 1 iframe to isolate JS, another iframe that is controlled/rendered into by a JS iframe.

Userlike uses that approach. Intercom uses that approach. I've seen many more that are trying to use that approach. That's why many React libraries take a custom window object as a property.

That approach requires a ponyfill with window passed as a function argument to be able to use it with a different window than the current one.