@rollup/plugin-commonjs 26.0.3 → 27.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -49,13 +49,13 @@ When used together with the node-resolve plugin
49
49
  ### `strictRequires`
50
50
 
51
51
  Type: `"auto" | boolean | "debug" | string[]`<br>
52
- Default: `"auto"`
52
+ Default: `true`
53
53
 
54
- By default, this plugin will try to hoist `require` statements as imports to the top of each file. While this works well for many code bases and allows for very efficient ESM output, it does not perfectly capture CommonJS semantics as the initialisation order of required modules will be different. The resultant side effects can include log statements being emitted in a different order, and some code that is dependent on the initialisation order of polyfills in require statements may not work. But it is especially problematic when there are circular `require` calls between CommonJS modules as those often rely on the lazy execution of nested `require` calls.
54
+ Historically, this plugin tried to hoist `require` statements as imports to the top of each file. While this works well for many code bases and allows for very efficient ESM output, it does not perfectly capture CommonJS semantics as the initialisation order of required modules will be different. The resultant side effects can include log statements being emitted in a different order, and some code that is dependent on the initialisation order of polyfills in require statements may not work. But it is especially problematic when there are circular `require` calls between CommonJS modules as those often rely on the lazy execution of nested `require` calls.
55
55
 
56
- Setting this option to `true` will wrap all CommonJS files in functions which are executed when they are required for the first time, preserving NodeJS semantics. This is the safest setting and should be used if the generated code does not work correctly with `"auto"`. Note that `strictRequires: true` can have a small impact on the size and performance of generated code, but less so if the code is minified.
56
+ The default value of `true` will wrap all CommonJS files in functions which are executed when they are required for the first time, preserving NodeJS semantics. This is the safest setting and should be used if the generated code does not work correctly with `"auto"`. Note that `strictRequires: true` can have a small impact on the size and performance of generated code, but less so if the code is minified.
57
57
 
58
- The default value of `"auto"` will only wrap CommonJS files when they are part of a CommonJS dependency cycle, e.g. an index file that is required by some of its dependencies, or if they are only required in a potentially "conditional" way like from within an if-statement or a function. All other CommonJS files are hoisted. This is the recommended setting for most code bases. Note that the detection of conditional requires can be subject to race conditions if there are both conditional and unconditional requires of the same file, which in edge cases may result in inconsistencies between builds. If you think this is a problem for you, you can avoid this by using any value other than `"auto"` or `"debug"`.
58
+ Setting this option to `"auto"` will only wrap CommonJS files when they are part of a CommonJS dependency cycle, e.g. an index file that is required by some of its dependencies, or if they are only required in a potentially "conditional" way like from within an if-statement or a function. All other CommonJS files are hoisted. This is the recommended setting for most code bases. Note that the detection of conditional requires can be subject to race conditions if there are both conditional and unconditional requires of the same file, which in edge cases may result in inconsistencies between builds. If you think this is a problem for you, you can avoid this by using any value other than `"auto"` or `"debug"`.
59
59
 
60
60
  `false` will entirely prevent wrapping and hoist all files. This may still work depending on the nature of cyclic dependencies but will often cause problems.
61
61
 
@@ -386,6 +386,30 @@ For these situations, you can change Rollup's behaviour either globally or per m
386
386
 
387
387
  To change this for individual modules, you can supply a function for `requireReturnsDefault` instead. This function will then be called once for each required ES module or external dependency with the corresponding id and allows you to return different values for different modules.
388
388
 
389
+ ## Using CommonJS files as entry points
390
+
391
+ With this plugin, you can also use CommonJS files as entry points. This means, however, that when you are bundling to an ES module, your bundle will only have a default export. If you want named exports instead, you should use an ES module entry point instead that reexports from your CommonJS entry point, e.g.
392
+
393
+ ```js
394
+ // main.cjs, the CommonJS entry
395
+ exports.foo = 'foo';
396
+ exports.bar = 'bar';
397
+
398
+ // main.mjs, the ES module entry
399
+ export { foo, bar } from './main.cjs';
400
+
401
+ // rollup.config.mjs
402
+ export default {
403
+ input: 'main.mjs',
404
+ output: {
405
+ format: 'es',
406
+ file: 'bundle.mjs'
407
+ }
408
+ };
409
+ ```
410
+
411
+ When bundling to CommonJS, i.e `output.format === 'cjs'`, make sure that you do not set `output.exports` to `'named'`. The default value of `'auto'` will usually work, but you can also set it explicitly to `'default'`. That makes sure that Rollup assigns the default export that was generated for your CommonJS entry point to `module.exports`, and semantics do not change.
412
+
389
413
  ## Using with @rollup/plugin-node-resolve
390
414
 
391
415
  Since most CommonJS packages you are importing are probably dependencies in `node_modules`, you may need to use [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve):
package/dist/cjs/index.js CHANGED
@@ -11,7 +11,7 @@ var estreeWalker = require('estree-walker');
11
11
  var MagicString = require('magic-string');
12
12
  var isReference = require('is-reference');
13
13
 
14
- var version = "26.0.3";
14
+ var version = "27.0.0";
15
15
  var peerDependencies = {
16
16
  rollup: "^2.68.0||^3.0.0||^4.0.0"
17
17
  };
@@ -123,10 +123,10 @@ function capitalize(name) {
123
123
 
124
124
  function getStrictRequiresFilter({ strictRequires }) {
125
125
  switch (strictRequires) {
126
- case true:
127
- return { strictRequiresFilter: () => true, detectCyclesAndConditional: false };
128
126
  // eslint-disable-next-line no-undefined
129
127
  case undefined:
128
+ case true:
129
+ return { strictRequiresFilter: () => true, detectCyclesAndConditional: false };
130
130
  case 'auto':
131
131
  case 'debug':
132
132
  case null:
@@ -331,12 +331,19 @@ const isWrappedId = (id, suffix) => id.endsWith(suffix);
331
331
  const wrapId = (id, suffix) => `\0${id}${suffix}`;
332
332
  const unwrapId = (wrappedId, suffix) => wrappedId.slice(1, -suffix.length);
333
333
 
334
+ // A proxy module when a module is required from non-wrapped CommonJS. Is different for ESM and CommonJS requires.
334
335
  const PROXY_SUFFIX = '?commonjs-proxy';
336
+ // Indicates that a required module is wrapped commonjs and needs special handling.
335
337
  const WRAPPED_SUFFIX = '?commonjs-wrapped';
338
+ // Indicates that a required module is external
336
339
  const EXTERNAL_SUFFIX = '?commonjs-external';
340
+ // A helper module that contains the exports object of a module
337
341
  const EXPORTS_SUFFIX = '?commonjs-exports';
342
+ // A helper module that contains the module object of a module, e.g. when module.exports is reassigned
338
343
  const MODULE_SUFFIX = '?commonjs-module';
344
+ // A special proxy for CommonJS entry points
339
345
  const ENTRY_SUFFIX = '?commonjs-entry';
346
+ // A proxy when wrapped ESM is required from CommonJS
340
347
  const ES_IMPORT_SUFFIX = '?commonjs-es-import';
341
348
 
342
349
  const DYNAMIC_MODULES_ID = '\0commonjs-dynamic-modules';
@@ -449,26 +456,28 @@ function getEntryProxy(id, defaultIsModuleExports, getModuleInfo, shebang) {
449
456
  }
450
457
  return shebang + code;
451
458
  }
452
- const result = getEsImportProxy(id, defaultIsModuleExports);
459
+ const result = getEsImportProxy(id, defaultIsModuleExports, true);
453
460
  return {
454
461
  ...result,
455
462
  code: shebang + result.code
456
463
  };
457
464
  }
458
465
 
459
- function getEsImportProxy(id, defaultIsModuleExports) {
466
+ function getEsImportProxy(id, defaultIsModuleExports, moduleSideEffects) {
460
467
  const name = getName(id);
461
468
  const exportsName = `${name}Exports`;
462
469
  const requireModule = `require${capitalize(name)}`;
463
470
  let code =
464
471
  `import { getDefaultExportFromCjs } from "${HELPERS_ID}";\n` +
465
472
  `import { __require as ${requireModule} } from ${JSON.stringify(id)};\n` +
466
- `var ${exportsName} = ${requireModule}();\n` +
473
+ `var ${exportsName} = ${moduleSideEffects ? '' : '/*@__PURE__*/ '}${requireModule}();\n` +
467
474
  `export { ${exportsName} as __moduleExports };`;
468
475
  if (defaultIsModuleExports === true) {
469
476
  code += `\nexport { ${exportsName} as default };`;
477
+ } else if (defaultIsModuleExports === false) {
478
+ code += `\nexport default ${exportsName}.default;`;
470
479
  } else {
471
- code += `export default /*@__PURE__*/getDefaultExportFromCjs(${exportsName});`;
480
+ code += `\nexport default /*@__PURE__*/getDefaultExportFromCjs(${exportsName});`;
472
481
  }
473
482
  return {
474
483
  code,
@@ -523,11 +532,7 @@ function getResolveId(extensions, isPossibleCjsId) {
523
532
  // All logic below is specific to ES imports.
524
533
  // Also, if we do not skip this logic for requires that are resolved while
525
534
  // transforming a commonjs file, it can easily lead to deadlocks.
526
- if (
527
- customOptions &&
528
- customOptions['node-resolve'] &&
529
- customOptions['node-resolve'].isRequire
530
- ) {
535
+ if (customOptions?.['node-resolve']?.isRequire) {
531
536
  return null;
532
537
  }
533
538
  const currentlyResolvingForParent = currentlyResolving.get(importer);
@@ -811,13 +816,14 @@ function getRequireResolver(extensions, detectCyclesAndConditional, currentlyRes
811
816
  // eslint-disable-next-line no-multi-assign
812
817
  const isCommonJS = (parentMeta.isRequiredCommonJS[dependencyId] =
813
818
  getTypeForFullyAnalyzedModule(dependencyId));
819
+ const isWrappedCommonJS = isCommonJS === IS_WRAPPED_COMMONJS;
814
820
  fullyAnalyzedModules[dependencyId] = true;
815
821
  return {
822
+ wrappedModuleSideEffects:
823
+ isWrappedCommonJS && rollupContext.getModuleInfo(dependencyId).moduleSideEffects,
816
824
  source: sources[index].source,
817
825
  id: allowProxy
818
- ? isCommonJS === IS_WRAPPED_COMMONJS
819
- ? wrapId(dependencyId, WRAPPED_SUFFIX)
820
- : wrapId(dependencyId, PROXY_SUFFIX)
826
+ ? wrapId(dependencyId, isWrappedCommonJS ? WRAPPED_SUFFIX : PROXY_SUFFIX)
821
827
  : dependencyId,
822
828
  isCommonJS
823
829
  };
@@ -1405,7 +1411,7 @@ function processRequireExpressions(
1405
1411
  magicString
1406
1412
  ) {
1407
1413
  const generateRequireName = getGenerateRequireName();
1408
- for (const { source, id: resolvedId, isCommonJS } of requireTargets) {
1414
+ for (const { source, id: resolvedId, isCommonJS, wrappedModuleSideEffects } of requireTargets) {
1409
1415
  const requires = requiresBySource[source];
1410
1416
  const name = generateRequireName(requires);
1411
1417
  let usesRequired = false;
@@ -1424,7 +1430,11 @@ function processRequireExpressions(
1424
1430
  } else if (canConvertRequire) {
1425
1431
  needsImport = true;
1426
1432
  if (isCommonJS === IS_WRAPPED_COMMONJS) {
1427
- magicString.overwrite(node.start, node.end, `${name}()`);
1433
+ magicString.overwrite(
1434
+ node.start,
1435
+ node.end,
1436
+ `${wrappedModuleSideEffects ? '' : '/*@__PURE__*/ '}${name}()`
1437
+ );
1428
1438
  } else if (usesReturnValue) {
1429
1439
  usesRequired = true;
1430
1440
  magicString.overwrite(node.start, node.end, name);
@@ -1531,6 +1541,7 @@ async function transformCommonjs(
1531
1541
  const topLevelAssignments = new Set();
1532
1542
  const topLevelDefineCompiledEsmExpressions = [];
1533
1543
  const replacedGlobal = [];
1544
+ const replacedThis = [];
1534
1545
  const replacedDynamicRequires = [];
1535
1546
  const importedVariables = new Set();
1536
1547
  const indentExclusionRanges = [];
@@ -1798,7 +1809,7 @@ async function transformCommonjs(
1798
1809
  if (lexicalDepth === 0 && !classBodyDepth) {
1799
1810
  uses.global = true;
1800
1811
  if (!ignoreGlobal) {
1801
- replacedGlobal.push(node);
1812
+ replacedThis.push(node);
1802
1813
  }
1803
1814
  }
1804
1815
  return;
@@ -1873,6 +1884,11 @@ async function transformCommonjs(
1873
1884
  storeName: true
1874
1885
  });
1875
1886
  }
1887
+ for (const node of replacedThis) {
1888
+ magicString.overwrite(node.start, node.end, exportsName, {
1889
+ storeName: true
1890
+ });
1891
+ }
1876
1892
  for (const node of replacedDynamicRequires) {
1877
1893
  magicString.overwrite(
1878
1894
  node.start,
@@ -2219,7 +2235,7 @@ function commonjs(options = {}) {
2219
2235
  }
2220
2236
  },
2221
2237
 
2222
- load(id) {
2238
+ async load(id) {
2223
2239
  if (id === HELPERS_ID) {
2224
2240
  return getHelpersModule();
2225
2241
  }
@@ -2265,7 +2281,11 @@ function commonjs(options = {}) {
2265
2281
 
2266
2282
  if (isWrappedId(id, ES_IMPORT_SUFFIX)) {
2267
2283
  const actualId = unwrapId(id, ES_IMPORT_SUFFIX);
2268
- return getEsImportProxy(actualId, getDefaultIsModuleExports(actualId));
2284
+ return getEsImportProxy(
2285
+ actualId,
2286
+ getDefaultIsModuleExports(actualId),
2287
+ (await this.load({ id: actualId })).moduleSideEffects
2288
+ );
2269
2289
  }
2270
2290
 
2271
2291
  if (id === DYNAMIC_MODULES_ID) {
package/dist/es/index.js CHANGED
@@ -7,7 +7,7 @@ import { walk } from 'estree-walker';
7
7
  import MagicString from 'magic-string';
8
8
  import isReference from 'is-reference';
9
9
 
10
- var version = "26.0.3";
10
+ var version = "27.0.0";
11
11
  var peerDependencies = {
12
12
  rollup: "^2.68.0||^3.0.0||^4.0.0"
13
13
  };
@@ -119,10 +119,10 @@ function capitalize(name) {
119
119
 
120
120
  function getStrictRequiresFilter({ strictRequires }) {
121
121
  switch (strictRequires) {
122
- case true:
123
- return { strictRequiresFilter: () => true, detectCyclesAndConditional: false };
124
122
  // eslint-disable-next-line no-undefined
125
123
  case undefined:
124
+ case true:
125
+ return { strictRequiresFilter: () => true, detectCyclesAndConditional: false };
126
126
  case 'auto':
127
127
  case 'debug':
128
128
  case null:
@@ -327,12 +327,19 @@ const isWrappedId = (id, suffix) => id.endsWith(suffix);
327
327
  const wrapId = (id, suffix) => `\0${id}${suffix}`;
328
328
  const unwrapId = (wrappedId, suffix) => wrappedId.slice(1, -suffix.length);
329
329
 
330
+ // A proxy module when a module is required from non-wrapped CommonJS. Is different for ESM and CommonJS requires.
330
331
  const PROXY_SUFFIX = '?commonjs-proxy';
332
+ // Indicates that a required module is wrapped commonjs and needs special handling.
331
333
  const WRAPPED_SUFFIX = '?commonjs-wrapped';
334
+ // Indicates that a required module is external
332
335
  const EXTERNAL_SUFFIX = '?commonjs-external';
336
+ // A helper module that contains the exports object of a module
333
337
  const EXPORTS_SUFFIX = '?commonjs-exports';
338
+ // A helper module that contains the module object of a module, e.g. when module.exports is reassigned
334
339
  const MODULE_SUFFIX = '?commonjs-module';
340
+ // A special proxy for CommonJS entry points
335
341
  const ENTRY_SUFFIX = '?commonjs-entry';
342
+ // A proxy when wrapped ESM is required from CommonJS
336
343
  const ES_IMPORT_SUFFIX = '?commonjs-es-import';
337
344
 
338
345
  const DYNAMIC_MODULES_ID = '\0commonjs-dynamic-modules';
@@ -445,26 +452,28 @@ function getEntryProxy(id, defaultIsModuleExports, getModuleInfo, shebang) {
445
452
  }
446
453
  return shebang + code;
447
454
  }
448
- const result = getEsImportProxy(id, defaultIsModuleExports);
455
+ const result = getEsImportProxy(id, defaultIsModuleExports, true);
449
456
  return {
450
457
  ...result,
451
458
  code: shebang + result.code
452
459
  };
453
460
  }
454
461
 
455
- function getEsImportProxy(id, defaultIsModuleExports) {
462
+ function getEsImportProxy(id, defaultIsModuleExports, moduleSideEffects) {
456
463
  const name = getName(id);
457
464
  const exportsName = `${name}Exports`;
458
465
  const requireModule = `require${capitalize(name)}`;
459
466
  let code =
460
467
  `import { getDefaultExportFromCjs } from "${HELPERS_ID}";\n` +
461
468
  `import { __require as ${requireModule} } from ${JSON.stringify(id)};\n` +
462
- `var ${exportsName} = ${requireModule}();\n` +
469
+ `var ${exportsName} = ${moduleSideEffects ? '' : '/*@__PURE__*/ '}${requireModule}();\n` +
463
470
  `export { ${exportsName} as __moduleExports };`;
464
471
  if (defaultIsModuleExports === true) {
465
472
  code += `\nexport { ${exportsName} as default };`;
473
+ } else if (defaultIsModuleExports === false) {
474
+ code += `\nexport default ${exportsName}.default;`;
466
475
  } else {
467
- code += `export default /*@__PURE__*/getDefaultExportFromCjs(${exportsName});`;
476
+ code += `\nexport default /*@__PURE__*/getDefaultExportFromCjs(${exportsName});`;
468
477
  }
469
478
  return {
470
479
  code,
@@ -519,11 +528,7 @@ function getResolveId(extensions, isPossibleCjsId) {
519
528
  // All logic below is specific to ES imports.
520
529
  // Also, if we do not skip this logic for requires that are resolved while
521
530
  // transforming a commonjs file, it can easily lead to deadlocks.
522
- if (
523
- customOptions &&
524
- customOptions['node-resolve'] &&
525
- customOptions['node-resolve'].isRequire
526
- ) {
531
+ if (customOptions?.['node-resolve']?.isRequire) {
527
532
  return null;
528
533
  }
529
534
  const currentlyResolvingForParent = currentlyResolving.get(importer);
@@ -807,13 +812,14 @@ function getRequireResolver(extensions, detectCyclesAndConditional, currentlyRes
807
812
  // eslint-disable-next-line no-multi-assign
808
813
  const isCommonJS = (parentMeta.isRequiredCommonJS[dependencyId] =
809
814
  getTypeForFullyAnalyzedModule(dependencyId));
815
+ const isWrappedCommonJS = isCommonJS === IS_WRAPPED_COMMONJS;
810
816
  fullyAnalyzedModules[dependencyId] = true;
811
817
  return {
818
+ wrappedModuleSideEffects:
819
+ isWrappedCommonJS && rollupContext.getModuleInfo(dependencyId).moduleSideEffects,
812
820
  source: sources[index].source,
813
821
  id: allowProxy
814
- ? isCommonJS === IS_WRAPPED_COMMONJS
815
- ? wrapId(dependencyId, WRAPPED_SUFFIX)
816
- : wrapId(dependencyId, PROXY_SUFFIX)
822
+ ? wrapId(dependencyId, isWrappedCommonJS ? WRAPPED_SUFFIX : PROXY_SUFFIX)
817
823
  : dependencyId,
818
824
  isCommonJS
819
825
  };
@@ -1401,7 +1407,7 @@ function processRequireExpressions(
1401
1407
  magicString
1402
1408
  ) {
1403
1409
  const generateRequireName = getGenerateRequireName();
1404
- for (const { source, id: resolvedId, isCommonJS } of requireTargets) {
1410
+ for (const { source, id: resolvedId, isCommonJS, wrappedModuleSideEffects } of requireTargets) {
1405
1411
  const requires = requiresBySource[source];
1406
1412
  const name = generateRequireName(requires);
1407
1413
  let usesRequired = false;
@@ -1420,7 +1426,11 @@ function processRequireExpressions(
1420
1426
  } else if (canConvertRequire) {
1421
1427
  needsImport = true;
1422
1428
  if (isCommonJS === IS_WRAPPED_COMMONJS) {
1423
- magicString.overwrite(node.start, node.end, `${name}()`);
1429
+ magicString.overwrite(
1430
+ node.start,
1431
+ node.end,
1432
+ `${wrappedModuleSideEffects ? '' : '/*@__PURE__*/ '}${name}()`
1433
+ );
1424
1434
  } else if (usesReturnValue) {
1425
1435
  usesRequired = true;
1426
1436
  magicString.overwrite(node.start, node.end, name);
@@ -1527,6 +1537,7 @@ async function transformCommonjs(
1527
1537
  const topLevelAssignments = new Set();
1528
1538
  const topLevelDefineCompiledEsmExpressions = [];
1529
1539
  const replacedGlobal = [];
1540
+ const replacedThis = [];
1530
1541
  const replacedDynamicRequires = [];
1531
1542
  const importedVariables = new Set();
1532
1543
  const indentExclusionRanges = [];
@@ -1794,7 +1805,7 @@ async function transformCommonjs(
1794
1805
  if (lexicalDepth === 0 && !classBodyDepth) {
1795
1806
  uses.global = true;
1796
1807
  if (!ignoreGlobal) {
1797
- replacedGlobal.push(node);
1808
+ replacedThis.push(node);
1798
1809
  }
1799
1810
  }
1800
1811
  return;
@@ -1869,6 +1880,11 @@ async function transformCommonjs(
1869
1880
  storeName: true
1870
1881
  });
1871
1882
  }
1883
+ for (const node of replacedThis) {
1884
+ magicString.overwrite(node.start, node.end, exportsName, {
1885
+ storeName: true
1886
+ });
1887
+ }
1872
1888
  for (const node of replacedDynamicRequires) {
1873
1889
  magicString.overwrite(
1874
1890
  node.start,
@@ -2215,7 +2231,7 @@ function commonjs(options = {}) {
2215
2231
  }
2216
2232
  },
2217
2233
 
2218
- load(id) {
2234
+ async load(id) {
2219
2235
  if (id === HELPERS_ID) {
2220
2236
  return getHelpersModule();
2221
2237
  }
@@ -2261,7 +2277,11 @@ function commonjs(options = {}) {
2261
2277
 
2262
2278
  if (isWrappedId(id, ES_IMPORT_SUFFIX)) {
2263
2279
  const actualId = unwrapId(id, ES_IMPORT_SUFFIX);
2264
- return getEsImportProxy(actualId, getDefaultIsModuleExports(actualId));
2280
+ return getEsImportProxy(
2281
+ actualId,
2282
+ getDefaultIsModuleExports(actualId),
2283
+ (await this.load({ id: actualId })).moduleSideEffects
2284
+ );
2265
2285
  }
2266
2286
 
2267
2287
  if (id === DYNAMIC_MODULES_ID) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rollup/plugin-commonjs",
3
- "version": "26.0.3",
3
+ "version": "27.0.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },