Tonejs / Tone.js

A Web Audio framework for making interactive music in the browser.
https://tonejs.github.io
MIT License
13.39k stars 976 forks source link

cannot import in default Next.js app #1077

Open DronHazra opened 2 years ago

DronHazra commented 2 years ago

Describe the bug

I can't import Tone.js in a default Next.js app. I know that I can't use Tone.js in Node, but I'm dynamically importing Tone so that the component is not rendered on the server, only on the browser.

To Reproduce

Here's a repo that shows a minimum example. I created a Next app, imported Tone, and tried to run Tone.start() when the user clicks on a button.

Expected behavior

I expect to be able to import Tone. Tone should work in the browser (I'm not trying to use it in Node), but it's not and I'm not sure why.

What I've tried

I've tried using dynamic imports directly (as described here), putting the import in an Effect hook so it only ran on the browser. This also did not work. It keeps saying Tone.start() is not a function.

Additional context

I'm using Next.js 12.1.5, React 18, and Tone 14.8.38.

cordial commented 2 years ago

I tried your minimum example and couldn't fix the issue fiddling with it. I do however have a next.js project running and working using the same approach as you tried using the following versions - "react": "^17.0.1", "react-dom": "^17.0.1", "tone": "^14.7.77" "next": "^10.0.9",

I tried to downgrade to these on your project, but I'm not entirely sure i downgrading everything correctly (and as i said i couldnt get rid of the error). Maybe try a new project with the above versions. let me know if you need / want any code from my project that might help...(its possible i came across this issue and fix it and have forgotten what i did, its been going a year or so).

limitkr commented 2 years ago

I have experienced the same problem. After trying many things, I found that there was a problem with the package manager. I think the tonejs have a incompatibility with 'Yarn pnp', so you need to change the yarn version to 'classic' instead of 'berry(yarn^2)' and reinstall the module.

# Change the yarn version
yarn set version classic

# Remove file related to yarn berry
# => .pnp.cjs, .pnp.loader.mjs, .yarn, etc.

# install modules
yarn install

Here is the package version that I use.

{
  ...
  "dependencies": {
    "next": "^12.1.6",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "tone": "^14.7.77"
  },
  ...
}
Vlsarro commented 2 years ago

Yeah, had the same problem. I have installed tone.js via npm install tone@next so I've got 14.8.40 version. Downgraded to 14.7.77 and problem has disappeared. @DronHazra your example is working if you downgrade tone.js version.

wormholecowboy commented 2 years ago

Can anyone help me get Tone.js going with Remix? I'm getting this error:

`/my-remix-app/node_modules/tone/build/esm/core/Tone.js:7 import { version } from "../version"; ^^^^^^

SyntaxError: Cannot use import statement outside a module`

Tried putting type:module in the package.json but no go. Do you think reinstalling the package with @next would work for Remix?

3dos commented 1 year ago

The problem here is that the 14.8 introduced the "type": "module" entry in the package.json and any NodeJS project trying to load tone now tries to load the ESM version. While the ESM generated code runs perfectly fine on browsers, in NodeJS, they need file extension paths.

One way to allow NodeJS to use the algorithm that resolves paths without extentions is by using this flag --es-module-specifier-resolution=node (see: the official NodeJS docs).

Paegasus commented 1 year ago

The problem here is that the 14.8 introduced the "type": "module" entry in the package.json and any NodeJS project trying to load tone now tries to load the ESM version. While the ESM generated code runs perfectly fine on browsers, in NodeJS, they need file extension paths.

One way to allow NodeJS to use the algorithm that resolves paths without extentions is by using this flag --es-module-specifier-resolution=node (see: the official NodeJS docs).

That flag sadly didn't help, did anyone manage to get it working?

3dos commented 11 months ago

The problem here is that the 14.8 introduced the "type": "module" entry in the package.json and any NodeJS project trying to load tone now tries to load the ESM version. While the ESM generated code runs perfectly fine on browsers, in NodeJS, they need file extension paths. One way to allow NodeJS to use the algorithm that resolves paths without extentions is by using this flag --es-module-specifier-resolution=node (see: the official NodeJS docs).

That flag sadly didn't help, did anyone manage to get it working?

Sadly, for now, we reverted back to 14.7 in order for Node to use the CJS version of ToneJS. Another option, which is clearly not ideal, would be to use fix-esm-import-paths on the installed lib with a post install npm hook.