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

[Web] Previously used .wasm binaries missing in 1.19.0 (using web bundler with CopyPlugin) #21811

Closed
e-simpson opened this issue Aug 21, 2024 · 18 comments
Labels
ep:WebGPU ort-web webgpu provider platform:web issues related to ONNX Runtime web; typically submitted using template

Comments

@e-simpson
Copy link

Describe the issue

Using a onnxruntime-web with a web bundler like CopyPlugin I am now getting Package path ./webgpu is not exported from package. When I manually try to bundle the .wasm's I get Unable to locate '..node_modules/onnxruntime-web/dist/ort-wasm.wasm' glob.

I assume the names changed with this update as I see the web bundling changed. I see now bundling was introduced with dd805ff. I looked for some migration docs but couldn't find any.

To reproduce

Can follow the current quick-start https://github.com/microsoft/onnxruntime-inference-examples/tree/main/js/quick-start_onnxruntime-web-bundler

or

  1. Use next.js or similar web bundler/pack framework
  2. Use webpack copy plugin to load onnxruntime-web. Example for next.js:
/** @type {import('next').NextConfig} */
import CopyPlugin from "copy-webpack-plugin";

const nextConfig = {
  webpack: (config) => {
    config.resolve.extensions.push(".ts", ".tsx");
    config.resolve.fallback = { fs: false };

    config.plugins.push(
      new CopyPlugin({
        patterns: [
          {
            from: './node_modules/onnxruntime-web/dist/ort-wasm.wasm',
            to: 'static/chunks/pages',
          },
          {
            from: './node_modules/onnxruntime-web/dist/ort-wasm-simd.wasm',
            to: 'static/chunks/pages',
          },
          { 
            from: './node_modules/onnxruntime-web/dist/ort-wasm-simd.jsep.wasm',
            to: 'static/chunks/pages',
          },
          ],
        }),
    );

    return config;
  } 
}

export default nextConfig;
  1. Import onnxruntime-web/webgpu with import * as ort from 'onnxruntime-web/webgpu';
  2. Run the dev server, example: bun run dev

I get the error:

Module not found: Package path ./webgpu is not exported from package .../node_modules/onnxruntime-web

Urgency

Not urgent, rolled back to 1.18.0 for now.

ONNX Runtime Installation

Released Package

ONNX Runtime Version or Commit ID

1.19.0

Execution Provider

'webgpu' (WebGPU)

@e-simpson e-simpson added the platform:web issues related to ONNX Runtime web; typically submitted using template label Aug 21, 2024
@github-actions github-actions bot added the ep:WebGPU ort-web webgpu provider label Aug 21, 2024
@gotomypc
Copy link

The solution to fix this, can be npm install [email protected], all fix the package.json, lock the onnxruntime-web to 1.14.0 version.

@e-simpson
Copy link
Author

@gotomypc I use 1.18.0 currently which works great. I was just looking to use some new features from 1.19.0😊

@fs-eire
Copy link
Contributor

fs-eire commented Aug 29, 2024

There are multiple changes for onnxruntime-web exports.

a TL;DR version:

  • if you use WebGPU, then
    • import * as ort from 'onnxruntime-web/webgpu';
    • copy ort-wasm-simd-threaded.jsep.wasm
  • if you use CPU only, then
    • import * as ort from 'onnxruntime-web';
    • copy ort-wasm-simd-threaded.wasm

Just 2 .wasm files. copy the one you uses.
See this link to check out options for importing.

Let me know if you have further questions

@fs-eire
Copy link
Contributor

fs-eire commented Aug 29, 2024

work item: examples should be updated.

@e-simpson
Copy link
Author

@fs-eire thanks for the reply!

I copied the ort-wasm-simd-threaded.jsep.wasm into my static files, made sure I'm using 1.19.0 and importing with import * as ort from 'onnxruntime-web/webgpu'; I get the error:

Module not found: Package path ./webgpu is not exported from package 
.../node_modules/onnxruntime-web (see exports field in .../node_modules/onnxruntime-web/package.json)
> 1 | import * as ort from 'onnxruntime-web/webgpu';
    | ^
  2 |

Strange. I tried to copy the ort-wasm-simd-threaded.wasm and use the base non-gpu version and nothing seems to be working. If I revert back to 1.18.0 everything seems to work.

@fs-eire
Copy link
Contributor

fs-eire commented Aug 30, 2024

@fs-eire thanks for the reply!

I copied the ort-wasm-simd-threaded.jsep.wasm into my static files, made sure I'm using 1.19.0 and importing with import * as ort from 'onnxruntime-web/webgpu'; I get the error:

Module not found: Package path ./webgpu is not exported from package 
.../node_modules/onnxruntime-web (see exports field in .../node_modules/onnxruntime-web/package.json)
> 1 | import * as ort from 'onnxruntime-web/webgpu';
    | ^
  2 |

Strange. I tried to copy the ort-wasm-simd-threaded.wasm and use the base non-gpu version and nothing seems to be working. If I revert back to 1.18.0 everything seems to work.

What bundler (and version) do you use? It looks like that your bundler is not reading from the "export" field of onnxruntime-web's package.json

@e-simpson
Copy link
Author

@fs-eire
Bundling with webpack 5.93.0 (what the latest Next.js comes with)

Yeah, and I see the 1.19.0 package exports for web-gpu

    "./webgpu": {
      "node": null,
      "import": "./dist/ort.webgpu.bundle.min.mjs",
      "require": "./dist/ort.webgpu.min.js",
      "types": "./types.d.ts"
    },

For reference the web-gpu exports for 1.18.0

    "./webgpu": {
      "import": "./dist/esm/ort.webgpu.min.js",
      "require": "./dist/cjs/ort.webgpu.min.js",
      "types": "./types.d.ts",
      "default": "./dist/ort.webgpu.min.js"
    },

Let me give turbopack a try

@fs-eire
Copy link
Contributor

fs-eire commented Aug 31, 2024

Since it's Next.js, make sure not using SSR (because importing 'onnxruntime-web/webgpu' from Node.js is explicitly disabled)

@illbexyz
Copy link

I'm having the same issue. I made sure to load onnxruntime-web/webgpu dynamically to filter out SSR errors, but the error seems to be triggered at build time.

I made a reproduction here: https://github.com/illbexyz/nextjs-onnxruntime.
See https://github.com/illbexyz/nextjs-onnxruntime/blob/main/src/pages/index.tsx where I import <OnnxButton />
(which contains the import to onnxruntime-web/webgpu) dynamically with ssr: false.

@fs-eire
Copy link
Contributor

fs-eire commented Sep 17, 2024

I'm having the same issue. I made sure to load onnxruntime-web/webgpu dynamically to filter out SSR errors, but the error seems to be triggered at build time.

I made a reproduction here: https://github.com/illbexyz/nextjs-onnxruntime. See https://github.com/illbexyz/nextjs-onnxruntime/blob/main/src/pages/index.tsx where I import <OnnxButton /> (which contains the import to onnxruntime-web/webgpu) dynamically with ssr: false.

I cloned the repo locally and I can reproduce this error. I am not sure how Next.js deals with this dynamic loading. But I have confirmed that even with ssr: false, when Next.js parses the line:

import * as onnx from "onnxruntime-web";

in OnnxButton.tsx, it uses the "node" export.

This is confirmed by replace the following in node_modules/onnxruntime-web/package.json:

  "exports": {
    ".": {
-     "node": {
-       "import": "./dist/ort.node.min.mjs",
-       "require": "./dist/ort.node.min.js"
-     },
+     "node": null,
      "import": "./dist/ort.bundle.min.mjs",
      "require": "./dist/ort.min.js",
      "types": "./types.d.ts"
    },

This will generate the following error message:

Module not found: Package path . is not exported from package C:\code\nextjs-onnxruntime\node_modules\onnxruntime-web

Conclusion:

The error is because Next.js module resolver picks export for "node" not "import"/"require"(web) in your repo. I don't know exactly how to change this behavior, but if Next.js picks the "import"/"require"(web) export, the issue should be fixed.

@Systemcluster
Copy link

I made a reproduction here: illbexyz/nextjs-onnxruntime.

It's missing onnxruntime-web in the dependencies, and both next dev and next build work for me after adding it.

@fs-eire
Copy link
Contributor

fs-eire commented Sep 18, 2024

I made a reproduction here: illbexyz/nextjs-onnxruntime.

It's missing onnxruntime-web in the dependencies, and both next dev and next build work for me after adding it.

Yes, you are right. It's missing in the dependencies and need to run npm install onnxruntime-web@dev. But I think @illbexyz is complaining about cannot import from "onnxruntime-web/webgpu" (while the repo uses "onnxruntime-web" and it works, modifying the line in OnnxButton.tsx will show that error)

@illbexyz
Copy link

Yes sorry my bad, I provided a quite sloppy reproduction 😅 In case it might be useful to someone, I updated the reproduction to:

  • declare onnxruntime-web@dev in package.json
  • use onnxruntime-web/webgpu in OnnxButton.tsx

The error is because Next.js module resolver picks export for "node" not "import"/"require"(web) in your repo. I don't know exactly how to change this behavior, but if Next.js picks the "import"/"require"(web) export, the issue should be fixed.

Yes I agree with this conclusion, but I have no idea on how to configure next.js to pick the "import"/"require"(web) export.

@e-simpson
Copy link
Author

Yeah, there has to be a "next.js" way to get around this either with some aliases, dynamic resolving, or client flags.

However, for now, I've just worked around it and have been using 1.19.x just as I did before in next.js by manually removing the "node": null, lines from module's package.json. My onnxruntime-web/package.json now looks like:

...
"exports": {
    ".": {
      "node": {
        "import": "./dist/ort.node.min.mjs",
        "require": "./dist/ort.node.min.js"
      },
      "import": "./dist/ort.bundle.min.mjs",
      "require": "./dist/ort.min.js",
      "types": "./types.d.ts"
    },
    "./all": {
      "import": "./dist/ort.all.bundle.min.mjs",
      "require": "./dist/ort.all.min.js",
      "types": "./types.d.ts"
    },
    "./wasm": {
      "import": "./dist/ort.wasm.min.mjs",
      "require": "./dist/ort.wasm.min.js",
      "types": "./types.d.ts"
    },
    "./webgl": {
      "import": "./dist/ort.webgl.min.mjs",
      "require": "./dist/ort.webgl.min.js",
      "types": "./types.d.ts"
    },
    "./webgpu": {
      "import": "./dist/ort.webgpu.bundle.min.mjs",
      "require": "./dist/ort.webgpu.min.js",
      "types": "./types.d.ts"
    },
    "./training": {
      "import": "./dist/ort.training.wasm.min.mjs",
      "require": "./dist/ort.training.wasm.min.js",
      "types": "./types.d.ts"
    }
  },
  ...

And everything works as before.

@fs-eire
Copy link
Contributor

fs-eire commented Sep 19, 2024

the original idea of adding "node": null, is to avoid misuse in Node.js. It seems by removing them indeed helps to use onnxruntime-web in Next.js... if not using web worker. (#22113 is the issue of next step if trying to enable web worker)

@fs-eire
Copy link
Contributor

fs-eire commented Sep 23, 2024

@illbexyz I verified the solution mentioned in vercel/next.js#70296 (comment) works.

Fix: fs-eire/nextjs-onnxruntime@b7adf6f

  • use 'use client'; at the top of the CSR component
  • use dynamic import and use if (typeof windows !== 'undefined') to wrap the dynamic import so that it will not be compiled as Node.js usage.

@illbexyz
Copy link

@fs-eire Thank you! I can confirm that the solution works correctly on Next 14. Unfortunately it doesn't work on Next <= 12 where 'use client' wasn't introduced yet, but imho it's not a big deal.

If @e-simpson agrees I think we can close the issue 🙂

@e-simpson
Copy link
Author

Yes let's consider this solved 🥳

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ep:WebGPU ort-web webgpu provider platform:web issues related to ONNX Runtime web; typically submitted using template
Projects
None yet
Development

No branches or pull requests

5 participants