juggle / resize-observer

Polyfills the ResizeObserver API.
https://juggle.studio/resize-observer
Apache License 2.0
964 stars 46 forks source link

Added Rollup, ESM and CJS builds #89

Closed Mike-Dax closed 4 years ago

Mike-Dax commented 4 years ago

This should close #82.

This maintains a default export and a named export of ResizeObserver, but provides both ESM and CJS versions.

Bundlers should detect the __esModule property and this shouldn't be a breaking change.

TremayneChrist commented 4 years ago

Hey @Mike-Dax thanks for this! Will try and test this as soon as I can.

TremayneChrist commented 4 years ago

Hi @Mike-Dax I appreciate there probably isn't a breaking change here, as no one can currently use a CJS version, however, I have problems with the inconsistencies between imports for CJS and ESM.

Default exports:

import ResizeObserver from '@juggle/resize-observer'; // works
const ResizeObserver = require('@juggle/resize-observer'); // broken
const ResizeObserver = require('@juggle/resize-observer').default; // undesirable

Named exports:

import { ResizeObserver } from '@juggle/resize-observer'; // works
const { ResizeObserver } = require('@juggle/resize-observer'); // works
const ResizeObserver = require('@juggle/resize-observer').ResizeObserver; // undesirable

V3 will only provide named exports, as the ResizeObserver specification expects both ResizeObserver and ResizeObserverEntry to be available publicly.

Mike-Dax commented 4 years ago

Hi @TremayneChrist.

Yes this is the issue, CJS only has a singular exports property, so you can't have both a 'default' (by setting module.exports = ResizeObserver) and also named exports (setting module.exports = { ResizeObserver }).

Default is in quotes because there's no such thing as a default property in CJS. Bundlers will assume a default property at the default key of the object export if using import syntax.

require() calls simply pass the exports object. (You can set the exports object to be the class or function you're exporting).


As a side note

const { ResizeObserver } = require('@juggle/resize-observer'); // works
const ResizeObserver = require('@juggle/resize-observer').ResizeObserver; // undesirable

These are identical, in the former you're just doing a destructuring assignment.


A hacky method would be to export ResizeObserver with module.exports = ResizeObserver (once transpiled), then set a named property of ResizeObserver on ResizeObserver to itself.

Essentially this:


function Thing() {}

Thing.Thing = Thing

export default Thing

It would mean these would all work.

const { ResizeObserver } = require('@juggle/resize-observer');
const ResizeObserver = require('@juggle/resize-observer');
const ResizeObserver = require('@juggle/resize-observer').ResizeObserver;
const ResizeObserver = require('@juggle/resize-observer').ResizeObserver.ResizeObserver.ResizeObserver.ResizeObserver.ResizeObserver.ResizeObserver.ResizeObserver.ResizeObserver; // circular references!

I wouldn't recommend that though, again it's quite a code smell.

TremayneChrist commented 4 years ago

Yep, very smelly 😄 I think it's best to leave this for now and push it into the next major. I've just pushed a prerelease if you fancy giving it a try.

TremayneChrist commented 4 years ago

Hi @Mike-Dax this has been fixed in v3.0.0