WordPress/wordpress-playground

[Browser] Support multiple browser tabs

adamziel opened this issue · 7 comments

What problem is this issue looking to solve?

In the browser, all the requests to WordPress are routed to a web worker by a service worker. The service worker handles the traffic for the entire domain, which means that all the open tabs are routing their WordPress requests via the same service worker.

Unfortunately, it passes them to all the running web workers instead of targeting specifically the one from the tab where the request originated. When five tabs are opened, five web workers handle all the requests, which causes all sorts of problems.

How does this issue proposes to solve it?

Find a way to route each request from service worker to only the specific web worker that initiated it. Somewhere around here:

https://github.com/adamziel/wordpress-wasm/blob/9d04a113a97f53a1303fefba642f65f1b5a5a5f6/src/web/service-worker.js#L31-L45

If there was a way to brand all requests from a specific tab somehow, that would be perfect. Perhaps each iframe could pretend to have a unique subdomain? Or each tab could attach a unique cookie or other http header to every request?

sessionStorage could be helpful here:

Data stored using sessionStorage do not persist across browser tabs, even if two tabs both contain webpages from the same domain origin

Another way of supporting multiple browser tabs would be running the same app instance across multiple tabs – kudos to @gziolo for the idea!

Edit: Let's track this one separately in #32

Surfacing this relevant comment here: #24

This StackOverflow answer offers some inspiration:
https://stackoverflow.com/questions/63848494/how-to-differ-regular-and-iframe-requests-through-a-service-worker
The service worker has access to self.clients and each client has a unique id and a frameType. There should be a way to only route requests coming from the client id associated with a specific iframe – this would also solve the multitab scenario.

Another way of supporting multiple browser tabs would be running the same app instance across multiple tabs – kudos to @gziolo for the idea!

This could be handled via a SharedWorker. Ideally WASM itself would run there, but it's currently blocked by a bug in Chrome – see #1. Another option would be to use SharedWorker as a traffic controller that elects one of the active tabs as a "leader" and uses it to resolve all the requests. I'm a bit worried how similar this is to distributed data synchronization problems.

A few ideas:

  • Require a catch-all domain like *.mysite.com where all subdomains point to the same directory on the same server and then load WordPress from a random subdomain in each browser tab. The downside is that such a setup is a huge barrier of entry.
  • Load a unique worker file in each browser tab, e.g. worker.js?tab_id=90871hjv189 or worker1.js and then interact only with that worker. The next opened tab would take the next available worker. The build process could even ship about 10 workers to cover the 90% use-case. User would have to be warned if the limit is exceeded. This won't work – you can only register one service worker per scope.
  • Initialize each WordPress on a random path, e.g. /tab-897/index.php, and either render just the requests related to the current tab's path, or register a service worker restricted to the /tab-897 scope.
  • Display an error in the second, third, etc tab.

Here are some problems I ran across:

  • There are no browser tab-specific cookies to uniquely tag all requests originating in each tab.
  • From the service worker's perspective, the clientId behind each request belongs to an iframe and not to the browser tab that runs the WordPress worker. w3c/ServiceWorker#1556 could help, but it's not implemented today.
  • The service worker cannot ask a client "is this request coming from you?" because the client doesn't know answer.

Solved by #31