filestack / filestack-js

Official Javascript SDK for the Filestack API and content ingestion system.
https://www.filestack.com
MIT License
206 stars 76 forks source link

Vite and rollup browser error when importing library #458

Closed taylorthurlow closed 2 years ago

taylorthurlow commented 3 years ago

I'm getting what looks like the symptom of a circular dependency when loading the ESM module in a browser.

Expected Behavior

Running the following code should import the ES module and not throw an error.

import * as filestack from "filestack-js";

Current Behavior

Running the following code:

import * as filestack from "filestack-js";

Raises the following error in the browser console:

Uncaught TypeError: Object prototype may only be an Object or null: undefined
    at setPrototypeOf (<anonymous>)
    at __extends (tslib.es6.js:25)
    at http.ts:43
    at node_modules/filestack-js/build/module/lib/request/adapters/http.js (http.ts:64)
    at __init (filestack-js.js?v=7b23504f:14)
    at request_adapter.node.ts:17

The problem is the usage of Stream.Writable when defining a class in http.ts. Stream.Writable is undefined. This would appear to be due to a circular dependency that rollup cannot resolve, but I'm not really sure.

Steps to Reproduce (for bugs)

Reproduction repo is https://github.com/taylorthurlow/filestack-rollup-repro - simple instructions can be found in the README. You will need ruby installed, I used Ruby 2.7. 2.5 and 2.6 should also be fine. This repo is basically a completely unmodified Rails application. The commit history is extremely short and shows what little I need to do to get this to happen.

Additional Screenshots

Screen Shot 2021-08-26 at 5 57 28 PM

Context

I'm just trying to use the library with Vite, which uses rollup under the hood.

Your Environment

taylorthurlow commented 3 years ago

I'm going to see if I can set up an all-javascript reproduction repo but I have no experience with JS-only web dev.

taylorthurlow commented 3 years ago

I fundamentally misunderstood how Vite works in development (it doesn't bundle at all, I believe it transpiles with esbuild) - so this issue wouldn't be specific to rollup. In fact, rollup is not being used at all in this reproduction. I'm continuing to investigate.

taylorthurlow commented 3 years ago

Ok after an entire day of learning more than I expected to about the insanity that is the JS ecosystem, I've come to the conclusion is that this is due to the fact that webpack v4 historically has automatically polyfilled a lot of nodeJS libraries. This is no longer the case with webpack v5, and never has been the case with rollup.

filestack-js makes heavy use of nodejs libraries and without the correct polyfills set up in the project, things will not work. I've made some small progress on this by configuring Vite/rollup to alias some package names like stream to stream-browserify and used the stream-browserify package to replace it. I did the same with the url package.

Now I'm running into an incompatibility with filestack-js's usage of lodash.clonedeep - I guess this is just a package which wraps cloneDeep for nodeJS. I assume this is another instance of the same problem where some polyfill/shim made things work before that doesn't work outside of webpack v4. My understanding is that this repo contains a list of polyfill replacements for some libraries.

I tried replacing the "nodejs-ified" (?) lodash.clonedeep using the same alias trick but because the exports are different I can't substitute it in a way that makes filestack-js happy. It ends up importing the module instead of the function itself.

I'm giving up for tonight, but I'd like to take this opportunity to ask the maintainers here what the level of compatibility is expected to be with bundlers like rollup, and especially webpack v5 as it gains traction - is the polyfilling just something the end user should expect to have to deal with?

paultuckey commented 2 years ago

@taylorthurlow I was able to work around this same issue by importing the built esm directly:

import * as filestack from 'filestack-js/build/browser/filestack.esm';
taylorthurlow commented 2 years ago

@paultuckey Ah man I can't believe I didn't try that. Thanks for the heads up.

csellis commented 2 years ago

@taylorthurlow I was able to work around this same issue by importing the built esm directly:

import * as filestack from 'filestack-js/build/browser/filestack.esm';

Brilliant. Works for me.

MCYouks commented 2 years ago

Brillant! Works for me too, thanks 👍

csellis commented 2 years ago

This stopped working for me now

tcampbPPU commented 2 years ago

@taylorthurlow I was able to work around this same issue by importing the built esm directly:

import * as filestack from 'filestack-js/build/browser/filestack.esm';

Thanks! The fix I was looking for