A more 2019 version, working for ES Modules.
The easiest way I've found so far is to use the experimental feature --loader
.
I use something like that to be able to require import { SOME_CONSTANT } from '@config'
or import { createConnection } from '@server/connection'
.
The loader code:
import path from 'path'
import fs from 'fs'
export function resolve (specifier, parentModuleURL, defaultResolver) {
specifier = specifier.replace(/^@/, path.resolve('.') + '/src/')
specifier = fs.existsSync(specifier) && fs.lstatSync(specifier).isDirectory() ? `${specifier}/index` : specifier
specifier += '.js'
return defaultResolver(specifier, parentModuleURL)
}
Then node --experimental-modules --loader ./moduleResolver.js ./myScriptWithoutExtension
NOTE: you don't need to use .mjs
extension if you specify a "type": "module"
in the nearest package.json
. You can stay extensionless.
NOTE2: you can replace the src
string with where you usually put your code, you could even have a process.env.NODE_ENV
based resolution.
NOTE3: If you give a directory to @
, it will expect to find an index.js
file.
NOTE4: You can use whateveer you want for aliasing, just replace the regex
import
instead ofrequire
, I get cryptic errors in the terminal. – Neoma../
anywhere in my Node.js project.app-module-path
allows me to do this by callingrequire('app-module-path/register')
in the root directory. That way I can reference all folders in the root such asrequire('some-directory/a-file')
from anywhere in the project even though that file is in the root directory. There don't seem to be any solutions to do this with the import syntax. Webpack has directory aliases so I figure there's gotta be a Node.js way. – Neoma