Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scaffolded project with "tsc --init" + "type": "module" fails to compile due to conflicting module/commonjs #27359

Open
JessicaSachs opened this issue Jul 20, 2023 · 12 comments

Comments

@JessicaSachs
Copy link
Contributor

JessicaSachs commented Jul 20, 2023

Current behavior

image

Desired behavior

Better error message. Something like the below

"The module type in your `tsconfig.json` doesn't match the one in your `package.json`. Either choose `commonjs` or `module`"

Test code to reproduce

npm init -y
pnpm install cypress typescript -D
pnpm tsc --init
pnpm cypress open

Change package.json to use "type": "module" (the default for tsc is commonjs)

Cypress Version

Any >= 10. Currently 12.X

@lmiller1990
Copy link
Contributor

I wonder what makes pnpm different to npm that breaks this?

In fact, I wonder why a package manager has any bearing at all on this. All pnpm does is install packages, it shouldn't impact actual execution, right?

Are we doing something deeply wrong -- we really shouldn't need package manager specific code at all.

@lmiller1990
Copy link
Contributor

I changed it to cypress.config.mts (which requires a patch to Cypress, too) but that seems to work. The whole point of type: module is so you don't need to add mts, though. It seems Cypress is not respecting type module when used with pnpm.

@lmiller1990
Copy link
Contributor

This has nothing to do with pnpm, same result with npm.

@JessicaSachs
Copy link
Contributor Author

@JessicaSachs
Copy link
Contributor Author

Mr. @marktnoonan supposed that it was pnpm - apologies for not digging more.

@lmiller1990
Copy link
Contributor

lmiller1990 commented Jul 20, 2023

You can fix with tsconfig.json like this:

{
  "compilerOptions": {
    "module": "ES2015"
  }
}

Explanation: #23552 (comment)

Bit of a mess, this really should not be the experience users are greeted with. If you don't have a tsconfig.json, TypeScript defaults to "module": "commonjs" so cypress.config.ts compiles to CJS... but since you've got "type": "module", Node.js uses the ESM loader.

I'm not sure what the correct way to fix this would be - we probably don't want to clobber the default tsconfig.json options (or do we? The user is asking for ESM, after all).

I am unsure why https://github.com/cypress-io/cypress/tree/develop/system-tests/projects/config-with-ts-module-error does not catch this.

@JessicaSachs
Copy link
Contributor Author

JessicaSachs commented Jul 20, 2023

Ahhh I touched "target" when I did tsc --init - thank you. That makes SO much sense.

@lmiller1990
Copy link
Contributor

lmiller1990 commented Jul 20, 2023

Should we close this? Or maybe pivot to "show a better error message"?

Also the test project you linked is used... to assert the exact error you ran into is shown 😇

cy.contains('p', getPathForPlatform('cy-projects/config-with-ts-module-error/cypress.config.ts'))

I wonder if the error should say something like "Check the module value in your tsconfig.json" instead of a fairly useless error message".

@JessicaSachs
Copy link
Contributor Author

Yeah I think "The module version in your tsconfig.json doesn't match the one in your package.json" is a good error message.

@JessicaSachs JessicaSachs changed the title Scaffolded project with pnpm + typescript + "type": "module" fails to compile Scaffolded project with "tsc --init" + "type": "module" fails to compile due to conflicting module/commonjs Jul 20, 2023
@JessicaSachs
Copy link
Contributor Author

I cleaned up stuff and expected behavior. Thanks again @lmiller1990 and @marktnoonan for triaging. I thought I was crazy.

@lmiller1990
Copy link
Contributor

Ecosystem is the crazy one, especially the CJS + ESM mess.

@lmiller1990
Copy link
Contributor

lmiller1990 commented Jul 20, 2023

Actually, this happens outside of Cypress, too. We are just bubbling up what Node.js runs into.

  1. npm install typescript
  2. set "type": "module"
  3. npx tsc --init
  4. echo "export const foo = 'bar'" > "foo.ts"`
  5. npx tsc -p .
  6. node foo.js
file:///Users/lachlanmiller/code/dump/dump/foo.js:2
Object.defineProperty(exports, "__esModule", { value: true });
                      ^

ReferenceError: exports is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and '/Users/lachlanmiller/code/dump/dump/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

So, I guess this is expected behavior? If we work around it, we'd be going against what would happen in a regular TS project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants