Skip to content

Instantly share code, notes, and snippets.

@LarsDenBakker
Last active June 5, 2020 08:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LarsDenBakker/db652738005bb7d0a973fdb8f8d76823 to your computer and use it in GitHub Desktop.
Save LarsDenBakker/db652738005bb7d0a973fdb8f8d76823 to your computer and use it in GitHub Desktop.
Support esm config in node commonjs projects
const fs = require('fs');
const path = require('path');
const extensions = ['.mjs', '.cjs', '.js'];
async function loadConfig(name) {
// check if node version supports dynamic imports
const supportsEsm = await (async () => {
try {
await import(__filename);
} catch (error) {
return false;
}
return true;
})();
const configName = path.join(process.cwd(), `${name}.config`);
if (!supportsEsm) {
const resolvedPath = require.resolve(configName);
// node version doesn't support ESM, load it as cjs
return fs.existsSync(resolvedPath) ? require(resolvedPath) : undefined;
}
// load config using dynamic import, resolving .mjs over .cjs over .js.
// this supports configs written in CJS and ESM, using node's project configuration
for (const extension of extensions) {
const resolvedPath = `${configName}${extension}`;
if (fs.existsSync(resolvedPath)) {
return import(resolvedPath);
}
}
}
// example usage
(async () => {
const config = await loadConfig('my-project');
console.log('config', config);
})();
@LarsDenBakker
Copy link
Author

LarsDenBakker commented Jun 5, 2020

This code snippet allows node projects shipped as commonjs to support user configs written in es modules as well as common js.

It uses node's logic for deciding if a file is ESM or CJS, based on package.json or file extension. On node versions which don't support es modules at all, commonjs is always used.

Examples:

node v10

<my-project>.config.js is always loaded

node v12 (latest), v13 & v14

<my-project>.config.mjs -> config is loaded as esm
<my-project>.config.cjs -> config is loaded as cjs
<my-project>.config.js -> config is loaded based on project package.json type

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment