Improving handling of exports in prebuilt CommonJS dependencies
If a CommonJS package is prebundled using the prebuild configuration setting, the exports in the generated bundle may not be what the user expects.
Given a CommonJS npm package test-pkg with an entry point which contains:
function functionA() {
return 'functionA';
}
function functionB() {
return 'functionB';
}
module.exports = { functionA, functionB };
If test-pkg is added to the list of npm dependencies to prebuild, then rollup-cache will generate the following test-pkg.bundle.js ESM bundle:
function functionA() {
return 'functionA';
}
function functionB() {
return 'functionB';
}
var testPkg = { functionA, functionB };
export { testPkg as default };
This behavior matches how Node handles importing a CommonJS package in an ESM module. However it is often not what existing in projects may expect. If a project using the above package has code in it like:
import { functionA, functionB } from 'test-pkg';
Then the generated project bundle will reference the prebuilt bundle using:
import { functionA, functionB } from './npm/test-pkg.bundle.js';
This import will then fail at runtime because the named exports functionA and functionB do not actually exist.
I can see a few ways to resolve this:
- Disallow prebuilding of non-ESM packages. This is probably the simplest and most predictable approach, but will prevent prebuilding from being used with a lot of existing packages.
- Change the way the exports are generated in the generated CommonJS package.
If on the other hand the CommonJS entry point contains:
function functionA() {
return 'functionA';
}
function functionB() {
return 'functionB';
}
exports.functionA = functionA;
exports.functionB = functionB;
Then the generated bundle is:
var testPkg = {};
function functionA() {
return 'functionA';
}
function functionB() {
return 'functionB';
}
var functionA_1 = testPkg.functionA = functionA;
var functionB_1 = testPkg.functionB = functionB;
export { testPkg as default, functionA_1 as functionA, functionB_1 as functionB };
This will work with the code in the original post.
The above scenarios are covered by the "Entry points" section of https://github.com/rollup/plugins/issues/481. See "Entry point which assigns to module.exports" and "Entry point which adds properties to exports".