powersync-js
powersync-js copied to clipboard
Support for react-native-web
I'm having trouble getting powersync installed and working with an expo universal app (react-native and react-native-web)
Error running powersync/react-native on web:
text version of the link: https://github.com/expo/fyi/blob/main/fb-batched-bridge-config-web.md
If i use @powersync/web, i get the error:
Uncaught SyntaxError: Cannot use 'import.meta' outside a module (at index.bundle?platform=web&dev=true&hot=false&lazy=true&transform.engine=hermes&transform.routerRoot=src%2Fapp:258371:114)
which comes from here:
class SharedWebStreamingSyncImplementation extends _WebStreamingSyncImplementation.WebStreamingSyncImplementation {
constructor(options) {
super(options);
/**
* Configure or connect to the shared sync worker.
* This worker will manage all syncing operations remotely.
*/
const syncWorker = new SharedWorker(new URL('../../worker/sync/SharedSyncImplementation.worker.js', import.meta.url), {
/* @vite-ignore */
name: `shared-sync-${this.webOptions.identifier}`,
type: 'module'
});
Additional info, issue raised on expo: https://github.com/expo/expo/issues/21099 https://github.com/expo/expo/issues/30323
here's a git repo reproducing the error:
https://github.com/fig-wealth/powersync-react-native-web
npx expo install
npx expo start
w to launch web
Metro does not support esm, probably wont until at least next year: https://github.com/facebook/metro/issues/916 https://github.com/facebook/metro/issues/886
any chance of making a commonjs transpile of powersync or changing the import.meta.url instances?
Thanks for the detailed issue and example repository! We'll use your example to investigate the requirements - I'll keep you posted when we have an update.
I was missing a commit, i've since added it to the repo. apologies
To give you all an update, and potentially reduce the problem set, I've created another branch that conditionally incorporates @powersync/react-native
https://github.com/fig-wealth/powersync-react-native-web/tree/with-react-native
As far as I can tell, it works on iOS (at least saying the auth is wrong... [I have the self hosted demo running])
We've done an initial investigation where we identified some hurdles and potential solutions for providing React Native web support. We have managed to get an example POC running using a UMD bundled version of the Web SDK. Support may be available in the near future.
That's great news. I can't wait 👍
The dev build has been working great so far. Thanks for all the hard work!
Hey team. We're trying to build for MVP over here:
npx expo export -p w --clear
This is the error we are getting on load:
Failed to fetch a worker script. Pretty sure it's powersync.
Here's a screen grab of the dist directory:
I'll try to get more information shortly.
Ok we're in business.
i have a git action:
# Copy public powersync files to dist directory
- name: Copy public files to dist directory
run: |
# Define the source and destination directories
SOURCE_DIR="apps/client/dist"
DEST_DIR="apps/client/dist/_expo/static/js/web"
# Create the destination directory if it doesn't exist
mkdir -p $DEST_DIR
# Copy all files from the source to the destination
cp -r $SOURCE_DIR/* $DEST_DIR
Moving the files into the _expo/web/js directory fixed it! This is probably just an artifact of the dev build.
hi @jasonlewicki , so does the powersync work on expo web now? Do we need to add more config like git action you paste above? Thanks
hi @jasonlewicki , so does the powersync work on expo web now? Do we need to add more config like git action you paste above? Thanks
@ducpt-bili Hey, yeah, until the team merges into main, there's a list of things you need to do to get it working:
install these:
"@powersync/attachments": "0.0.0-dev-20240812065227",
"@powersync/common": "0.0.0-dev-20240812065227",
"@powersync/kysely-driver": "0.0.0-dev-20240812065227",
"@powersync/react": "0.0.0-dev-20240812065227",
"@powersync/react-native": "0.0.0-dev-20240812065227",
"@powersync/web": "0.0.0-dev-20240812065227",
Then, add this script:
// This file is required for the dev build of powersync to work properly.
// It copies the necessary files from the node_modules/@powersync/web/dist directory to the public directory.
// Gets around the package being built with esm modules and not being able to be resolved by metro.
// This is a temporary solution until the package is updated.
const fs = require('fs');
const path = require('path');
// Source directory
const sourceDir = path.join(
__dirname,
'node_modules',
'@powersync',
'web',
'dist',
);
const destDir = path.join(__dirname, 'public');
function copyRecursiveSync(src, dest) {
if (fs.existsSync(src) && fs.statSync(src).isDirectory()) {
// Create the destination directory if it doesn't exist
if (!fs.existsSync(dest)) {
fs.mkdirSync(dest, { recursive: true });
}
const files = fs.readdirSync(src);
// Copy each file/directory
files.forEach((file) => {
const srcFile = path.join(src, file);
const destFile = path.join(dest, file);
if (fs.statSync(srcFile).isDirectory()) {
copyRecursiveSync(srcFile, destFile);
} else {
fs.copyFileSync(srcFile, destFile);
}
});
} else {
// eslint-disable-next-line no-console
console.error(
`Source directory ${src} does not exist or is not a directory.`,
);
}
}
// Execute the copy
copyRecursiveSync(sourceDir, destDir);
// eslint-disable-next-line no-console
console.log(`Files copied from ${sourceDir} to ${destDir} successfully.`);
and run it.
then modify your metro config to add this:
const customResolveRequest = (context, moduleName, platform) => {
if (platform === 'web') {
if (
['react-native-prompt-android', '@powersync/react-native'].includes(
moduleName,
)
) {
return {
type: 'empty',
};
}
const mapping = {
'react-native': 'react-native-web',
'@powersync/web': '@powersync/web/dist/index.umd.js',
kysely: 'kysely/dist/cjs/index.js',
};
if (mapping[moduleName]) {
// eslint-disable-next-line no-console
console.log('remapping', moduleName);
return context.resolveRequest(context, mapping[moduleName], platform);
}
} else if (['@powersync/web'].includes(moduleName)) {
return {
type: 'empty',
};
}
// Ensure you call the default resolver.
return context.resolveRequest(context, moduleName, platform);
};
the git action above is for production runs, where you copy/move the dev files into the proper dist directory
hi @jasonlewicki , thank you for your hard work.
https://releases.powersync.com/announcements/react-native-for-web-support