rocicorp / replicache

Realtime Sync for Any Backend Stack
https://doc.replicache.dev
1.05k stars 37 forks source link

Seems like Next.js is not working #151

Closed aboodman closed 3 years ago

aboodman commented 4 years ago

@elsigh tried to use Replicache in a nextjs app and just imported it through npm the naive way. It correctly resolved to the cjs bundle, but the cjs bundle contains code with export which doesn't seem correct.

This blocks @elsigh from trying Replicache. We should maybe make a sample nextjs app to ensure this works.

aboodman commented 4 years ago

Confirmed. I can replicate like this:

npx create-next-app foo

Then in package.json, add:

  "resolutions": {
    "webpack": "^5.0.0-beta.30"
  }

... to enable wp5 support per https://nextjs.org/blog/next-9-5#webpack-5-support-beta.

Then npm install replicache and instantiate it in index.js. I get:

error - ./node_modules/replicache/out/wasm/release/replicache_client.js 302:22
Module parse failed: Unexpected token (302:22)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| async function init(input) {
|     if (typeof input === 'undefined') {
>         input = import.meta.url.replace(/\.js$/, '_bg.wasm');
|     }
|     const imports = {};
/Users/aa/work/roci/replicache-next/node_modules/replicache/out.cjs/wasm/release/replicache_client.js:223
export function uuid() {
^^^^^^

SyntaxError: Unexpected token 'export'

I think since this blocks anyone creating a cjs app it's a p1. @arv I see the flag in webpack-build, but not sure how you want to setup the output.

arv commented 4 years ago

Did some exploring. If we generate --target nodejs for wasm-pack compilation we get closer but there are some more issues.

Next.js is running in a Node.js environment without a lot of DOM. I think we will also run into trouble with IDBFactory if we get that far.

aboodman commented 4 years ago

I’m so lost - why are we running in a node environment?

arv commented 4 years ago

Next.js tries to run the js on the server, it is what is so special about next.js. I will try to switch to dynamic import and see how that plays out.

arv commented 4 years ago

We can check process.browser or use dynamic import which are only run on the client.

arv commented 4 years ago

Manually Removing out.cjs and things seems to work well with next.js

Screen Shot 2020-10-26 at 11 20 41 AM
aboodman commented 4 years ago

This needs to be re-opened, right?

arv commented 3 years ago

Getting closer...

Turns out I have to use yarn for "resolutions" to work.

Now it replaces the import.meta.url with a file:// URL (which is clearly wrong), however, one of the webpack bugs suggests using the following pattern to get webpack to realize that it is an asset (https://github.com/webpack/webpack/issues/6719#issuecomment-710336119)

new URL('./path/file.wasm', import.meta.url);

That look much better and becomes http://localhost:3000/_next/c770d646807cab937689.wasm but that file is 404

Then I tried using file-loader.

// next.config.js
module.exports = {
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.wasm/,
      use: ["file-loader"],
    });

    return config;
  },
};

Could not resolve file-loader...

yarn add file-loader

Still getting 404.

Maybe @elsigh has any idea what I am missing?

aboodman commented 3 years ago

I was able to hack this to work horribly with the following steps:

  1. npx create-next-app foo
  2. resolutions -> use wp5
  3. add a symlink public/wasm -> node_modules/out/wasm
  4. pass wasmModule field to Replicache constructor with value wasm/release/replicache_client_bg.wasm

Basically, I tell Replicache the URL to find the wasm file at specifically rather than trying to derive it from import.meta.url, then I hack app dir to serve it.

This is not ideal, but works for now.

aboodman commented 3 years ago

new URL('./path/file.wasm', import.meta.url);

Where did you put this? I can't replicate your steps here.

That look much better and becomes http://localhost:3000/_next/c770d646807cab937689.wasm but that file is 404

I wonder if webassemblyModuleFilename is the missing piece here?

https://github.com/vercel/next.js/blob/canary/examples/with-webassembly/next.config.js

arv commented 3 years ago

I modified the generated code in replicache_client.js but we can do the same thing one layer higher up.

I tried using webassemblyModuleFilename too. Not sure if it was working, in other words changing the name didn't seem to change the URL or where the file was assured on disk.

More later...

arv commented 3 years ago

And yes, manually putting things in public works for me too

arv commented 3 years ago

Calling this done for now.

We will see if we need to resurface a cjs build in the future.