みかづきブログ・カスタム

基本的にはちょちょいのほいです。

Electron + Next.jsの開発で、yarn devを実行した際にエラーが発生する際の対策(Error [ERR_REQUIRE_ESM]: require() of ES Module /node_modules/electron-next/node_modules/electron-is-dev/index.js from /node_modules/electron-next/index.js not supported. 編) 💪


ことの発端

普段、Electronアプリを制作する際は、 Next.jsのElectron + TypeScriptのexample を使っています。

github.com

yarn create next-app --example with-electron-typescript app-name

で、Electron + Next.jsの雛形が作成できるので非常に便利です。

しかし、直近でつくったプロジェクトで開発サーバを起動しようとして、

yarn dev

を実行したところ、

Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/nanashi/app/node_modules/electron-next/node_modules/electron-is-dev/index.js from /Users/nanashi/app/node_modules/electron-next/index.js not supported.

というエラーが発生し、起動できなくなっていました。

ちなみに、Next.jsのElectronテンプレートでは、わりとこういうことがあって、以前も、別のエラーで苦しんだことがあります。

blog.kimizuka.org

以前の記事では、実行時の環境を記録し忘れていたので、今回はしっかり記録しておきます。

実行環境

  • macOS: 14.3.1
  • チップ: Apple M1 Max
  • Node.js: v20.10.0

package.json

{
  "private": true,
  "main": "main/index.js",
  "productName": "ElectronTypescriptNext",
  "scripts": {
    "clean": "rimraf dist main renderer/out renderer/.next",
    "dev": "npm run build-electron && electron .",
    "build-renderer": "next build renderer",
    "build-electron": "tsc -p electron-src",
    "build": "npm run build-renderer && npm run build-electron",
    "pack-app": "npm run build && electron-builder --dir",
    "dist": "npm run build && electron-builder",
    "type-check": "tsc -p ./renderer/tsconfig.json && tsc -p ./electron-src/tsconfig.json"
  },
  "dependencies": {
    "electron-is-dev": "^1.2.0",
    "electron-next": "^3.1.5",
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@types/node": "^14.18.63",
    "@types/react": "^16.14.52",
    "@types/react-dom": "^16.9.24",
    "electron": "^27.1.2",
    "electron-builder": "^24.9.1",
    "next": "latest",
    "rimraf": "^3.0.2",
    "typescript": "^4.9.5"
  },
  "build": {
    "asar": true,
    "files": [
      "main",
      "renderer/out"
    ]
  }
}

原因

electron-nextの中で、electron-is-devの最新版をインストールしていることが原因です。

node_modules/electron-next/package.json

{
  "name": "electron-next",
  "version": "3.1.5",
  "description": "Build Electron apps using Next.js",
  "main": "index.js",
  "repository": "leo/electron-next",
  "scripts": {
    "precommit": "lint-staged",
    "test": "xo"
  },
  "keywords": [
    "electron",
    "next",
    "electron.js",
    "next.js"
  ],
  "files": [
    "index.js"
  ],
  "xo": {
    "extends": "prettier",
    "rules": {
      "import/no-unresolved": 0,
      "import/no-extraneous-dependencies": 0
    }
  },
  "lint-staged": {
    "*.js": [
      "npm run test",
      "prettier --single-quote --no-semi --write",
      "git add"
    ]
  },
  "author": "leo",
  "license": "MIT",
  "dependencies": {
    "app-root-path": ">=2.0.1",
    "electron-is-dev": ">=0.3.0"
  },
  "devDependencies": {
    "eslint-config-prettier": "2.9.0",
    "husky": "0.14.3",
    "lint-staged": "7.0.0",
    "prettier": "1.10.2",
    "xo": "0.20.3"
  }
}

0.3.0以上という指定ですが、僕の環境だと3.0.1がインストールされます。
しかし、困ったことに、electron-is-devの3以降はCommonJSからES Moduleに切り替わっており、

Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/nanashi/app/node_modules/electron-next/node_modules/electron-is-dev/index.js from /Users/nanashi/app/node_modules/electron-next/index.js not supported.

というエラーが発生してしまうわけです。
requireではなくimportで読み込まないといけません。

解決方法

electron-is-devは2.0.0まではCommonJSに対応していたので、requireで読み込むことができます。

github.com

そもそも、テンプレートのpackage.jsonでelectron-is-devを、^1.2.0で読み込んでいるのも、それが原因のひとつだとなのでしょう。

なので、electron-nextのバージョンをを2.0.0以下のelectron-is-devを読み込んでいるときまで戻せば解決しそうです。

調べてみると、3.0.0では、electron-is-devの0.1.2を読み込んでいます

github.com

他のパッケージのバージョンもガクッと下がるのが気がかりで、electronは1.6.10になってしまいますが、一旦、

package.json

{
  "private": true,
  "main": "main/index.js",
  "productName": "ElectronTypescriptNext",
  "scripts": {
    "clean": "rimraf dist main renderer/out renderer/.next",
    "dev": "npm run build-electron && electron .",
    "build-renderer": "next build renderer",
    "build-electron": "tsc -p electron-src",
    "build": "npm run build-renderer && npm run build-electron",
    "pack-app": "npm run build && electron-builder --dir",
    "dist": "npm run build && electron-builder",
    "type-check": "tsc -p ./renderer/tsconfig.json && tsc -p ./electron-src/tsconfig.json"
  },
  "dependencies": {
    "electron-is-dev": "^1.2.0",
    "electron-next": "3.0.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@types/node": "^14.18.63",
    "@types/react": "^16.14.52",
    "@types/react-dom": "^16.9.24",
    "electron": "^27.1.2",
    "electron-builder": "^24.9.1",
    "next": "latest",
    "rimraf": "^3.0.2",
    "typescript": "^4.9.5"
  },
  "build": {
    "asar": true,
    "files": [
      "main",
      "renderer/out"
    ]
  }
}

として、試してみました。

が。

Error: Failed to find Electron v1.6.10 for darwin-arm64 at https://github.com/electron/electron/releases/download/v1.6.10/electron-v1.6.10-darwin-arm64.zip

と、やはりElectronのバージョンを下げすぎたことが原因でうまくいきません。

なので、苦肉の策として、

として、解決を目指しました。

package.json

{
  "private": true,
  "main": "main/index.js",
  "productName": "ElectronTypescriptNext",
  "scripts": {
    "clean": "rimraf dist main renderer/out renderer/.next",
    "dev": "npm run build-electron && electron .",
    "build-renderer": "next build renderer",
    "build-electron": "tsc -p electron-src",
    "build": "npm run build-renderer && npm run build-electron",
    "pack-app": "npm run build && electron-builder --dir",
    "dist": "npm run build && electron-builder",
    "type-check": "tsc -p ./renderer/tsconfig.json && tsc -p ./electron-src/tsconfig.json"
  },
  "dependencies": {
    "electron-is-dev": "^1.2.0",
    "electron-next": "git+https://github.com/kimizuka/electron-next#master",
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@types/node": "^14.18.63",
    "@types/react": "^16.14.52",
    "@types/react-dom": "^16.9.24",
    "electron": "^27.1.2",
    "electron-builder": "^24.9.1",
    "next": "latest",
    "rimraf": "^3.0.2",
    "typescript": "^4.9.5"
  },
  "build": {
    "asar": true,
    "files": [
      "main",
      "renderer/out"
    ]
  }
}

そして、結果的にこれで無事に yarn dev が実行できるようになりました。
もっとスマートな解決策があるような気がするのですが、今回のところはこれでよしとしておきます。