supabase / realtime-js

An isomorphic Javascript client for Supabase Realtime server.
https://supabase.com
MIT License
324 stars 58 forks source link

Build breaks with React Native starting from 2.9.0 #272

Closed piccinnigius closed 11 months ago

piccinnigius commented 11 months ago

Bug report

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

Additional context

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

w3b6x9 commented 11 months ago

@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.

piccinnigius commented 11 months ago

@w3b6x9 thanks for replying.

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

w3b6x9 commented 11 months ago

@piccinnigius which react native version are you on?

piccinnigius commented 11 months ago

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

w3b6x9 commented 11 months ago

@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?

piccinnigius commented 11 months ago

@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

w3b6x9 commented 11 months ago

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

piccinnigius commented 11 months ago

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

piccinnigius commented 11 months ago

@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.

w3b6x9 commented 11 months ago

@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.