[Bug]: All capacitor commands fail with ERR_REQUIRE_ESM
Capacitor Version
(gathered after my temporary fix, see details below)
Latest Dependencies:
@capacitor/cli: 5.7.0 @capacitor/core: 5.7.0 @capacitor/android: 5.7.0 @capacitor/ios: 5.7.0
Installed Dependencies:
@capacitor/android: 5.7.0 @capacitor/ios: not installed @capacitor/cli: 5.7.0 @capacitor/core: 5.7.0
Other API Details
npm: 10.2.3
node: 18.19.0 (however I did also experience this on 20.11.0)
yarn: 1.22.21
Platforms Affected
- [X] iOS
- [X] Android
- [X] Web
Current Behavior
When trying to run ionic capacitor run android for the first time in a fresh ionic app the following error appears when the ionic cli reaches the step where this capacitor init MyApp io.ionic.starter --web-dir dist is run:
> capacitor init MyApp io.ionic.starter --web-dir dist
/.../node_modules/@ionic/utils-terminal/dist/format.js:9
const stringWidth = require("string-width");
^
Error [ERR_REQUIRE_ESM]: require() of ES Module /.../node_modules/string-width/index.js from /.../node_modules/@ionic/utils-terminal/dist/format.js not supported.
Instead change the require of index.js in /.../node_modules/@ionic/utils-terminal/dist/format.js to a dynamic import() which is available in all CommonJS modules.
at Object.<anonymous> (/.../node_modules/@ionic/utils-terminal/dist/format.js:9:21)
at Object.<anonymous> (/.../node_modules/@ionic/utils-terminal/dist/index.js:6:22)
at Object.<anonymous> (/.../node_modules/@ionic/cli-framework-output/dist/index.js:5:26)
at Object.<anonymous> (/.../node_modules/@capacitor/cli/dist/log.js:5:32)
at Object.<anonymous> (/.../node_modules/@capacitor/cli/dist/config.js:10:15)
at Object.<anonymous> (/.../node_modules/@capacitor/cli/dist/index.js:7:18)
at Object.<anonymous> (/.../node_modules/@capacitor/cli/bin/capacitor:17:11) {
code: 'ERR_REQUIRE_ESM'
}
Node.js v18.19.0
[ERROR] An error occurred while running subprocess capacitor.
capacitor init MyApp io.ionic.starter --web-dir dist exited with exit code 1.
Re-running this command with the --verbose flag may provide more information.
Researching this issue I ran yarn why string-width which resulted in:
yarn why v1.22.21
[1/4] 🤔 Why do we have the module "string-width"...?
[2/4] 🚚 Initialising dependency graph...
[3/4] 🔍 Finding dependency...
[4/4] 🚡 Calculating file sizes...
=> Found "[email protected]"
info Reasons this module exists
- "@vue#test-utils#js-beautify#glob#jackspeak#@isaacs#cliui" depends on it
- Hoisted from "@vue#test-utils#js-beautify#glob#jackspeak#@isaacs#cliui#string-width"
- Hoisted from "@vue#test-utils#js-beautify#glob#jackspeak#@isaacs#cliui#wrap-ansi#string-width"
info Disk size without dependencies: "172KB"
info Disk size with unique dependencies: "308KB"
info Disk size with transitive dependencies: "328KB"
info Number of shared dependencies: 4
✨ Done in 0.16s.
Looking at the recent releases of @vue/test-utils I found that in versions 2.4.1 and 2.4.2 they updated their dependencies.
By hard locking my version of @vue/test-utils to 2.4.0 and performing a clean install by deleting my yarn.lock file and node_modules followed by yarn install I was able to run capacitor init MyApp io.ionic.starter --web-dir dist without any errors.
Running yarn why string-width now results in:
yarn why v1.22.21
[1/4] 🤔 Why do we have the module "string-width"...?
[2/4] 🚚 Initialising dependency graph...
[3/4] 🔍 Finding dependency...
[4/4] 🚡 Calculating file sizes...
=> Found "[email protected]"
info Reasons this module exists
- "@ionic#utils-terminal" depends on it
- Hoisted from "@ionic#utils-terminal#string-width"
- Hoisted from "wrap-ansi#string-width"
- Hoisted from "cypress#cli-table3#string-width"
- Hoisted from "@capacitor#cli#@ionic#utils-subprocess#@ionic#utils-terminal#string-width"
- Hoisted from "cypress#listr2#cli-truncate#string-width"
- Hoisted from "@capacitor#cli#@ionic#utils-subprocess#@ionic#utils-process#@ionic#utils-terminal#string-width"
- Hoisted from "cypress#listr2#log-update#wrap-ansi#string-width"
info Disk size without dependencies: "20KB"
info Disk size with unique dependencies: "128KB"
info Disk size with transitive dependencies: "148KB"
info Number of shared dependencies: 3
✨ Done in 0.14s.
I do not know exactly what changed with the dependencies of @vue/test-utils after version 2.4.0 but something there seems to cause yarn to disregard the manifest of @ionic/utils-terminal and install major versions of some dependencies that are not supported.
Expected Behavior
ionic capacitor run android or even capacitor initworks without any errors
This is my output after locking @vuejs/test-utils to version 2.4.0:
> capacitor init MyApp io.ionic.starter --web-dir dist
✔ Creating capacitor.config.ts in /.../ in 1.68ms
[success] capacitor.config.ts created!
Next steps:
https://capacitorjs.com/docs/getting-started#where-to-go-next
[OK] Integration capacitor added!
> yarn add --exact --non-interactive @capacitor/[email protected]
yarn add v1.22.21
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
warning "@vitejs/plugin-legacy > [email protected]" has unmet peer dependency "esbuild@~0.19.2".
[4/4] Building fresh packages...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ @capacitor/[email protected]
info All dependencies
└─ @capacitor/[email protected]
Done in 2.16s.
> capacitor add android
[capacitor] ✔ Adding native android project in android in 15.85ms
[capacitor] ✔ add in 16.18ms
[capacitor] [warn] sync could not run--missing dist directory.
[capacitor] [success] android platform added!
[capacitor] Follow the Developer Workflow guide to get building:
[capacitor] https://capacitorjs.com/docs/basics/workflow
? Which device would you like to target? (Use arrow keys)
....
Project Reproduction
https://github.com/thomasakarlsen/capacitor-esm-bug
Additional Information
I had the same issue as #7126 and did some more digging to figure out why it was happening.
Based on the results of my debugging I am not sure if this is the right package to create the issue for, but it is the capacitor init command that fails. Let me know if the issue should be made elsewhere.
For anyone else experiencing this issue the temporary solution seems to be locking @vuejs/test-utils to version 2.4.0 (and doing a clean install of dependencies)