alex8088 / quick-start

An easy way to start a front-end project.
MIT License
256 stars 39 forks source link

[ERR_REQUIRE_ESM]: require() of ES Module ... is not supported #43

Closed benbucksch closed 1 month ago

benbucksch commented 2 months ago

Project setup

Reproduction

  1. npm create @quick-start/electron@latest
    • Project name: electron-app
    • Select a framework: › svelte
    • Add TypeScript? Yes
    • Add Electron updater plugin? Yes
    • Enable Electron download mirror proxy? No
  2. cd electron-app; yarn install; yarn run dev -- works
  3. yarn add electron-context-menu, and import it to main.ts, as shown below.
  4. Start the app using yarn run dev

Note: This is an ESM-only (!) third-party npm library, not built by me. The problem is not limited to this library. I have seen the same error multiple times in the past, with different libraries. It appears to be a generic problem with vite in combination with ESM-only modules.

Actual result

Expected result

(and actual result before adding electron-context-menu)

Code

Reduced code of the e2/src/main/index.ts file:

import { BrowserWindow } from 'electron'
import contextMenu from 'electron-context-menu'; // <-- fails here

function createWindow(): void {
  contextMenu({});
  const mainWindow = new BrowserWindow({...})
  ...
}

createWindow();
...

You find the rest of the files, including the build config files, at https://github.com/mustang-im/mustang/tree/4fc959d/e2

Error

App threw an error during load
Error [ERR_REQUIRE_ESM]: require() of ES Module /e2/node_modules/electron-context-menu/index.js from /e2/out/main/index.js not supported.
Instead change the require of /e2/node_modules/electron-context-menu/index.js in /e2/out/main/index.js to a dynamic import() which is available in all CommonJS modules.
    at f._load (node:electron/js2c/asar_bundle:2:13377)
    at Object.<anonymous> (/e2/out/main/index.js:37:21)
    at f._load (node:electron/js2c/asar_bundle:2:13377)
    at loadApplicationPackage (/e2/node_modules/electron/dist/resources/default_app.asar/main.js:121:16)
    at Object.<anonymous> (/e2/node_modules/electron/dist/resources/default_app.asar/main.js:233:9)
    at f._load (node:electron/js2c/asar_bundle:2:13377)
    at node:electron/js2c/browser_init:2:123937
    at node:electron/js2c/browser_init:2:124140
    at node:electron/js2c/browser_init:2:124144
    at f._load (node:electron/js2c/asar_bundle:2:13377)
A JavaScript error occurred in the main process
Uncaught Exception:
Error [ERR_REQUIRE_ESM]: require() of ES Module /e2/node_modules/electron-context-menu/index.js from /e2/out/main/index.js not supported.
Instead change the require of /e2/node_modules/electron-context-menu/index.js in /e2/out/main/index.js to a dynamic import() which is available in all CommonJS modules.
    at f._load (node:electron/js2c/asar_bundle:2:13377)
    at Object.<anonymous> (/e2/out/main/index.js:37:21)
    at f._load (node:electron/js2c/asar_bundle:2:13377)
    at loadApplicationPackage (/e2/node_modules/electron/dist/resources/default_app.asar/main.js:121:16)
    at Object.<anonymous> (/e2/node_modules/electron/dist/resources/default_app.asar/main.js:233:9)
    at f._load (node:electron/js2c/asar_bundle:2:13377)
    at node:electron/js2c/browser_init:2:123937
    at node:electron/js2c/browser_init:2:124140
    at node:electron/js2c/browser_init:2:124144
    at f._load (node:electron/js2c/asar_bundle:2:13377)

Fix attempts

What I tried to fix it:

Rejected solutions

What I consider a bad fix with other disadvantages and what I do not want to do:

Possible solutions

What I could imagine might work:

Used Scaffolding

create-electron

Used Package Manager

yarn

Validations

benbucksch commented 2 months ago

Also filed as https://github.com/electron-userland/electron-builder/issues/8443

alex8088 commented 2 months ago

https://electron-vite.org/guide/troubleshooting#error-err-require-esm-require-of-es-module

alex8088 commented 2 months ago

Better contentmenu: https://github.com/alex8088/electron-uikit/tree/main/packages/contextmenu

benbucksch commented 1 month ago

Better contentmenu: https://github.com/alex8088/electron-uikit/tree/main/packages/contextmenu

FYI: These do different things. This implements the menu widget, but not the menu items, i.e. which items apply to the context, the JS function that implements the functionality, and the label and icon. electron-context-menu implements the latter, not the former.

benbucksch commented 1 month ago

@alex8088 Hey Alex, we managed to change the complication of the main and render process scripts (src/main/index.ts and src/renderer/index.ts) to pure ESM, solving this issue: https://github.com/mustang-im/mustang/commit/c426b1948e946127b2d39fd2e97f83558727f1a2

Would it be a good idea to change the quick-start template to default to ESM instead of compiling to CommonJS? I understand why CommonJS was the default a few years ago, but now basically everybody (esp. with Svelte) uses pure ESM. It's a pity to compile this down to CommonJS.

benbucksch commented 1 month ago

This is esp. true given that quick-start is meant for new projects, so you don't have to worry a lot about legacy code. And the projects started now might be existing for years to come with that template code. They'll be stuck with CommonJS, unless the project developers dig into it, understand that it's compiled to CommonJS (this wasn't clear to me until this bug - I thought we were using ESM only), and find the right solution. All others will continue to use CommonJS.

So, isn't it better to use the new/future/standard technology for new projects?

alex8088 commented 1 month ago

https://electron-vite.org/guide/dev#esm-support-in-electron

benbucksch commented 1 month ago

Yes, we followed these instructions to activate ESM support. However, that requires all developers to a) know that their code is recompiled as CommonJS and b) manually make these changes. It took us significant amount of time to debug this problem. I never would have thought that our ESM code is downconverted by the build scripts to CommonJS. Without knowing all the details, it's surprising that the import of an ESM package from our purely ESM code is failing.

This bug is about making ESM is enabled by default in the quick-start, see my last 2 comments.