Skip to content Skip to sidebar Skip to footer

How To Trick Node.js To Load .js Files As Es6 Modules?

Node.JS 10 added experimental support for loading ES6 modules, which already work in browsers. That would mean that we could finally use exactly the same files for Node.JS and brow

Solution 1:

You can now import .js file in node v12.x, in 2 steps:

  • Add the following line in your package.json file:
// package.json
{
  "type": "module"
}
  • Add --experimental-modules flag before the script:
node --experimental-modules index.js

Reference: https://nodejs.org/api/esm.html

Solution 2:

Node.js requires all ES modules should have .mjs extension. Since Node.js support of ES modules is experimental, this is subject to change. A proposal and open pull request are expected to address this problem with package.json esm flag and --mode option.

Currently this can be solved with custom ES module loader that hooks into default module resolver and changes module type for some modules:

custom-loader.mjs

import path from'path';

constESM_WITH_JS_EXT = './MyFile.js'; // relative to loader pathconstESM_WITH_JS_EXT_URL = newURL(path.dirname(import.meta.url) + `/${ESM_WITH_JS_EXT}`).href;

exportfunctionresolve(specifier, parentModuleURL, defaultResolver) {
    const resolvedModule = defaultResolver(specifier, parentModuleURL);

    if (resolvedModule.url === ESM_WITH_JS_EXT_URL)
        resolvedModule.format = 'esm';

    return resolvedModule;
}

It is used as:

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

Since there are fundamental differences in how ES and CommonJS modules are evaluated, the changes should be limited to modules that need them.

Solution 3:

I solved exactly this problem with the fabulous esm package. You can enable dynamic (smart) esm module loading package wide, or per run with a flag like this:

node -r esm your/es6/module.js

It also has options to treat every file as a es6 module, or only those ending in '.mjs'. There are other packages out there, but this one just worked.

Solution 4:

Import and export modules using ES6 that work with Node.js

Name files with .mjs extension instead of .js

Create files

touch main.mjs lib.mjs

main.js

import { add } from'./lib.mjs';
console.log(add(40, 2));

lib.mjs

exportletadd = (x,y) => {
  return x + y
}

Run

node --experimental-modulesmain.js

Solution 5:

Here is a module that does what you need esmjs.mjs

import { readFileSync } from'fs'import { fileURLToPath, pathToFileURL } from'url'import { dirname, join } from'path'exportconstjsmodule = (test_url_or_path, module_path) => {

    const __filename = test_url_or_path.toLowerCase().startsWith('file:')
        ? fileURLToPath(test_url_or_path)
        : test_url_or_path

    const __dirname = dirname(__filename)

    const abs_path = join(__dirname, module_path)
    const file_url = pathToFileURL(abs_path)

    const file_buf = readFileSync(file_url)
    const b64 = file_buf.toString('base64')

    const moduleData = "data:text/javascript;base64," + b64

    returnimport(moduleData)
}

Usage from .mjs module:

const { hey } = awaitjsmodule(import.meta.url, '../../test-data/mjs.js')

Usage, from .js file:

const { hey } = awaitjsmodule(__filename, '../../test-data/mjs.js')

Reference & tests on Github

Post a Comment for "How To Trick Node.js To Load .js Files As Es6 Modules?"