Search code examples
node.jses6-modulesmjs

Importing using relative paths in Node.js with ES Modules


In the past, I used app-module-path whenever I wanted to have relative paths in my Node.js apps. If I use ES Modules through the .mjs format, how do I have the same functionality where a certain directory path becomes relative?

In an alternative way, would I be able to assign an alias to a directory instead so all relative paths are relative to that alias much like how ./ is an alias for a path being relative to the current directory.


Solution

  • It's possible to give aliases to certain paths for CommonJS modules that are loaded with require by monkey-patching built-in module module.

    ES modules provide a way to change module loading behaviour by specifying custom ES module loader, as explained in this related answer.

    This way root source path (which will be specified relatively to loader location) can be mapped to some alias (@ is conventional for front-end projects):

    custom-loader.mjs

    import path from 'path';
    
    const ROOT_PATH = new URL(path.dirname(import.meta.url) + '/src').pathname;
    
    export function resolve(specifier, parentModuleURL, defaultResolver) {
        specifier = specifier.replace(/^@/, ROOT_PATH);
        return defaultResolver(specifier, parentModuleURL);
    }
    

    Which is used like:

    node --experimental-modules --loader ./custom-loader.mjs ./app.mjs
    

    Notice that this provides a behaviour that isn't natural for ES modules, this may affect how this code is treated by other tools like IDEs.