nest-cli icon indicating copy to clipboard operation
nest-cli copied to clipboard

Ability to create projects with ESM pre-configured

Open vemv opened this issue 1 year ago • 11 comments

Is there an existing issue that is already proposing this?

  • [X] I have searched the existing issues

Is your feature request related to a problem? Please describe it

While I understand that NestJS, the framework, is written in CommonJS, and that there's no immediate problem with that, I'm under the impression that users most often want their apps to be set up to consume/emit ESM.

The NestJS CLI creates apps assuming CommonJS, so pure ESM libraries won't work out of the box.

Adapting a NestJS app to work with ESM needs somewhat detailed knowledge, and misc surgery. Some folks don't even know it's possible to make it work, which isn't a good look for NestJS.

Describe the solution you'd like

A new option in the wizard that expressed the user intent to have their project use a ESM compilation pipeline.

The differences seem relatively tiny, and described in this document:

  • Make sure you are using TypeScript 4.7 or later.
  • Add "type": "module" to your package.json.
  • Replace "main": "index.js" with "exports": "./index.js" in your package.json.
  • Update the "engines" field in package.json to Node.js 18: "node": ">=18".
  • Add "module": "node16", "moduleResolution": "node16" to your tsconfig.json. (Example)
  • moduleResolution must be set to node16 or nodenext, NOT node!
  • Use only full relative file paths for imports: import x from '.'; → import x from './index.js';.
  • Remove namespace usage and use export instead.
  • Use the node: protocol for Node.js built-in imports.
  • You must use a .js extension in relative imports even though you're importing .ts files.

Teachability, documentation, adoption, migration strategy

If this option was successfully implemented, perhaps it could eventually become the default?

What is the motivation / use case for changing the behavior?

The ability to consume pure ESM libs, and the reduced burden given to users.

vemv avatar Dec 27 '24 09:12 vemv

You can already consume esm libraries if using recent versions of node 22 and typescript 5.8 and nodenext

jadejr avatar Apr 08 '25 03:04 jadejr

Hi @jadejr, I'm aware of that but this issue was asking for a CLI preset so that users don't have to figure this out on their own.

vemv avatar Apr 08 '25 04:04 vemv

The main motivation is:

The ability to consume pure ESM libs, and the reduced burden given to users.

I was wrong in my post because i forgot you had to change module to node20, node22, or nodenext in tsconfig.json to consume es modules in a common js project. So we need to add that to the preset, but that doesn't mean one has to convert the whole project to ESM.

The preset idea for making ESM projects out of the box is useful in it's own right beyond just consuming ESM.

jadejr avatar Apr 08 '25 19:04 jadejr

The main motivation is:

The ability to consume pure ESM libs, and the reduced burden given to users.

I was wrong in my post because i forgot you had to change module to node20, node22, or nodenext in tsconfig.json to consume es modules in a common js project. So we need to add that to the preset, but that doesn't mean one has to convert the whole project to ESM.

The preset idea for making ESM projects out of the box is useful in it's own right beyond just consuming ESM.

Is there more documentation on how-to do this? I'm trying to use some ESM only module and I can't

albjeremias avatar May 07 '25 10:05 albjeremias

@albjeremias : You must use nodenext for module in tsconfig, typescript 5.8, and a recent version of node 20, 22, or 23. In typescript 5.9 you'll be able to use node20 or node22 for module. Do not change moduleResolution

jadejr avatar May 07 '25 14:05 jadejr

hi! :)

@albjeremias : You must use nodenext for module in tsconfig, typescript 5.8, and a recent version of node 20, 22, or 23. In typescript 5.9 you'll be able to use node20 or node22 for module. Do not change moduleResolution

here i made all the changes suggested https://github.com/helpbuttons/helpbuttons/pull/1189/files

changing typescript version to 5.9, change module in tsconfig to nodenext

but now I get this error, even though fedify is installed in node_modules!

src/modules/fediverse/fedify.middleware.ts:3:61 - error TS2307: Cannot find module '@fedify/fedify' or its corresponding type declarations.

3 import { createFederation, Federation, MemoryKvStore } from "@fedify/fedify";
                                                              ~~~~~~~~~~~~~~~~

[17:37:01] Found 1 error. Watching for file changes.

and my node version v23.9.0

albjeremias avatar May 07 '25 16:05 albjeremias

@albjeremias typescript 5.9 isn't out yet is it? Let's not turn this into a help session for some other issue unrelated to nest-cli.

jadejr avatar May 08 '25 00:05 jadejr

@albjeremias typescript 5.9 isn't out yet is it? Let's not turn this into a help session for some other issue unrelated to nest-cli.

i tried with typescript 5.9 (available using yarn at least, shows a list to use a dev branch) and typescript 5.8. if you can point me out to documentation explaining your suggestion id be very greatful.

thanks for the support until now. I found many people requesting help on this issue, and not many clear solutions.

albjeremias avatar May 08 '25 11:05 albjeremias

@albjeremias From what i can tell this is no longer about nest-cli. I think it's time to open a discussion on nestjs discussions or the nestjs discord for help with attempting to use nestjs with esm. If it's general typescript support then you'd need to find the appropriate place for that

jadejr avatar May 08 '25 18:05 jadejr

1. Make sure you are using TypeScript 4.7 or later.
2. Add "type": "module" to your package.json.
3. Replace "main": "index.js" with "exports": "./index.js" in your package.json.
4. Update the "engines" field in package.json to Node.js 18: "node": ">=18".
5. Add ["module": "node16", "moduleResolution": "node16"](https://www.typescriptlang.org/tsconfig#module) to your tsconfig.json. ([Example](https://github.com/sindresorhus/tsconfig/blob/main/tsconfig.json))
6. moduleResolution must be set to node16 or nodenext, NOT node!
7. Use only full relative file paths for imports: import x from '.'; → import x from './index.js';.
8. Remove namespace usage and use export instead.
9. Use the [node: protocol](https://nodejs.org/api/esm.html#esm_node_imports) for Node.js built-in imports.
10. You must use a .js extension in relative imports even though you're importing .ts files.

Standard mode, It's work. Does anyone use ESM in monorepo model microservices?

zhangstar666 avatar Jun 11 '25 09:06 zhangstar666

i tried with typescript 5.9 (available using yarn at least, shows a list to use a dev branch) and typescript 5.8. if you can point me out to documentation explaining your suggestion id be very greatful.

thanks for the support until now. I found many people requesting help on this issue, and not many clear solutions.

This repo support ESM:https://github.com/CatsMiaow/nestjs-project-performance

zhangstar666 avatar Jun 11 '25 09:06 zhangstar666