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

Evolu's worker setup does not work with Metro bundler on web (and also new versions of Expo). #478

Open
samwightt opened this issue Sep 8, 2024 · 1 comment

Comments

@samwightt
Copy link
Contributor

Evolu has several workers that it needs to start in order for Evolu to start correctly. When Evolu starts a worker, it uses syntax like this:

      new Worker(new URL("Sync.worker.js", import.meta.url), {
        type: "module",
      })

Vite and a few other bundlers understand this syntax and will automatically take care of including Sync.worker.js as part of the bundle automatically. However, this does not work with Metro.

The current example of using Expo in the repo uses an older Webpack setup. However, Expo's Webpack support is deprecated and will not receive future updates. Instead, it's recommended to use expo-router, which is a new bundler built on top of Metro. All new Expo projects use expo-router by default.

There are two problems when trying to get Evolu to work with Metro (SPECIFICALLY ONLY WITH THE WEB TARGET):

  • import.meta.url is not supported in Metro as Metro does not fully support ESM (don't ask me why, but it supports dynamic import but not this apparently 🙄). Here is a tracking issue in Expo for this: Expo Web can’t use an ESM package with import.meta. expo/expo#30323
  • Metro (and expo-router as far as I can tell) do not have a native syntax for web workers. They do not support the new Worker(new URL("blah", import.meta.url)) syntax that Vite understands. This means that even if import.meta.url was supported, Sync.worker.js would not be included in the Metro bundle. ie. new Worker(new URL("Sync.worker.js", import.meta.url)) would not work because the compiled assets would not include Sync.worker.js. I couldn't find any issues for this and I don't know if this is something that the Metro team would even want to fix. expo-router maybe, but in RN as far as I can tell there are other solutions for doing background tasks.

Making Evolu compatible with Metro

In order to make Evolu compatible with Metro as it is right now, two things need to happen:

  • Evolu needs config options that allow Worker URLs to be passed in as a string. As far as I can tell, there are two workers: Db.worker.ts and Sync.worker.ts. Each of these needs the URLs to be passed via Evolu's config options. Additionally, it would be good to wrap import.meta.url in a try / catch block to ensure it is actually supported in that context (the modules outputted from Metro are not modules, just JS files like old Webpack).
  • Evolu needs to bundle the Db.worker.ts and Sync.worker.ts as assets that the user can put in their root public folder of the project. Metro will include files automatically in the /public folder of the project.

An issue sort-of already exists for this, but the second requirement is something that's a little more specific. See here: #468

There are only issues with the web target in Metro. Because @evolu/react-native does not use web workers or rely on them, it works just fine for iOS and Android targets. Unfortunately expo-sqlite does not work on the web target so it's not possible just to have one file work for all of them.

@steida
Copy link
Contributor

steida commented Sep 9, 2024

I will review it after the new sync and update docs. Thank you!

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

No branches or pull requests

2 participants