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

Support executing ESM schematics

Open Platonn opened this issue 3 years ago • 7 comments

🚀 Feature request

Support schematics written in ES Modules. Currently only CommonJS schematics are supported.

Command (mark with an x)

  • [ ] new
  • [ ] build
  • [ ] serve
  • [ ] test
  • [ ] e2e
  • [ ] generate
  • [ ] add
  • [ ] update
  • [ ] lint
  • [ ] extract-i18n
  • [ ] run
  • [ ] config
  • [ ] help
  • [ ] version
  • [ ] doc
  • [x] other: compiling custom schematics

Description

Currently custom (and official) schematics can execute only CommonJS code, but not ES Modules. This is problematic when you want to import an ES Module in your custom schematics, for example HtmlParser from @angular/compiler (which since ng13 is shipped only as ESM).

Problems with not supporting ESM:

The following error started to occur for our custom schematics in runtime, since we upgraded from ng12 to 13: require() of ES Module <path-to-the-repo>/node_modules/@angular/compiler/fesm2015/compiler.mjs not supported. Instead change the require of <path-to-the-repo>/node_modules/@angular/compiler/fesm2015/compiler.mjs to a dynamic import() which is available in all CommonJS modules.

But the advised change of the static @angular/compiler to a dynamic import is cumbersome due to various reasons:

  • it unnecessarily changes the our synchronous code to asynchronous code
  • it induces passing down the compilerModule (result of await import(@angular/compiler)) as an argument down to all helper functions (example in angular repo)
  • it requires a hacky workaround ticking the Typescript compiler so to avoid compiling the dynamic import() into the require() call - for more see the workaround function loadEsmModule() in angular repo . Btw. this function is not exported in public API, so we need to copy-paste it to our repo.

Describe the solution you'd like

Support executing ESM schematics .

Describe alternatives you've considered

Change the import of ESM to dynamic imports in our schematics code and deal with all its cumbersome consequences (described above).

Platonn avatar Mar 02 '22 10:03 Platonn

This feature request is now candidate for our backlog! In the next phase, the community has 60 days to upvote. If the request receives more than 20 upvotes, we'll move it to our consideration list.

You can find more details about the feature request process in our documentation.

angular-robot[bot] avatar Mar 02 '22 13:03 angular-robot[bot]

Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends.

Find more details about Angular's feature request process in our documentation.

angular-robot[bot] avatar Apr 10 '22 13:04 angular-robot[bot]

I only started using schematics, so there's a good chance the following suggestion might not work for you according to your case.

Generally speaking, I've always found passing strings for module paths and then letting some 3rd party library resolve it causing more problems than it's solving.

Is there any reason we don't let the caller resolve the module and pass the resolved value, then @angular/schematics can work directly with the resolved value without having to worry about how to resolve it?

This also enables much easier implementation for type support, by defining generics that end users can make use of because they'd have the type of the value they're passing at development time out of the box while passing strings for the paths would require manually passing a generic type to get type safety.

I've seen @hapi/hapi support both ways of working with modules, by both passing the string and the value.

So one non-breaking change we could do here is support passing the value directly, that way we won't have to wait for a new major version to unblock people from migrating to ESM. Would happily try and make a PR for that.

What do you think?

AbdelrahmanHafez avatar May 06 '22 12:05 AbdelrahmanHafez

So is there any progress on this issue now?

DawnSouther avatar Sep 19 '24 09:09 DawnSouther

As of node 22.12, is it now possible to require native ES modules like @angular/compiler synchronously so the dynamic import workaround in "Describe alternatives you've considered" is not necessary if you are using that version or a newer one.

I think this issue still has merit since supporting ESM Schematics and/or migrating the devkit to ESM would be a good move once some Angular packages already do not support CommonJS.

mmarinero avatar Jan 30 '25 17:01 mmarinero

This issue also makes it difficult to use ESM-native tooling like Vite/Vitest for building and testing our custom schematics.

allout58 avatar Mar 05 '25 15:03 allout58

Came across this issue as a potential blocker for ESM Transition Plan for AnalogJS v2.0.0-alpha #1844 Currently conducting research and appreciate any feedback.

benpsnyder avatar Aug 18 '25 15:08 benpsnyder