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

issue with fetch while using adapter-cloudflare-workers #1674

Closed
bhvngt opened this issue Jun 11, 2021 · 8 comments
Closed

issue with fetch while using adapter-cloudflare-workers #1674

bhvngt opened this issue Jun 11, 2021 · 8 comments

Comments

@bhvngt
Copy link

bhvngt commented Jun 11, 2021

Describe the bug
I am using supabase-js with sveltekit and cloudflare-workers. While using adapter-cloudflare-workers, I get hit with following issue when I do wrangler dev.

Uncaught
ReferenceError: require is not defined
    at node_modules/node-fetch/lib/index.js (worker.js:59:18)
    at __require (worker.js:9:44)
    at node_modules/cross-fetch/dist/node-ponyfill.js (worker.js:1099:21)
    at __require (worker.js:9:44)
    at node_modules/@supabase/gotrue-js/dist/main/lib/fetch.js (worker.js:1152:41)
    at __require (worker.js:9:44)
    at node_modules/@supabase/gotrue-js/dist/main/GoTrueApi.js (worker.js:1442:19)
    at __require (worker.js:9:44)
    at node_modules/@supabase/gotrue-js/dist/main/index.js (worker.js:2149:39)
    at __require (worker.js:9:44)

This issue happens because supabase-js is using cross-fetch as its fetch-polyfill. I found a workaround by applying following patches

  • changing platform from node to browser in the esbuild options inside adapter-cloudflare-worker.
  • patching cross-fetch to export native fetch for browser polyfill.

node may have been chosen as a platform of choice for esbuild, since cloudflare has started supporting node libraries for its workers platform.

However, cloudflare provides a hybrid of browser(service-worker) and node environment with native fetch support. Hence, if I keep node as a platform, then I face issues with browser's native object such as fetch, websocket that are also available under cloudflare's service-worker environment.

I have couple of questions here

  • Would it make sense to change the platform from node to browser. This will essentially conform to intrinsic nature of service-worker environment supporting many of the browser's native objects.
  • Is there a way to customise esbuild options used for a given adapter?
  • As per esbuild team, to override any external dependency, one way is to write a custom plugin such as esbuild-plugin-external-global. Is there a way to pass custom plugin or 3rd party plugin to esbuild config used during adapter build?

Logs

I have provided the error logs in my issue above

To Reproduce
Here's a sample repo.

supabase url + apikey and cloudflare account_id + zone_id will be required to reproduce issue

Expected behavior

cloudflare-worker adapter should allow options to customise esbuild so that third party libraries using cross-fetch can be integrated to cloudflare environment.

Stacktraces
If you have a stack trace to include, we recommend putting inside a <details> block for the sake of the thread's readability:

Stack trace
Uncaught
ReferenceError: require is not defined
    at node_modules/node-fetch/lib/index.js (worker.js:59:18)
    at __require (worker.js:9:44)
    at node_modules/cross-fetch/dist/node-ponyfill.js (worker.js:1099:21)
    at __require (worker.js:9:44)
    at node_modules/@supabase/gotrue-js/dist/main/lib/fetch.js (worker.js:1152:41)
    at __require (worker.js:9:44)
    at node_modules/@supabase/gotrue-js/dist/main/GoTrueApi.js (worker.js:1442:19)
    at __require (worker.js:9:44)
    at node_modules/@supabase/gotrue-js/dist/main/index.js (worker.js:2149:39)
    at __require (worker.js:9:44)

Information about your SvelteKit Installation:

Diagnostics
System:
    OS: macOS 11.4
    CPU: (4) x64 Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz
    Memory: 21.73 MB / 16.00 GB
    Shell: 3.2.1 - /usr/local/bin/fish
  Binaries:
    Node: 16.3.0 - ~/.local/share/nvm/v16.3.0/bin/node
    npm: 7.15.1 - ~/.local/share/nvm/v16.3.0/bin/npm
  Browsers:
    Chrome: 91.0.4472.101
    Chrome Canary: 93.0.4539.0
    Edge: 91.0.864.41
    Firefox: 86.0.1
    Safari: 14.1.1
  npmPackages:
    @sveltejs/kit: next => 1.0.0-next.114
    svelte: ^3.34.0 => 3.38.2

Severity
This is hampering me from running supabase together with sveltekit on cloudflare. I believe that this issues goes beyond supabase. If not supabase, many other libraries use cross-fetch to access their apis. Hence, they may potentially face this issue.

Additional context

@benmccann
Copy link
Member

Would it make sense to change the platform from node to browser?

I haven't used Cloudflare workers, so am not sure. Perhaps @halfnelson would know more. I think the issue I'd be most worried about is getting packages that expect things like document to be defined

Is there a way to customise esbuild options used for a given adapter?

The options are set on a per-adapter basis. Right now they're hardcoded, but I would imagine that the platform should be constant, so that's fine

platform: 'node' // TODO would be great if we could generate ESM and use type = "javascript"

@bhvngt
Copy link
Author

bhvngt commented Jun 12, 2021

Thanks @benmccann. I understand the need for keeping the platform value constant. I too am new with cloudflare and would love to hear from @halfnelson about his thoughts.

What I have learned so far is that polyfills such as node-fetch, websocket etc. requires node libraries such as http, stream etc. Cloudflare workers environment does not provide any of those libraries. It is not a node environment. It works more like a service-worker bubble on a server. Having said that, you do have a valid point regarding document

Again @halfnelson may be a better person to clarify this understanding.

@halfnelson
Copy link
Contributor

The original version didn't do any bundling and relied on cloudflare to do the webpack build. Although I am not sure what impacts changing esbuild platform from node -> browser would have, I am not sure browser is the right choice. Cloudflare themselves are trying to support a more "node" like environment while having browser as the default could drag in modules assuming the presence of window, document etc.

There is a third option called "neutral" although I am not sure that helps

@halfnelson
Copy link
Contributor

looking at it, cross-fetch should import the global fetch, but it looks like it has been temporarily disabled:
https://github.com/lquixada/cross-fetch/blob/main/rollup.config.js#L49

@halfnelson
Copy link
Contributor

related issues on their repo
lquixada/cross-fetch#69
lquixada/cross-fetch#78

@bhvngt
Copy link
Author

bhvngt commented Jun 13, 2021

Thanks @halfnelson.

lquixada/cross-fetch#78 occurs when cross-fetch picks up browser based build browser-ponyfill. It did not occur in my case since it picked up node-ponyfill. Hence these two issues are slightly different. This is the same case for https://github.com/lquixada/cross-fetch/blob/main/rollup.config.js#L49

Like what is done in lquixada/cross-fetch#69, even if I override "cross-fetch", I start facing issues with other browser native object/classes such as websocket. So with "node" platform we may have to override couple of this objects.

I get your concern related to window and document object. But with node, similar issues occurs with built-in node modules such as http, url, stream etc. In case of window and document, it will probably error out like what it is currently doing with node built-ins. But thats probably how cloudflare-workers was meant to function. It seems to me that cloudflare workers are browser-type sandbox running on a server. Hence not sure if they will ever support node built-ins. You will be a better judge here though.

platform=neutral seems to build esm build with no externalisation. So in that case, the build may try to bundle all the built-in node modules, which may not work with cloudflare environment.

As per their doc, platform=browser seems to also bundle up commonjs modules.

@The-Noah
Copy link
Contributor

This fixed it for me:

{
  fetch: (...args) => fetch(...args),
}

Source: supabase/postgrest-js#235

@Rich-Harris
Copy link
Member

Closing since there's a viable workaround. Hopefully libraries will stop bundling things like cross-fetch, now that more and more runtimes expose it natively

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

No branches or pull requests

5 participants