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

Support for ESM in TypeScript projects #3385

Open
fvictorio opened this issue Nov 30, 2022 · 46 comments
Open

Support for ESM in TypeScript projects #3385

fvictorio opened this issue Nov 30, 2022 · 46 comments
Assignees
Labels
effort:difficult status:blocked Blocked by other issues or external reasons type:feature Feature request

Comments

@fvictorio
Copy link
Member

fvictorio commented Nov 30, 2022

Please comment and/or upvote this issue if you need support for ESM in TypeScript projects. If possible, tell us more about your use case and why you need this and cannot just transpile to cjs.

UPDATE: We have an experimental version working

See this comment to learn how to use an experimental version of this: #3385 (comment)

@github-actions
Copy link
Contributor

This issue is also being tracked on Linear.

We use Linear to manage our development process, but we keep the conversations on Github.

LINEAR-ID: b31f8c05-52a3-44ca-b22e-10ec21278d4c

@matthewlilley
Copy link

matthewlilley commented Dec 6, 2022

@fvictorio we use wagmi/core for some scripts which only supports ESM. Had to convert all tests to .js and extract chunks of scripts into another package for now to deal with this.

sushiswap/sushiswap@ccd68f9

@DenisGorbachev
Copy link

I'm using https://github.com/sindresorhus/execa, which is ESM-only.

@anteqkois
Copy link

I can't run task when use new TypeScript:

"module": "NodeNext",
"moduleResolution": "NodeNext",

Obviously when i delete "type": "module" from package.json it's start work, but i must use this setting.

Error from terimnal:
image

@talentlessguy
Copy link

Suggestion for TS ESM implementation:

ts-node has a ts-node/esm loader hook. Also mts extension could be used but I'm not sure if that's needed.

@paulmillr
Copy link

Copying @alcuadrado comments from monorepo:

Nop, unfortunately Hardhat's core depends on CJS pretty heavily.

The reason for that is that our plugin system is dependent on the order of require() that users make to plugins. In ESM the order of imports is not guaranteed (and does change in practice).

What about await import? You can do this one after another.

We need to rework our plugin system for it to fully support ESM.

I'm starting to think that maybe we should move to esm-only when it's properly supported by ts-node or some similar project. But note that even after that, the migration would be a pretty large project, as every plugin will need to be adapted.

If you keep supporting two module systems, ESM modules would be able to import common.js code - which uses old sequential requires and is cool.

@alcuadrado
Copy link
Member

What about await import? You can do this one after another.

Oh, that may be a great idea actually! I think now ESM in node.js means/implies that you have top-level-await. This could work! Thanks !

@alex-mccreary
Copy link

Upvote; we are using ESM in our TypeScript project because of a dependency requirement.

@pynixwang
Copy link

pure esm package is coming.

@thevolcanomanishere
Copy link

I am looking to integrate Playwright with Hardhat + Wagmi in order to automate frontend testing that involves connecting to a hardhat node :)

@kostysh
Copy link

kostysh commented Apr 14, 2023

Upvote; we are using ESM in our TypeScript project

@highskore
Copy link

pure esm package is coming.

do u know when? 🧐

@robwilkes
Copy link

upvote, many packages are ESM only now, I have to install older versions for compatibility. all my projects and code is ESM now, except for hardhat.

@CJ42
Copy link

CJ42 commented Jun 7, 2023

Upvoting as well. We have constants values defined in a constants.ts / constants.js](https://github.com/lukso-network/lsp-smart-contracts/blob/develop/constants.ts) file in the LUKSO lsp-smart-contracts. These are part of the [@lukso/lsp-smart-contracts` npm package and are important values to be consumed by projects that use our smart contracts package.

https://github.com/lukso-network/lsp-smart-contracts

In our case, this is problematic as any Hardhat Typescript project that has the @lukso/lsp-smart-contracts as a dependency cannot import these necessary constant values.

The only workaround we found was in this PR by @richtera: lukso-network/lsp-smart-contracts#601.

image

https://github.com/lukso-network/lsp-smart-contracts/pull/601/files

The file in the folder looks like this:

image

ES Lint raises a warning, but we are still able to import as shown below.

import { INTERFACE_IDS } from "@lukso/lsp-smart-contracts/dist/constants.cjs.js";

const test = INTERFACE_IDS.LSP0ERC725Account;

@vinerz
Copy link

vinerz commented Jul 9, 2023

Following this issue. Would help a lot to get rid of some workarounds for ESM/CJS interop.

@fraVlaca
Copy link

yes pls really need esm compatibility with typescript, make it happen guys

@paulperegud
Copy link

Having to choose dependencies basing on "does it still support CommonJS" criterion is annoying. Following this issue.

@Yuripetusko
Copy link

The experimental solution works fine for me, but another solution would be to simply switch from ts-node to tsx internally

@signorecello
Copy link

Thanks! I went the monorepo route and it worked just fine by using separate tsconfigs.

I was just wondering if you were still going for the full support. Seems like you are, which is great!

Thanks!

@schaable
Copy link
Member

can hardhat just migrate to https://www.npmjs.com/package/tsx package? It runs without any problems with ESM, it was built to be ESM first.

The experimental solution works fine for me, but another solution would be to simply switch from ts-node to tsx internally

We tried that approach and, with our current setup, it's not possible to swap from ts-node to tsx without introducing breaking changes. As @kanej said, it's one of the key items we'll focus over the next months. Rest assured, full ESM support is on the way.

@Yuripetusko
Copy link

can hardhat just migrate to https://www.npmjs.com/package/tsx package? It runs without any problems with ESM, it was built to be ESM first.

The experimental solution works fine for me, but another solution would be to simply switch from ts-node to tsx internally

We tried that approach and, with our current setup, it's not possible to swap from ts-node to tsx without introducing breaking changes. As @kanej said, it's one of the key items we'll focus over the next months. Rest assured, full ESM support is on the way.

Feel free to ignore, but just curious what are the blockers/breaking changes for switching hardhat to tsx? Also breaking change is not a big deal IMO if it allows to shed some legacy support and help move the whole dev ecosystem to a modern tooling and approaches

@fullkomnun
Copy link

fullkomnun commented Feb 26, 2024

Thanks for adding this support!

Recently migrated a TS project to ESM and here's my feedback:

  1. Most of the codebase has been succesfully migrated (tests, scripts etc) except for hardhat.config and some related setup utils and tasks.
  2. I had to patch hardhat-deploy (see this) but was able to get it to load both CJS/ESM deployment scripts transparently. I'm not sure how should proper support be added to the plugin itself.
  3. The verbosity of NODE_OPTIONS is quite annoying but I was able to hide it away when using mocha directly (via .mocharc) or when using a wrapper script to keep package.json clean. This also allows applying type checking conditionally based on HARDHAT_TYPECHECK env var (which by itself no longer affect type-check).
  4. In addition to the configuration you mentioned I found that running tests in-parallel fails unless I also add "experimentalSpecifierResolution": "node":
  "ts-node": {
    "experimentalSpecifierResolution": "node",
    "experimentalResolver": true,
    "files": true,
  },

with the following error:

  1) Uncaught error outside test suite:
     Uncaught Cannot find module '<REDACTED>/solidity/node_modules/hardhat/register' imported from <REDACTED>/solidity/node_modules/mocha/lib/nodejs/esm-utils.js
      at finalizeResolution (node_modules/ts-node/dist-raw/node-internal-modules-esm-resolve.js:366:11)
      at moduleResolve (node_modules/ts-node/dist-raw/node-internal-modules-esm-resolve.js:801:10)
      at Object.defaultResolve (node_modules/ts-node/dist-raw/node-internal-modules-esm-resolve.js:912:11)
      at <REDACTED>/solidity/node_modules/ts-node/src/esm.ts:218:35
      at entrypointFallback (node_modules/ts-node/src/esm.ts:168:34)
      at <REDACTED>/solidity/node_modules/ts-node/src/esm.ts:217:14
      at addShortCircuitFlag (node_modules/ts-node/src/esm.ts:409:21)
      at resolve (node_modules/ts-node/src/esm.ts:197:12)
      at nextResolve (node:internal/modules/esm/hooks:865:28)
      at Hooks.resolve (node:internal/modules/esm/hooks:303:30)

Could be easily reproduced here
5. When running ESM tests/scripts (as opposed to CJS) reported LOC in call traces appear to be shifted which makes it harder to debug. Could be easily reproduced here.
It is probably a bug in ts-node, and there have been reports of similar issues probably due to a different root cause.

Failed attempt to mitigate:

  • Tried to use: Node 18 or Node 21.
  • Tried to use the beta release of ts-node '11.0.0-beta.1'
  • Verified that we use latest versions of typescript and ts-node
  • Forced 'hardhat' to use specific versions (latest) of mocha and ts-node (NOTE: issue is not restricted to tests!)
  • Tried to play with tsconfig and NODE_OPTIONS (like add --enable-source-maps)
  1. There's this rare issue which is hard to reproduce

@sim31
Copy link

sim31 commented Jun 5, 2024

I experience the shifted line numbers in stack traces as well. Thanks @fullkomnun for your report, saved me time from trying these mitigations myself.

@pogilvie
Copy link

It's 2024 and I'd like to start new projects with Typescript and ESM support. It would be create to support a runtime like Bun or Deno which supports these natively out of the box.

@Ahmedborwin
Copy link

Ahmedborwin commented Jun 13, 2024

I am trying to migrate a scaffold-eth project to allow for hardhat ESM support. Repo: https://github.com/Ahmedborwin/cryptoSoccer.

I have followed the instructions listed by @schaable but I still get the much-loved HH19 error when I try to import hardhat tasks (that I got from the chainlink functions boilerplate) to my hardhat.config.cts.

The tasks folder is made up of .js scripts that are common modules. Not sure why importing them is causing the error in the first place. I tried converting them to .cjs but still no luck.

Anyone have any idea how I can make these hardhat tasks available to my hardhat typescript project?

If this question is badly worded, please be patient with me. I am learning. Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
effort:difficult status:blocked Blocked by other issues or external reasons type:feature Feature request
Projects
Status: Blocked
Development

No branches or pull requests