ionic-team / ionic-cli

The Ionic command-line interface
MIT License
1.99k stars 640 forks source link

[Bug]: All capacitor commands fail with ERR_REQUIRE_ESM #5081

Open thomasakarlsen opened 3 months ago

thomasakarlsen commented 3 months ago

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

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 "string-width@5.1.2"
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 "string-width@4.2.3"
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/android@5.7.0
yarn add v1.22.21
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
warning "@vitejs/plugin-legacy > esbuild-plugin-browserslist@0.10.0" 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/android@5.7.0
info All dependencies
└─ @capacitor/android@5.7.0
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 ionic-team/capacitor#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)

ionitron-bot[bot] commented 3 months ago

This issue needs more information before it can be addressed. In particular, the reporter needs to provide a minimal sample app that demonstrates the issue. If no sample app is provided within 15 days, the issue will be closed. Please see the Contributing Guide for how to create a Sample App. Thanks! Ionitron 💙

thomasakarlsen commented 3 months ago

I have added a reproduction repo: https://github.com/thomasakarlsen/capacitor-esm-bug

thomasakarlsen commented 3 months ago

Regarding the reproduction repo: It seems like cypress is having a similar issue making it impossible to run yarn install on it. I have no clue how to fix this. Again, this repo is just a fresh setup of ionic start --type=vue so to investigate the specific issue I have talked about here it is best to create a new ionic app locally.

There is something really weird going on with the dependencies here...

thomasakarlsen commented 3 months ago

Seems like deleting the yarn.lock file and then running yarn install somehow produces a dependency graph that properly works even without setting @vue/test-utils to 2.4.0.

Interestingly this works both for the reproduction repo and if you use ionic start --type=vue.

jcesarmobile commented 2 months ago

Thanks for the issue, but it's an Ionic CLI issue, not a Capacitor issue, I've moved it to the appropriate repository.

The problem is, as you have figured out by now, that something is installing string-width version 5.x, which is a ESM version and the Ionic CLI doesn't support ESM dependencies. When you remove the lock file and reinstall, then the 4.x version is installed and your app works.

Ionic CLI would need to be updated to support ESM dependencies for this to be fixed, but also some people mention that using yarn 4 also fixes the issue.