diff --git a/packages/commonjs/README.md b/packages/commonjs/README.md index 6aff1ee2e..66432e503 100644 --- a/packages/commonjs/README.md +++ b/packages/commonjs/README.md @@ -174,6 +174,49 @@ If you set `esmExternals` to `true`, this plugins assumes that all external depe You can also supply an array of ids to be treated as ES modules, or a function that will be passed each external id to determine if it is an ES module. +### `defaultIsModuleExports` + +Type: `boolean | "auto"`
+Default: `"auto"` + +Controls what is the default export when importing a CommonJS file from an ES module. + +- `true`: The value of the default export is `module.exports`. This currently matches the behavior of Node.js when importing a CommonJS file. + ```js + // mod.cjs + exports.default = 3; + ``` + ```js + import foo from './mod.cjs'; + console.log(foo); // { default: 3 } + ``` +- `false`: The value of the default export is `exports.default`. + ```js + // mod.cjs + exports.default = 3; + ``` + ```js + import foo from './mod.cjs'; + console.log(foo); // 3 + ``` +- `"auto"`: The value of the default export is `exports.default` if the CommonJS file has an `exports.__esModule === true` property; otherwise it's `module.exports`. This makes it possible to import + the default export of ES modules compiled to CommonJS as if they were not compiled. + ```js + // mod.cjs + exports.default = 3; + ``` + ```js + // mod-compiled.cjs + exports.__esModule = true; + exports.default = 3; + ``` + ```js + import foo from './mod.cjs'; + import bar from './mod-compiled.cjs'; + console.log(foo); // { default: 3 } + console.log(bar); // 3 + ``` + ### `requireReturnsDefault` Type: `boolean | "namespace" | "auto" | "preferred" | ((id: string) => boolean | "auto" | "preferred")`
diff --git a/packages/commonjs/src/generate-exports.js b/packages/commonjs/src/generate-exports.js index 2818c65ed..4a30cb5ff 100644 --- a/packages/commonjs/src/generate-exports.js +++ b/packages/commonjs/src/generate-exports.js @@ -20,7 +20,8 @@ export function rewriteExportsAndGetExportsBlock( isRestorableCompiledEsm, code, uses, - HELPERS_NAME + HELPERS_NAME, + defaultIsModuleExports ) { const namedExportDeclarations = [`export { ${moduleName} as __moduleExports };`]; const moduleExportsPropertyAssignments = []; @@ -75,19 +76,29 @@ export function rewriteExportsAndGetExportsBlock( // Generate default export const defaultExport = []; - if (isRestorableCompiledEsm) { - defaultExport.push(`export default ${deconflictedDefaultExportName || moduleName};`); - } else if ( - (wrapped || deconflictedDefaultExportName) && - (defineCompiledEsmExpressions.length > 0 || code.indexOf('__esModule') >= 0) - ) { - // eslint-disable-next-line no-param-reassign - uses.commonjsHelpers = true; - defaultExport.push( - `export default /*@__PURE__*/${HELPERS_NAME}.getDefaultExportFromCjs(${moduleName});` - ); - } else { + if (defaultIsModuleExports === 'auto') { + if (isRestorableCompiledEsm) { + defaultExport.push(`export default ${deconflictedDefaultExportName || moduleName};`); + } else if ( + (wrapped || deconflictedDefaultExportName) && + (defineCompiledEsmExpressions.length > 0 || code.includes('__esModule')) + ) { + // eslint-disable-next-line no-param-reassign + uses.commonjsHelpers = true; + defaultExport.push( + `export default /*@__PURE__*/${HELPERS_NAME}.getDefaultExportFromCjs(${moduleName});` + ); + } else { + defaultExport.push(`export default ${moduleName};`); + } + } else if (defaultIsModuleExports === true) { defaultExport.push(`export default ${moduleName};`); + } else if (defaultIsModuleExports === false) { + if (deconflictedDefaultExportName) { + defaultExport.push(`export default ${deconflictedDefaultExportName};`); + } else { + defaultExport.push(`export default ${moduleName}.default;`); + } } return `\n\n${defaultExport diff --git a/packages/commonjs/src/index.js b/packages/commonjs/src/index.js index 79015294b..bdb92bcdc 100644 --- a/packages/commonjs/src/index.js +++ b/packages/commonjs/src/index.js @@ -59,6 +59,8 @@ export default function commonjs(options = {}) { : Array.isArray(esmExternals) ? ((esmExternalIds = new Set(esmExternals)), (id) => esmExternalIds.has(id)) : () => esmExternals; + const defaultIsModuleExports = + typeof options.defaultIsModuleExports === 'boolean' ? options.defaultIsModuleExports : 'auto'; const { dynamicRequireModuleSet, dynamicRequireModuleDirPaths } = getDynamicRequirePaths( options.dynamicRequireTargets @@ -145,7 +147,8 @@ export default function commonjs(options = {}) { dynamicRequireModuleSet, disableWrap, commonDir, - ast + ast, + defaultIsModuleExports ); } diff --git a/packages/commonjs/src/transform-commonjs.js b/packages/commonjs/src/transform-commonjs.js index ccb32a565..e37271a8e 100644 --- a/packages/commonjs/src/transform-commonjs.js +++ b/packages/commonjs/src/transform-commonjs.js @@ -53,7 +53,8 @@ export default function transformCommonjs( dynamicRequireModuleSet, disableWrap, commonDir, - astCache + astCache, + defaultIsModuleExports ) { const ast = astCache || tryParse(parse, code, id); const magicString = new MagicString(code); @@ -470,7 +471,8 @@ export default function transformCommonjs( isRestorableCompiledEsm, code, uses, - HELPERS_NAME + HELPERS_NAME, + defaultIsModuleExports ); const importBlock = rewriteRequireExpressionsAndGetImportBlock( diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-__esModule/_config.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-__esModule/_config.js new file mode 100755 index 000000000..466f62535 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-__esModule/_config.js @@ -0,0 +1,5 @@ +module.exports = { + options: { + defaultIsModuleExports: 'auto' + } +}; diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-__esModule/input.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-__esModule/input.js new file mode 100755 index 000000000..d4efb165b --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-__esModule/input.js @@ -0,0 +1,3 @@ +exports.__esModule = true; +exports.default = 2; +exports.named = 3; diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-__esModule/output.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-__esModule/output.js new file mode 100755 index 000000000..29b4b47c3 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-__esModule/output.js @@ -0,0 +1,11 @@ +var _default = 2; +var named = 3; + +var input = /*#__PURE__*/Object.defineProperty({ + default: _default, + named: named +}, '__esModule', {value: true}); + +export default _default; +export { input as __moduleExports }; +export { named }; \ No newline at end of file diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-no-__esModule/_config.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-no-__esModule/_config.js new file mode 100755 index 000000000..466f62535 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-no-__esModule/_config.js @@ -0,0 +1,5 @@ +module.exports = { + options: { + defaultIsModuleExports: 'auto' + } +}; diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-no-__esModule/input.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-no-__esModule/input.js new file mode 100755 index 000000000..562cc1abe --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-no-__esModule/input.js @@ -0,0 +1,2 @@ +exports.default = 2; +exports.named = 3; diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-no-__esModule/output.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-no-__esModule/output.js new file mode 100755 index 000000000..9e4a115e8 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-auto-no-__esModule/output.js @@ -0,0 +1,11 @@ +var _default = 2; +var named = 3; + +var input = { + default: _default, + named: named +}; + +export default input; +export { input as __moduleExports }; +export { named }; \ No newline at end of file diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-__esModule/_config.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-__esModule/_config.js new file mode 100755 index 000000000..d4402a7ee --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-__esModule/_config.js @@ -0,0 +1,5 @@ +module.exports = { + options: { + defaultIsModuleExports: false + } +}; diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-__esModule/input.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-__esModule/input.js new file mode 100755 index 000000000..d4efb165b --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-__esModule/input.js @@ -0,0 +1,3 @@ +exports.__esModule = true; +exports.default = 2; +exports.named = 3; diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-__esModule/output.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-__esModule/output.js new file mode 100755 index 000000000..29b4b47c3 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-__esModule/output.js @@ -0,0 +1,11 @@ +var _default = 2; +var named = 3; + +var input = /*#__PURE__*/Object.defineProperty({ + default: _default, + named: named +}, '__esModule', {value: true}); + +export default _default; +export { input as __moduleExports }; +export { named }; \ No newline at end of file diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-__esModule/_config.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-__esModule/_config.js new file mode 100755 index 000000000..d4402a7ee --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-__esModule/_config.js @@ -0,0 +1,5 @@ +module.exports = { + options: { + defaultIsModuleExports: false + } +}; diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-__esModule/input.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-__esModule/input.js new file mode 100755 index 000000000..562cc1abe --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-__esModule/input.js @@ -0,0 +1,2 @@ +exports.default = 2; +exports.named = 3; diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-__esModule/output.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-__esModule/output.js new file mode 100755 index 000000000..de8e0862a --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-__esModule/output.js @@ -0,0 +1,11 @@ +var _default = 2; +var named = 3; + +var input = { + default: _default, + named: named +}; + +export default _default; +export { input as __moduleExports }; +export { named }; \ No newline at end of file diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-default/_config.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-default/_config.js new file mode 100755 index 000000000..d4402a7ee --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-default/_config.js @@ -0,0 +1,5 @@ +module.exports = { + options: { + defaultIsModuleExports: false + } +}; diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-default/input.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-default/input.js new file mode 100755 index 000000000..fd2304246 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-default/input.js @@ -0,0 +1 @@ +exports.named = 3; diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-default/output.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-default/output.js new file mode 100755 index 000000000..81484f1e4 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-false-no-default/output.js @@ -0,0 +1,9 @@ +var named = 3; + +var input = { + named: named +}; + +export default input.default; +export { input as __moduleExports }; +export { named }; \ No newline at end of file diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-__esModule/_config.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-__esModule/_config.js new file mode 100755 index 000000000..a57f02831 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-__esModule/_config.js @@ -0,0 +1,5 @@ +module.exports = { + options: { + defaultIsModuleExports: true + } +}; diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-__esModule/input.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-__esModule/input.js new file mode 100755 index 000000000..d4efb165b --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-__esModule/input.js @@ -0,0 +1,3 @@ +exports.__esModule = true; +exports.default = 2; +exports.named = 3; diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-__esModule/output.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-__esModule/output.js new file mode 100755 index 000000000..f997b9eaf --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-__esModule/output.js @@ -0,0 +1,11 @@ +var _default = 2; +var named = 3; + +var input = /*#__PURE__*/Object.defineProperty({ + default: _default, + named: named +}, '__esModule', {value: true}); + +export default input; +export { input as __moduleExports }; +export { named }; \ No newline at end of file diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-no-__esModule/_config.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-no-__esModule/_config.js new file mode 100755 index 000000000..a57f02831 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-no-__esModule/_config.js @@ -0,0 +1,5 @@ +module.exports = { + options: { + defaultIsModuleExports: true + } +}; diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-no-__esModule/input.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-no-__esModule/input.js new file mode 100755 index 000000000..562cc1abe --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-no-__esModule/input.js @@ -0,0 +1,2 @@ +exports.default = 2; +exports.named = 3; diff --git a/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-no-__esModule/output.js b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-no-__esModule/output.js new file mode 100755 index 000000000..9e4a115e8 --- /dev/null +++ b/packages/commonjs/test/fixtures/form/defaultIsModuleExports-true-no-__esModule/output.js @@ -0,0 +1,11 @@ +var _default = 2; +var named = 3; + +var input = { + default: _default, + named: named +}; + +export default input; +export { input as __moduleExports }; +export { named }; \ No newline at end of file