supabase / realtime-js

An isomorphic Javascript client for Supabase Realtime server.

Home Page:https://supabase.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Build breaks with React Native starting from 2.9.0

piccinnigius opened this issue · comments

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

After "move from websocket to ws and support native browser WebSocket API" (#263) cannot build anymore in React Native (Webpack).
In particular ws module cannot find some libraries url,stream, etc. Adding Polyfills causes max call stack errors.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Init new project
  2. Try to compile

Expected behavior

Replacement of websocket to ws must not be a breaking change.

System information

  • OS: [ Windows]
  • Version of supabase-js: [latest]
  • Version of Node.js: [19.8.1]

Additional context

Same codebase, same build steps works as usual using @supabase/supabase-js 2.36.0 - realtime 2.8.4

@piccinnigius which version of realtime-js are you on when using supabase-js? this should be fixed in realtime-js v2.9.1. try upgrading supabase-js in your react native app.

@w3b6x9 thanks for replying.

I'm using latest supabasejs that comes with realtime v2.9.1 :/

@piccinnigius which react native version are you on?

@w3b6x9 I've been on 0.71.14 and to check if on newer versions works I've upgraded to 0.73.1

@piccinnigius that's odd b/c it's working fine for me. here are my setup steps:

  1. npx react-native@latest init TestProject (v0.73.1)
  2. npm install @supabase/supabase-js (v2.39.2) - confirmed that it's on realtime-js v0.29.1
  3. npm install react-native-url-polyfill and imported at the top of index.js - looks like this is a necessity b/c supabase-js is using URL
  4. Set up Supabase client, created and subscribed to channel

did you have the same steps? can you share exactly your setup and the output you're seeing?

@w3b6x9 i can confirm that usually works.
I think that part of the problem is related to using webpack on React Native.

In second hand we can refeer to ws readme that says:

Note: This module does not work in the browser. The client in the docs is a reference to a back end with the role of a client in the WebSocket communication. Browser clients must use the native WebSocket object. To make the same code work seamlessly on Node.js and the browser, you can use one of the many wrappers available on npm, like isomorphic-ws.

The real question is: why if in React Native Websocket is available and NATIVE_WEBSOCKET_AVAILABLE is true this section messing up resulting in using ws package?

Anyway this is the output:

Details

Cannot apply update due to error: {"loc": "1:287-302", "message": "Module not found: Error: Can't resolve 'zlib' in 'D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "zlib": require.resolve("browserify-zlib") }'
- install 'browserify-zlib'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "zlib": false }", "moduleIdentifier": "D:\testPrj\apps\react-native\node_modules\babel-loader\lib\index.js!D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib\permessage-deflate.js", "moduleName": "../../packages/native-shared/node_modules/@supabase/realtime-js/node_modules/ws/lib/permessage-deflate.js"}
x [16:37:08.169Z][Console] Cannot apply update due to error: {"loc": "1:1311-1328", "message": "Module not found: Error: Can't resolve 'stream' in 'D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib'
Did you mean './stream'?
Requests that should resolve in the current directory need to start with './'.
Requests that start with a name are treated as module requests and resolve within module directories (node_modules).
If changing the source code is not an option there is also a resolve options called 'preferRelative' which tries to resolve these kind of requests in the current directory too.

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "stream": require.resolve("stream-browserify") }'
- install 'stream-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "stream": false }", "moduleIdentifier": "D:\testPrj\apps\react-native\node_modules\babel-loader\lib\index.js!D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib\receiver.js", "moduleName": "../../packages/native-shared/node_modules/@supabase/realtime-js/node_modules/ws/lib/receiver.js"}
x [16:37:08.175Z][Console] Cannot apply update due to error: {"loc": "1:459-476", "message": "Module not found: Error: Can't resolve 'stream' in 'D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib'
Did you mean './stream'?
Requests that should resolve in the current directory need to start with './'.
Requests that start with a name are treated as module requests and resolve within module directories (node_modules).
If changing the source code is not an option there is also a resolve options called 'preferRelative' which tries to resolve these kind of requests in the current directory too.

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "stream": require.resolve("stream-browserify") }'
- install 'stream-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "stream": false }", "moduleIdentifier": "D:\testPrj\apps\react-native\node_modules\babel-loader\lib\index.js!D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib\sender.js", "moduleName": "../../packages/native-shared/node_modules/@supabase/realtime-js/node_modules/ws/lib/sender.js"}
x [16:37:08.187Z][Console] Cannot apply update due to error: {"loc": "1:514-531", "message": "Module not found: Error: Can't resolve 'crypto' in 'D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "crypto": require.resolve("crypto-browserify") }'
- install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "crypto": false }", "moduleIdentifier": "D:\testPrj\apps\react-native\node_modules\babel-loader\lib\index.js!D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib\sender.js", "moduleName": "../../packages/native-shared/node_modules/@supabase/realtime-js/node_modules/ws/lib/sender.js"}
x [16:37:08.187Z][Console] Cannot apply update due to error: {"loc": "1:26-43", "message": "Module not found: Error: Can't resolve 'stream' in 'D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib'
Did you mean './stream'?
Requests that should resolve in the current directory need to start with './'.
Requests that start with a name are treated as module requests and resolve within module directories (node_modules).
If changing the source code is not an option there is also a resolve options called 'preferRelative' which tries to resolve these kind of requests in the current directory too.

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "stream": require.resolve("stream-browserify") }'
- install 'stream-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "stream": false }", "moduleIdentifier": "D:\testPrj\apps\react-native\node_modules\babel-loader\lib\index.js!D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib\stream.js", "moduleName": "../../packages/native-shared/node_modules/@supabase/realtime-js/node_modules/ws/lib/stream.js"}
x [16:37:08.188Z][Console] Cannot apply update due to error: {"loc": "1:1619-1634", "message": "Module not found: Error: Can't resolve 'http' in 'D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "http": require.resolve("stream-http") }'
- install 'stream-http'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "http": false }", "moduleIdentifier": "D:\testPrj\apps\react-native\node_modules\babel-loader\lib\index.js!D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib\websocket-server.js", "moduleName": "../../packages/native-shared/node_modules/@supabase/realtime-js/node_modules/ws/lib/websocket-server.js"}
x [16:37:08.189Z][Console] Cannot apply update due to error: {"loc": "1:1648-1665", "message": "Module not found: Error: Can't resolve 'stream' in 'D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib'
Did you mean './stream'?
Requests that should resolve in the current directory need to start with './'.
Requests that start with a name are treated as module requests and resolve within module directories (node_modules).
If changing the source code is not an option there is also a resolve options called 'preferRelative' which tries to resolve these kind of requests in the current directory too.

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "stream": require.resolve("stream-browserify") }'
- install 'stream-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "stream": false }", "moduleIdentifier": "D:\testPrj\apps\react-native\node_modules\babel-loader\lib\index.js!D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib\websocket-server.js", "moduleName": "../../packages/native-shared/node_modules/@supabase/realtime-js/node_modules/ws/lib/websocket-server.js"}
x [16:37:08.191Z][Console] Cannot apply update due to error: {"loc": "1:1703-1720", "message": "Module not found: Error: Can't resolve 'crypto' in 'D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "crypto": require.resolve("crypto-browserify") }'
- install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "crypto": false }", "moduleIdentifier": "D:\testPrj\apps\react-native\node_modules\babel-loader\lib\index.js!D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib\websocket-server.js", "moduleName": "../../packages/native-shared/node_modules/@supabase/realtime-js/node_modules/ws/lib/websocket-server.js"}
x [16:37:08.194Z][Console] Cannot apply update due to error: {"loc": "1:1721-1737", "message": "Module not found: Error: Can't resolve 'https' in 'D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "https": require.resolve("https-browserify") }'
- install 'https-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "https": false }", "moduleIdentifier": "D:\testPrj\apps\react-native\node_modules\babel-loader\lib\index.js!D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib\websocket.js", "moduleName": "../../packages/native-shared/node_modules/@supabase/realtime-js/node_modules/ws/lib/websocket.js"}
x [16:37:08.200Z][Console] Cannot apply update due to error: {"loc": "1:1747-1762", "message": "Module not found: Error: Can't resolve 'http' in 'D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "http": require.resolve("stream-http") }'
- install 'stream-http'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "http": false }", "moduleIdentifier": "D:\testPrj\apps\react-native\node_modules\babel-loader\lib\index.js!D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib\websocket.js", "moduleName": "../../packages/native-shared/node_modules/@supabase/realtime-js/node_modules/ws/lib/websocket.js"}
x [16:37:08.201Z][Console] Cannot apply update due to error: {"loc": "1:1771-1785", "message": "Module not found: Error: Can't resolve 'net' in 'D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\no
de_modules\ws\lib'", "moduleIdentifier": "D:\testPrj\apps\react-native\node_modules\babel-loader\lib\index.js!D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib\websocket.js", "moduleName": "../../packages/native-shared/node_modules/@supabase/realtime-js/node_modules/ws/lib/websocket.js"}
x [16:37:08.201Z][Console] Cannot apply update due to error: {"loc": "1:1794-1808", "message": "Module not found: Error: Can't resolve 'tls' in 'D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\no
de_modules\ws\lib'", "moduleIdentifier": "D:\testPrj\apps\react-native\node_modules\babel-loader\lib\index.js!D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib\websocket.js", "moduleName": "../../packages/native-shared/node_modules/@supabase/realtime-js/node_modules/ws/lib/websocket.js"}
x [16:37:08.204Z][Console] Cannot apply update due to error: {"loc": "1:1822-1839", "message": "Module not found: Error: Can't resolve 'crypto' in 'D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "crypto": require.resolve("crypto-browserify") }'
- install 'crypto-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "crypto": false }", "moduleIdentifier": "D:\testPrj\apps\react-native\node_modules\babel-loader\lib\index.js!D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib\websocket.js", "moduleName": "../../packages/native-shared/node_modules/@supabase/realtime-js/node_modules/ws/lib/websocket.js"}
x [16:37:08.252Z][Console] Cannot apply update due to error: {"loc": "1:1918-1935", "message": "Module not found: Error: Can't resolve 'stream' in 'D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib'
Did you mean './stream'?
Requests that should resolve in the current directory need to start with './'.
Requests that start with a name are treated as module requests and resolve within module directories (node_modules).
If changing the source code is not an option there is also a resolve options called 'preferRelative' which tries to resolve these kind of requests in the current directory too.

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "stream": require.resolve("stream-browserify") }'
- install 'stream-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "stream": false }", "moduleIdentifier": "D:\testPrj\apps\react-native\node_modules\babel-loader\lib\index.js!D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib\websocket.js", "moduleName": "../../packages/native-shared/node_modules/@supabase/realtime-js/node_modules/ws/lib/websocket.js"}
x [16:37:08.252Z][Console] Cannot apply update due to error: {"loc": "1:2002-2016", "message": "Module not found: Error: Can't resolve 'url' in 'D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.

If you want to include a polyfill, you need to:
- add a fallback 'resolve.fallback: { "url": require.resolve("url/") }'
- install 'url'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "url": false }", "moduleIdentifier": "D:\testPrj\apps\react-native\node_modules\babel-loader\lib\index.js!D:\testPrj\packages\native-shared\node_modules\@supabase\realtime-js\node_modules\ws\lib\websocket.js", "moduleName": "../../packages/native-shared/node_modules/@supabase/realtime-js/node_modules/ws/lib/websocket.js"}

Thanks in advance

@piccinnigius have you tried polyfill-ing all the modules listed in the error message?

@w3b6x9 yes, this results in maximum call stack exceeded error

@w3b6x9 I've fixed by marking ws as external in webpack configuration. Idk if something needs to be done on realtime-js side.

it works also by doing eval on the import but I think that it's a bit anti-pattern

Thanks for your help.

@piccinnigius nice, glad that marking it external got it working.

The real question is: why if in React Native Websocket is available and NATIVE_WEBSOCKET_AVAILABLE is true this section messing up resulting in using ws package?

i'm still wondering this that you pointed out. i'll look into this and see if i can come up with anything.