tauri-apps / tauri

Build smaller, faster, and more secure desktop and mobile applications with a web frontend.
https://tauri.app
Apache License 2.0
82.63k stars 2.48k forks source link

[feat] Support HTTP client in web worker #3308

Open iSplasher opened 2 years ago

iSplasher commented 2 years ago

Describe the problem

I wasn't sure whether to list this as a bug or not, but I'm not able to use fetch from @tauri-apps/api/http in web workers. Considering that the browser native fetch supports web workers, I would expect the same here.

Describe the solution you'd like

I would like to use fetch in web workers.

Alternatives considered

I guess an alternative would be to delegate the fetching to the main thread, but this isn't really ideal and requires boilerplate.

Additional context

This is the specific error I'm getting in the browser.

tauri.ts:29 

Uncaught (in promise) ReferenceError: window is not defined
    at uid (tauri.ts:29:3)
    at transformCallback (tauri.ts:54:6)
    at tauri.ts:88:12
    at new Promise (<anonymous>)
    at Object.<anonymous> (tauri.ts:86:40)
    at step (spelling.086f3e36.js?1643473028886:10130:23)
    at Object.next (spelling.086f3e36.js?1643473028886:10071:20)
    at spelling.086f3e36.js?1643473028886:10056:71
    at new Promise (<anonymous>)
    at __awaiter (spelling.086f3e36.js?1643473028886:10038:12)
JonasKruckenberg commented 2 years ago

This won't happen anytime soon, since it's more complex than "@tauri-apps/api/http to webworkers". Let me explain:

As you probably already know tauri uses the operating systems webview to render to UI. This means when the app starts up we hand your HTML/CSS/JS over to the webview to be displayed. The crucial problem is the controls a webview exposes are very limited. For example you can give a function to the webview that can be called from the frontend (the underpinning of our IPC system), but how and when the frontend can actually call that function is wholly up to the discretion of the webview.

In practice the webview injects window.chrome.webview.postMessage (on windows window.webkit.messageHandlers.ipc.postMessage on macos) into the Javascript scope where it sees fit and for whatever reason webview libraries decided to not inject that into the scope of webworkers 🤷‍♂️

Now don't despair though, we have plans to improve on the current situation and solve this problem, but those plans will not become reality for v1.

jorbuedo commented 2 years ago

This is quite unfortunate and affects not only the fetch function :( I was trying to use the tauri-plugin-sql-api in a web worker and it failed because of the undefined window. I hope it can be addressed at some point, otherwise workers are basically unusable on tauri.

evbo commented 2 years ago

@jorbuedo do you think webworkers are unusuable in Tauri period or only unusuable when calling Tauri API's?

jorbuedo commented 2 years ago

@evbo Since you can't call Tauri API, can't fetch and still are restricted to the usual worker limitations... yes, they are unusable. They technically work, so if you had a very isolated task with no IO or state persistence, you could send it from the main thread, compute there, and send result back. But that's about it.

evbo commented 2 years ago

@jorbuedo so then maybe I'll open a new issue? It seems this particular issue concerned with the Tauri fetch API specifically..

But you (and I) probably are both noticing that any sort of web worker requested by any sort of JS library isn't working, period. Do you agree with that statement?

If so, I think this is a huge issue for the specific use-case where someone is trying to take an existing website and plop it into a Tauri app with minimal boilerplate Rust backend. I love Rust, but there are times when you just need to take an already working design and lift it into a desktop platform.

So confirm my suspicion? There's simply no way to do any JS in a separate thread without writing a custom Rust command?

jorbuedo commented 2 years ago

@evbo As far as I tried in June, that's correct. I decided to spin up a Nodejs sidecar and rpc everything from main thread to it to bypass Rust.

evbo commented 2 years ago

@jorbuedo I think it's a similar limitation in Electron... From what I'm reading, Electron comes built-in with a nodejs runtime, so it essentially skips the step of creating a sidecar by always providing you one by default... But that means you need to still do the work in the backend.

So... actually... I'm boggled how anyone could possible solve this issue.. Do you know of any examples of how this is successfully handled elsewhere?

jorbuedo commented 2 years ago

Electron comes with a full browser though, so web workers should work fine there if the intention is to easily port a a webapp to the desktop.

evbo commented 2 years ago

@JonasKruckenberg Really glad Tauri is going to support this more. I was going to file a separate issue and still could, but do you prefer this existing feature request be the catchall for web worker compatibility with any/all JS libraries executing in the webview (Tauri API or otherwise)?

Also, maybe consider documenting this limitation? It is a serious limitation for those of us migrating existing websites where we don't have as much flexibility to rewrite them into calling the Rust backend to get async processing.

JonasKruckenberg commented 2 years ago

@JonasKruckenberg Really glad Tauri is going to support this more. I was going to file a separate issue and still could, but do you prefer this existing feature request be the catchall for web worker compatibility with any/all JS libraries executing in the webview (Tauri API or otherwise)?

If you have any specific issues with web workers (the fact that they don't seem to work at all for you) you should file separate issues for that.

Also, maybe consider documenting this limitation?

Last time I checked this myself web workers worked fine, so maybe this is an issue with a specific platform/situation? We should do some more research on this, but then it'd be a good idea to document yes!

bukowa commented 4 months ago

Since V2 is already in beta, does anyone have any information on whether anything has changed?

FabianLars commented 4 months ago

No relevant changes in v2 yet.

david-mkl commented 3 months ago

A workaround that I tried was to create a new hidden window and run background tasks there. That way you still have access to window (and the Tauri APIs). For example in tauri.conf.json

{
    "windows": [
      {
        "url": "index.html",
        "label": "main"
        // ...
      },
      {
        "url": "index.worker.html",
        "label": "worker",
        "visible": false,
        "focus": false,
        "fullscreen": false,
        "minimizable": false,
        "maximizable": false,
        "hiddenTitle": true,
        "width": 0,
        "height": 0
      }
    ]
}

Then I can emit events to the "worker" window. It seems to work really well (at least on macos), but I'm also not sure if I'm misusing Tauri in some way by doing this 🤔