Last active
June 5, 2020 08:09
-
-
Save LarsDenBakker/db652738005bb7d0a973fdb8f8d76823 to your computer and use it in GitHub Desktop.
Support esm config in node commonjs projects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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 loadednode 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