Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ResizeObserver + polyfill as alternative to element-resize-detector #156

Open
nickschot opened this issue Mar 28, 2020 · 5 comments
Open

Comments

@nickschot
Copy link

I've noticed the element-resize-detector is quite a huge library for what it does. Were using the native ResizeObserver + a polyfill like https://www.npmjs.com/package/resize-observer-polyfill (2.44kB gzipped) considered? Seems like it would work just as well and save many KB. The polyfill could even be loaded conditionally based on ember's config/targets.js feature.

image

@lukemelia
Copy link

Sounds like a great idea. I came across this addon when looking for a ResizeObserver-based modifier -- that was my expectation of how this problem would likely be solved.

@ijlee2
Copy link

ijlee2 commented Jun 3, 2020

I'd like to see how well a modifier based on ResizeObserver works too. :)

My application is for ember-container-query, whereby O(10¹) resizes can happen at the same time (not just 1 or 2 resizes). I'm interested to see if ResizeObserver performs as well as (or better than) what element-resize-detector did.

@nickschot
Copy link
Author

So I looked into this a bit and found out a couple of things while tinkering with a ResizeObserver proof of concept for this addon:

  1. The native ResizeObserver has no "don't run on insertion" type implementation, has to be worked around manually by ignoring the first call (no big deal here).
  2. It is most performant to use a single ResizeObserver for the entire app. See: https://groups.google.com/a/chromium.org/g/blink-dev/c/z6ienONUb5A/m/F5-VcUZtBAAJ?pli=1 The problem with this is that you cannot distinguish between multiple modifiers on the same element. We'd have to do some manual bookkeeping here to know when to actually unobserve the element.
  3. ResizeObserver passes the callback a ResizeObserverEntry by default with some pretty useful information including the new sizes of the element. In many use cases of this modifier it would be very beneficial to also provide this information through this modifier instead of just the element as it saves on layout calculations (i.e. having to call getBoundingClientRect manually in the callback forces another layout calculation). I'd prefer to simply pass the ResizeObserverEntry as the only argument, but that would be a breaking change.

Thoughts are welcome!

@voltidev
Copy link

voltidev commented Jun 22, 2020

I built ember-resize-observer-service to solve exactly the problem with multiple ResizeObserver instances. Feel free to use it to migrate this addon to ResizeObserver API, if it makes sense.

Building a size-responsive modifier with it is pretty straight forward:

export default class OnResizeModifier extends Modifier {
  @service resizeObserver;

  didInstall() {
    this.resizeObserver.observe(this.element, this.handleResize);
  }

  willRemove() {
    this.resizeObserver.unobserve(this.element, this.handleResize);
  }

  @action
  handleResize(...args) {
    let [callback] = this.args.positional;
    callback(...args);
  }
}

@nickschot If you need a complete ResizeObserver based solution with a single instance optimization, I built ember-on-resize-modifier.

And in case if you need a polyfill:

ember install ember-resize-observer-polyfill

@nickschot
Copy link
Author

If it already exists it makes sense to migrate to that addon in my opinion. As far is I can see (after a very quick peek) the main feature difference is that your addon also runs on insert. For my use cases that doesn’t matter though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants