Skip to content

Commit bfe60d3

Browse files
nicolo-ribaudoguybedford
authored andcommitted
feat(commonjs): Add defaultIsModuleExports option to match Node.js behavior (#838)
* [commonjs] Add `nodeDefaultImport` option to match Node.js behavior * Undo unrelated changes * Undo editor autoformatter * Change option
1 parent c328e2c commit bfe60d3

File tree

25 files changed

+201
-16
lines changed

25 files changed

+201
-16
lines changed

packages/commonjs/README.md

+43
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,49 @@ If you set `esmExternals` to `true`, this plugins assumes that all external depe
174174

175175
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.
176176

177+
### `defaultIsModuleExports`
178+
179+
Type: `boolean | "auto"`<br>
180+
Default: `"auto"`
181+
182+
Controls what is the default export when importing a CommonJS file from an ES module.
183+
184+
- `true`: The value of the default export is `module.exports`. This currently matches the behavior of Node.js when importing a CommonJS file.
185+
```js
186+
// mod.cjs
187+
exports.default = 3;
188+
```
189+
```js
190+
import foo from './mod.cjs';
191+
console.log(foo); // { default: 3 }
192+
```
193+
- `false`: The value of the default export is `exports.default`.
194+
```js
195+
// mod.cjs
196+
exports.default = 3;
197+
```
198+
```js
199+
import foo from './mod.cjs';
200+
console.log(foo); // 3
201+
```
202+
- `"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
203+
the default export of ES modules compiled to CommonJS as if they were not compiled.
204+
```js
205+
// mod.cjs
206+
exports.default = 3;
207+
```
208+
```js
209+
// mod-compiled.cjs
210+
exports.__esModule = true;
211+
exports.default = 3;
212+
```
213+
```js
214+
import foo from './mod.cjs';
215+
import bar from './mod-compiled.cjs';
216+
console.log(foo); // { default: 3 }
217+
console.log(bar); // 3
218+
```
219+
177220
### `requireReturnsDefault`
178221

179222
Type: `boolean | "namespace" | "auto" | "preferred" | ((id: string) => boolean | "auto" | "preferred")`<br>

packages/commonjs/src/generate-exports.js

+24-13
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ export function rewriteExportsAndGetExportsBlock(
2020
isRestorableCompiledEsm,
2121
code,
2222
uses,
23-
HELPERS_NAME
23+
HELPERS_NAME,
24+
defaultIsModuleExports
2425
) {
2526
const namedExportDeclarations = [`export { ${moduleName} as __moduleExports };`];
2627
const moduleExportsPropertyAssignments = [];
@@ -75,19 +76,29 @@ export function rewriteExportsAndGetExportsBlock(
7576

7677
// Generate default export
7778
const defaultExport = [];
78-
if (isRestorableCompiledEsm) {
79-
defaultExport.push(`export default ${deconflictedDefaultExportName || moduleName};`);
80-
} else if (
81-
(wrapped || deconflictedDefaultExportName) &&
82-
(defineCompiledEsmExpressions.length > 0 || code.indexOf('__esModule') >= 0)
83-
) {
84-
// eslint-disable-next-line no-param-reassign
85-
uses.commonjsHelpers = true;
86-
defaultExport.push(
87-
`export default /*@__PURE__*/${HELPERS_NAME}.getDefaultExportFromCjs(${moduleName});`
88-
);
89-
} else {
79+
if (defaultIsModuleExports === 'auto') {
80+
if (isRestorableCompiledEsm) {
81+
defaultExport.push(`export default ${deconflictedDefaultExportName || moduleName};`);
82+
} else if (
83+
(wrapped || deconflictedDefaultExportName) &&
84+
(defineCompiledEsmExpressions.length > 0 || code.includes('__esModule'))
85+
) {
86+
// eslint-disable-next-line no-param-reassign
87+
uses.commonjsHelpers = true;
88+
defaultExport.push(
89+
`export default /*@__PURE__*/${HELPERS_NAME}.getDefaultExportFromCjs(${moduleName});`
90+
);
91+
} else {
92+
defaultExport.push(`export default ${moduleName};`);
93+
}
94+
} else if (defaultIsModuleExports === true) {
9095
defaultExport.push(`export default ${moduleName};`);
96+
} else if (defaultIsModuleExports === false) {
97+
if (deconflictedDefaultExportName) {
98+
defaultExport.push(`export default ${deconflictedDefaultExportName};`);
99+
} else {
100+
defaultExport.push(`export default ${moduleName}.default;`);
101+
}
91102
}
92103

93104
return `\n\n${defaultExport

packages/commonjs/src/index.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ export default function commonjs(options = {}) {
5959
: Array.isArray(esmExternals)
6060
? ((esmExternalIds = new Set(esmExternals)), (id) => esmExternalIds.has(id))
6161
: () => esmExternals;
62+
const defaultIsModuleExports =
63+
typeof options.defaultIsModuleExports === 'boolean' ? options.defaultIsModuleExports : 'auto';
6264

6365
const { dynamicRequireModuleSet, dynamicRequireModuleDirPaths } = getDynamicRequirePaths(
6466
options.dynamicRequireTargets
@@ -145,7 +147,8 @@ export default function commonjs(options = {}) {
145147
dynamicRequireModuleSet,
146148
disableWrap,
147149
commonDir,
148-
ast
150+
ast,
151+
defaultIsModuleExports
149152
);
150153
}
151154

packages/commonjs/src/transform-commonjs.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ export default function transformCommonjs(
5353
dynamicRequireModuleSet,
5454
disableWrap,
5555
commonDir,
56-
astCache
56+
astCache,
57+
defaultIsModuleExports
5758
) {
5859
const ast = astCache || tryParse(parse, code, id);
5960
const magicString = new MagicString(code);
@@ -470,7 +471,8 @@ export default function transformCommonjs(
470471
isRestorableCompiledEsm,
471472
code,
472473
uses,
473-
HELPERS_NAME
474+
HELPERS_NAME,
475+
defaultIsModuleExports
474476
);
475477

476478
const importBlock = rewriteRequireExpressionsAndGetImportBlock(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
options: {
3+
defaultIsModuleExports: 'auto'
4+
}
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
exports.__esModule = true;
2+
exports.default = 2;
3+
exports.named = 3;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
var _default = 2;
2+
var named = 3;
3+
4+
var input = /*#__PURE__*/Object.defineProperty({
5+
default: _default,
6+
named: named
7+
}, '__esModule', {value: true});
8+
9+
export default _default;
10+
export { input as __moduleExports };
11+
export { named };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
options: {
3+
defaultIsModuleExports: 'auto'
4+
}
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
exports.default = 2;
2+
exports.named = 3;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
var _default = 2;
2+
var named = 3;
3+
4+
var input = {
5+
default: _default,
6+
named: named
7+
};
8+
9+
export default input;
10+
export { input as __moduleExports };
11+
export { named };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
options: {
3+
defaultIsModuleExports: false
4+
}
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
exports.__esModule = true;
2+
exports.default = 2;
3+
exports.named = 3;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
var _default = 2;
2+
var named = 3;
3+
4+
var input = /*#__PURE__*/Object.defineProperty({
5+
default: _default,
6+
named: named
7+
}, '__esModule', {value: true});
8+
9+
export default _default;
10+
export { input as __moduleExports };
11+
export { named };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
options: {
3+
defaultIsModuleExports: false
4+
}
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
exports.default = 2;
2+
exports.named = 3;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
var _default = 2;
2+
var named = 3;
3+
4+
var input = {
5+
default: _default,
6+
named: named
7+
};
8+
9+
export default _default;
10+
export { input as __moduleExports };
11+
export { named };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
options: {
3+
defaultIsModuleExports: false
4+
}
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
exports.named = 3;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
var named = 3;
2+
3+
var input = {
4+
named: named
5+
};
6+
7+
export default input.default;
8+
export { input as __moduleExports };
9+
export { named };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
options: {
3+
defaultIsModuleExports: true
4+
}
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
exports.__esModule = true;
2+
exports.default = 2;
3+
exports.named = 3;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
var _default = 2;
2+
var named = 3;
3+
4+
var input = /*#__PURE__*/Object.defineProperty({
5+
default: _default,
6+
named: named
7+
}, '__esModule', {value: true});
8+
9+
export default input;
10+
export { input as __moduleExports };
11+
export { named };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
options: {
3+
defaultIsModuleExports: true
4+
}
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
exports.default = 2;
2+
exports.named = 3;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
var _default = 2;
2+
var named = 3;
3+
4+
var input = {
5+
default: _default,
6+
named: named
7+
};
8+
9+
export default input;
10+
export { input as __moduleExports };
11+
export { named };

0 commit comments

Comments
 (0)