module-alias: Not working with native ES modules
I’m moving a project over to using node’s native ES modules (enabled with the --experimental-modules
flag). After updating my code, module-alias is no longer working. I tried adding this to the root of my app (this is the method I was using before transitioning to esm):
require('module-alias/register')
I tried changing it to:
import 'module-alias/register'
I tried requiring when starting the server:
node --experimental-modules -r module-alias/register server/app.js
The first aliased import in my app is this:
import {responseError} from '@app/lib/response'
I’m getting this error from it:
internal/modules/esm/default_resolve.js:69
let url = moduleWrapResolve(specifier, parentURL);
^
Error: Cannot find package '@app/lib' imported from server/app.js
at Loader.resolve [as _resolve] (internal/modules/esm/default_resolve.js:69:13)
at Loader.resolve (internal/modules/esm/loader.js:70:33)
at Loader.getModuleJob (internal/modules/esm/loader.js:143:40)
at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:43:40)
at link (internal/modules/esm/module_job.js:42:36)
The relevant lines in my package.json are:
"_moduleAliases": {
"@app": "./server"
},
I’m starting the app like this:
node --experimental-modules server/app.js
module-alias worked fine using CommonJS. The only change I made to the code was changing require
s to import
s.
About this issue
- Original URL
- State: open
- Created 5 years ago
- Reactions: 32
- Comments: 27
@cullylarson Ran into the same issue.
It appears that the new esm code isn’t running the _resolveFilename which is the core of this library. Based on the docs it looks as though they are moving off of this library’s hack and onto a standard feature: https://github.com/nodejs/node/blob/master/doc/api/esm.md#experimental-loader-hooks It’s still experimental though.
I rewrote and reduced a lot based on known things within my library but this code is working for me:
Then:
node --no-warnings --experimental-modules --es-module-specifier-resolution=node --loader ./custom-loader.mjs index.js
Not yet solved natively without execution flags?
I understand that this is kind of an issue with Node itself, but it would be nice if the README included a warning about this package not being compatible with native ES modules. I just spent an hour questioning my sanity only to find out that the feature I’ve been hopelessly debugging was never intended to work at all.
@Kehrlann Thanks for the kind invitation to do a PR. I really appreciate the way you presented it. I’m near a deadline on a project right now and about to start another, otherwise I would take you up on the offer.
In this code there is a problem with Windows paths.
I made an npm module using this code that fixes also that problem, check it out here: esm-module-alias
Very interesting ! So if I understand correctly, you must just provide a .js file in a --loader flag ; and that .js file be a module that exports a
resolve
function, which basically does whatmodule-alias
does. (There might be a chicken and egg problem if you want to usemodule-alias
programmatically though)So it’d be very easy to do a pull request (wink wink, nudge nudge) that exports a neat little module that wraps
module-aliases
’ resolve function, which can then be used like (rough idea, semantics TBD) :node --no-warnings --experimental-modules --es-module-specifier-resolution=node --loader ./node_modules/module-alias/es6-loader.js index.js
@cullylarson @jdt3969 interested in doing a PR ?
@ilearnio any additional thoughts ?
Later. Imagine I published a package that relied on starting node with
--experimental-loader
but then I’d also publish it to npm for others to use it. Now they’d have to be aware that now their project too as to be started with--experimental-loader
.That makes it unusable for npm packages until a version of node is out that removes the flag.
This is really interesting and the gist looks promising @jshado1.
But I’m wondering if this functionality can already be used when publishing a module to npm. I guess not, because how am I supposed to specify
--experimental-loader=./alias-loader.mjs ./index.mjs
as a user of said module?You guys think we can do this without using the
--loader
flag and instead do it programmatically? Now thatModule._resolveFilename
isn’t being used forimport
statements I wonder what is. May dive into it this week.