joshwcomeau / use-sound

A React Hook for playing sound effects

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Compatible 2.0.1 -> 2.0.2 version breaks require support in webpack build

lewiji opened this issue · comments

Our package.json uses the compatible flag:

"use-sound": "^2.0.1",

Upon running the built module, we get the error:

± |feat-pixi-canvas-fallback {3} U:2 ✗| → node dist/server.js
node:internal/modules/cjs/loader:1125
      throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
      ^

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/ljp/dev/pdm/ruthless-server/node_modules/use-sound/dist/index.js
require() of ES modules is not supported.
require() of /home/ljp/dev/pdm/ruthless-server/node_modules/use-sound/dist/index.js from /home/ljp/dev/pdm/ruthless-server/dist/server.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/ljp/dev/pdm/ruthless-server/node_modules/use-sound/package.json.

    at new NodeError (node:internal/errors:278:15)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1125:13)
    at Module.load (node:internal/modules/cjs/loader:973:32)
    at Function.Module._load (node:internal/modules/cjs/loader:813:14)
    at Module.require (node:internal/modules/cjs/loader:997:19)
    at require (node:internal/modules/cjs/helpers:92:18)
    at Object.use-sound (/home/ljp/dev/pdm/ruthless-server/dist/server.js:5224:18)
    at __webpack_require__ (/home/ljp/dev/pdm/ruthless-server/dist/server.js:5291:42)
    at eval (webpack-internal:///./app/src/notification/components/NotificationSystem.js:11:67)
    at Module../app/src/notification/components/NotificationSystem.js (/home/ljp/dev/pdm/ruthless-server/dist/server.js:906:1) {
  code: 'ERR_REQUIRE_ESM'
}

Though the NotificationSystem.js module uses import syntax and works on a dev server, in the build it fails I guess because of some webpack internal using a require statement instead.

I believe this is due to this change #71 d7d9ef9

Now, this likely points to a lurking issue in my webpack config which can probably be fixed, and a quick workaround is just to specifically use 2.0.1 as the package version, however I'm not sure that changing that flag (type: "module") is truly a compatible, minor change (as well, I feel that that particular change should have bumped the version number which was changed a couple of commits prior).

It's due #55, and #71 is an attempt to fix it. Try to apply that change locally to verify if it works for your case.

I see, thanks I will try that. Did try to search for other issues but didn't find one, I'll comment and close this if that works.

It's been merged and shipped in 2.1.1, let me know how it goes

Thanks both, it's getting late here so I didn't have time to thoroughly investigate what's going on, but I bumped the package to 2.1.1, nuked node_modules and ran yarn. I then verified the version checked out into node_modules was 2.1.1. Rebuilt project from clean - unfortunately the same error on starting the server:

± |develop → pdm {4} U:2 ✗| → yarn start
yarn run v1.22.10
$ node dist/server.js
node:internal/modules/cjs/loader:1125
      throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
      ^

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/ljp/dev/pdm/ruthless-server/node_modules/use-sound/dist/index.js
require() of ES modules is not supported.
require() of /home/ljp/dev/pdm/ruthless-server/node_modules/use-sound/dist/index.js from /home/ljp/dev/pdm/ruthless-server/dist/server.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/ljp/dev/pdm/ruthless-server/node_modules/use-sound/package.json.

    at new NodeError (node:internal/errors:278:15)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1125:13)
    at Module.load (node:internal/modules/cjs/loader:973:32)
    at Function.Module._load (node:internal/modules/cjs/loader:813:14)
    at Module.require (node:internal/modules/cjs/loader:997:19)
    at require (node:internal/modules/cjs/helpers:92:18)
    at Object.use-sound (/home/ljp/dev/pdm/ruthless-server/dist/server.js:5224:18)
    at __webpack_require__ (/home/ljp/dev/pdm/ruthless-server/dist/server.js:5291:42)
    at eval (webpack-internal:///./app/src/notification/components/NotificationSystem.js:11:67)
    at Module../app/src/notification/components/NotificationSystem.js (/home/ljp/dev/pdm/ruthless-server/dist/server.js:906:1) {
  code: 'ERR_REQUIRE_ESM'
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

I guess I'm not entirely up to date with what these changes are doing, this is for some of the more recent, leaner build tools than webpack that are using native ES modules, is that right? I'll do some research tomorrow because if it's going to be as simple as just changing my webpack/babel config a little to add interoperability I'll just do that, or just go back to 2.0.1 for now (which I'm happy with for this project, it only flagged up as a new dev started and installed packages from scratch without a lockfile).

I'm on webpack 5.21.2 if that's important, which is slightly out of date I guess, so perhaps upgrading that would help? It's getting late here so I'm gonna have to pause until tomorrow.

Here's the output from use-sound's package.json to make sure I'm looking at the right version:

± |develop → pdm {4} U:2 ✗| → cat node_modules/use-sound/package.json
{
  "name": "use-sound",
  "author": "Josh Comeau",
  "module": "dist/use-sound.esm.js",
  "type": "module",
  "exports": {
    "import": "./dist/use-sound.esm.js",
    "require": "./dist/index.js"
  },
  "version": "2.1.1",
  "repository": "github:joshwcomeau/use-sound",
  "license": "MIT",
  "main": "dist/index.js",
  "typings": "dist/index.d.ts",
  "scripts": {
    "start": "tsdx watch",
    "build": "tsdx build",
    "test": "tsdx test --passWithNoTests",
    "lint": "tsdx lint",
    "prepare": "tsdx build",
    "storybook": "start-storybook -p 6006",
    "build-storybook": "build-storybook"
  },
  "files": [
    "dist"
  ],
  "dependencies": {
    "howler": "^2.1.3"
  },
  "devDependencies": {
    "@babel/core": "^7.8.7",

... etc

Thanks for your assistance so far.

====

Edit: oh, and for reference, node version for this project is 15.5.0

Yeah, ESM support in Node gives a lot of hassle. Definitely test the latest webpack, somehow your build process downgraded the import statement to the old require statement, so make sure your target code is at least ES6 or higher, or remove the "type": "module" from the project level package.json. A minimal reproduction repo demonstrating the problem would also be helpful.

I'm seeing the same thing here. The error message and the Node docs agree:

Files ending with .js are loaded as ES modules when the nearest parent package.json file contains a top-level field "type" with a value of "module".

So I'm guessing that webpack is loading the entry from the main key, which isn't an ES module, but Node thinks it's an ES module because "type": "module". I'm not sure how the newly added exports key works, but Node doesn't seem to be respecting it on my end.

Will dig in further and see if I can find a workaround. Happily using 2.0.2 in the mean time though! 🙂

Well, I'm glad I'm not alone on this, slightly tearing my hair out 😁

I made a bunch of attempts at upgrading my webpack/babel config earlier to make it compatible, no luck whatsoever sadly. No matter what I set the build targets to in the webpack or babel configs, it outputs require statements into the build. I replace the babel preset env config with esmodules: true - no difference. Upgraded both babel and webpack to latest version, again no effect.

Big problem is that we're clearly in a transitional stage between these 2 standards and a lot of the info online is out of date. The docs aren't very clear for this functionality on either webpack or babel, either.

My project is a monorepo with both a game server and initally SSR'd client under the same package (along with a bunch of submodules which I've today configured as workspaces in Yarn v2 in an attempt to get this ES modules thing working). I also changed my projects package and the submodules to use the "type: 'module'" flag. Though everything builds without issue after some fiddling, still I end up with the above error on use-sound.

(I even started changing my config files that need require to .cjs and my program code to .mjs files before realising I was going slightly mad with this giant codebase 😊 I hope they bin off that idea to be honest...)

I like these changes and what they add to the structure and build process, but it did nothing to get use-sound latest working, I'm afraid. At this point I think I'm just going to revert back too, which I'm happy to do, I'm just a bit perplexed about the entire thing right now.

It feels a bit to me like the wider JS community is trying to forcibly kill off require, and that's fine by me, but I'd rather not get caught in the crossfire!

Thanks again for your input. I've contacted another dev who I know is more of an expert at webpack, so if I do eventually solve it I'll update the issue.

Sorry for the trouble y'all!

I'm thinking here's what I'll do:

• I'll publish a new minor version in 2.x, which removes the type/exports fields (and should fix this issue)
• I'll publish 3.0.0 with the field

That way y'all don't have to lock to a minor/patch version.

One other thing, too: the source for this project is really pretty small. It's two files (other than the TS types):

I have zero problem with folks copy/pasting the source into their own projects—just please add a comment with a link to this repo. Because this is a small project, I think it's a feasible alternative, and it has a ton of benefits (no potential issues like this in the future, you "own" the code and can tweak it as-needed).

Kk, 2.2.0 is published with the type/exports removed. And 3.0.0 published with the fields re-added.

Please do consider "adopting" the code directly though :D I won't be publishing any updates on the 2.x version going forward, so you may as well make it your own!

That's great, thank you for the resolution, Josh!

I would eventually like to get this project compatible with 3.0.0+ for future-proofing, because I liked a lot of what I saw when attempting to upgrade things, but the 2.2.0 version will definitely tide things over for now. Also, not a bad idea with just adding the source straight to the project - I didn't realise it was just 2 files!

If/when the stars align and webpack starts to behave with ESM mode, I will still leave a comment here just in case anyone has a similar issue later down the line, though I appreciate this isn't specifically a use-sound issue, more a "future-javascript" and webpack/babel issue at this point.