Rollup Version
2.53.0
Operating System (or Browser)
Linux, macOS
Node Version (if applicable)
10+
Link To Reproduction
https://github.com/milesj/rollup-preserve-namespaces
PR I encountered it: milesj/boost#151
Expected Behaviour
It looks like namespace imports that are not used but are exported are dropped, for example this fails:
export * as ns from './namespace';
However, namespace imports that are used within the same file that are exported persist, for example this passes:
import * as ns from './namespace';
export { ns };
export const test = { ...ns };
Discovery
I started updating a project of mine to the latest Rollup version, and immediately noticed that a ton of unit tests are failing with the following errors (as seen in the REPL/PR link):
TypeError: Cannot read property 'parse' of undefined
14 |
15 | resp.on('end', () => {
> 16 | const pkg = json.parse<{ 'dist-tags': Record<string, string> }>(data);
TypeError: Cannot read property 'console' of undefined
114 | transports: [
115 | new StreamTransport({
> 116 | format: formats.console,
This is very weird, as this code hasn't changed in a long time and is pretty straight forward. After digging into it further, it looks like namespaced imports that are exported are completely dropped and are no longer exported in the transpiled output. For example, this code:
/**
* @copyright 2020, Miles Johnson
* @license https://opensource.org/licenses/MIT
*/
import optimal, { Blueprint, Predicates, predicates } from 'optimal';
import type { CommonErrorCode } from './CommonError';
import CommonError from './CommonError';
import Contract from './Contract';
import ExitError from './ExitError';
import PackageGraph from './PackageGraph';
import Path from './Path';
import PathResolver from './PathResolver';
import Project from './Project';
export * from './constants';
export * from './helpers';
export * from './types';
export * from '@boost/decorators';
// THESE 2 EXPORTS
export * as json from './serializers/json';
export * as yaml from './serializers/yaml';
export {
CommonError,
Contract,
ExitError,
optimal,
PackageGraph,
Path,
PathResolver,
predicates,
Project,
};
export type { Blueprint, CommonErrorCode, Predicates };
Is transpiled to the following. Notice that json and yaml exports do not exist! The files are required, but they do nothing.
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
var optimal = require('optimal');
var CommonError = require('./CommonError.js');
var Contract = require('./Contract.js');
var ExitError = require('./ExitError.js');
var PackageGraph = require('./PackageGraph.js');
var Path = require('./Path.js');
var PathResolver = require('./PathResolver.js');
var Project = require('./Project.js');
var constants = require('./constants.js');
require('./helpers/index.js');
require('./serializers/json.js');
require('./serializers/yaml.js');
var types = require('./types.js');
var decorators = require('@boost/decorators');
var createBlueprint = require('./helpers/createBlueprint.js');
var deepFreeze = require('./helpers/deepFreeze.js');
var deepMerge = require('./helpers/deepMerge.js');
var formatMs = require('./helpers/formatMs.js');
var instanceOf = require('./helpers/instanceOf.js');
var isEmpty = require('./helpers/isEmpty.js');
var isFilePath = require('./helpers/isFilePath.js');
var isModuleName = require('./helpers/isModuleName.js');
var isObject = require('./helpers/isObject.js');
var isPlainObject = require('./helpers/isPlainObject.js');
var parseFile = require('./helpers/parseFile.js');
var requireModule = require('./helpers/requireModule.js');
var requireTypedModule = require('./helpers/requireTypedModule.js');
var toArray = require('./helpers/toArray.js');
function _interopDefaultLegacy(e) {
return e && typeof e === 'object' && 'default' in e ? e : {
'default': e
};
}
var optimal__default = /*#__PURE__*/_interopDefaultLegacy(optimal);
/**
* @copyright 2020, Miles Johnson
* @license https://opensource.org/licenses/MIT
*/
Object.defineProperty(exports, 'optimal', {
enumerable: true,
get: function () {
return optimal__default['default'];
}
});
Object.defineProperty(exports, 'predicates', {
enumerable: true,
get: function () {
return optimal.predicates;
}
});
exports.CommonError = CommonError;
exports.Contract = Contract;
exports.ExitError = ExitError;
exports.PackageGraph = PackageGraph;
exports.Path = Path;
exports.PathResolver = PathResolver;
exports.Project = Project;
exports.MODULE_NAME_PART = constants.MODULE_NAME_PART;
exports.MODULE_NAME_PATTERN = constants.MODULE_NAME_PATTERN;
Object.defineProperty(exports, 'LookupType', {
enumerable: true,
get: function () {
return types.LookupType;
}
});
exports.createBlueprint = createBlueprint;
exports.deepFreeze = deepFreeze;
exports.deepMerge = deepMerge;
exports.formatMs = formatMs;
exports.instanceOf = instanceOf;
exports.isEmpty = isEmpty;
exports.isFilePath = isFilePath;
exports.isModuleName = isModuleName;
exports.isObject = isObject;
exports.isPlainObject = isPlainObject;
exports.parseFile = parseFile;
exports.requireModule = requireModule;
exports.requireTypedModule = requireTypedModule;
exports.toArray = toArray;
Object.keys(decorators).forEach(function (k) {
if (k !== 'default' && !exports.hasOwnProperty(k)) Object.defineProperty(exports, k, {
enumerable: true,
get: function () {
return decorators[k];
}
});
});
//# sourceMappingURL=index.js.map
As for the other error above, it is also a namespaced import being exported (https://github.com/milesj/boost/blob/master/packages/log/src/index.ts#L7)
import * as formats from './formats';
export { formats };
Attempts
I've tried different combinations of interop, exports, treeshake, sourceMaps, and any option I could think of. None of them seemed to resolve this issue.
HOWEVER, when I set preserveModules to false and use a single entry point, the export DOES correctly exist.
Instead of export * as X, I also tried the following. It has the same problem (https://github.com/milesj/boost/blob/master/packages/common/src/index.ts#L15).
import * as json from './serializers/json';
import * as yaml from './serializers/yaml';
export { json, yaml };
Config
The configuration is generated by Packemon, which can be found here: https://github.com/milesj/packemon/blob/master/src/rollup/config.ts
Since it's kind of abstracted away, here's a console log of the config while running the build.
{
cache: undefined,
external: [Function (anonymous)],
input: [
'/Users/milesj/Projects/boost/packages/common/src/CommonError.ts',
'/Users/milesj/Projects/boost/packages/common/src/Contract.ts',
'/Users/milesj/Projects/boost/packages/common/src/ExitError.ts',
'/Users/milesj/Projects/boost/packages/common/src/PackageGraph.ts',
'/Users/milesj/Projects/boost/packages/common/src/Path.ts',
'/Users/milesj/Projects/boost/packages/common/src/PathResolver.ts',
'/Users/milesj/Projects/boost/packages/common/src/Project.ts',
'/Users/milesj/Projects/boost/packages/common/src/constants.ts',
'/Users/milesj/Projects/boost/packages/common/src/index.ts',
'/Users/milesj/Projects/boost/packages/common/src/types.ts',
'/Users/milesj/Projects/boost/packages/common/src/helpers/createBlueprint.ts',
'/Users/milesj/Projects/boost/packages/common/src/helpers/deepFreeze.ts',
'/Users/milesj/Projects/boost/packages/common/src/helpers/deepMerge.ts',
'/Users/milesj/Projects/boost/packages/common/src/helpers/formatMs.ts',
'/Users/milesj/Projects/boost/packages/common/src/helpers/index.ts',
'/Users/milesj/Projects/boost/packages/common/src/helpers/instanceOf.ts',
'/Users/milesj/Projects/boost/packages/common/src/helpers/isEmpty.ts',
'/Users/milesj/Projects/boost/packages/common/src/helpers/isFilePath.ts',
'/Users/milesj/Projects/boost/packages/common/src/helpers/isModuleName.ts',
'/Users/milesj/Projects/boost/packages/common/src/helpers/isObject.ts',
'/Users/milesj/Projects/boost/packages/common/src/helpers/isPlainObject.ts',
'/Users/milesj/Projects/boost/packages/common/src/helpers/parseFile.ts',
'/Users/milesj/Projects/boost/packages/common/src/helpers/requireModule.ts',
'/Users/milesj/Projects/boost/packages/common/src/helpers/requireTypedModule.ts',
'/Users/milesj/Projects/boost/packages/common/src/helpers/toArray.ts',
'/Users/milesj/Projects/boost/packages/common/src/internal/interopRequireModule.ts',
'/Users/milesj/Projects/boost/packages/common/src/serializers/json.ts',
'/Users/milesj/Projects/boost/packages/common/src/serializers/yaml.ts'
],
output: [
{
dir: '/Users/milesj/Projects/boost/packages/common/lib',
format: 'cjs',
originalFormat: 'lib',
paths: {},
assetFileNames: '../assets/[name]-[hash][extname]',
chunkFileNames: '[name]-[hash].js',
entryFileNames: '[name].js',
preserveModules: true,
preferConst: false,
plugins: [
{
name: 'babel',
renderStart: [Function: renderStart],
renderChunk: [Function: renderChunk]
},
{
name: 'packemon-add-bin-shebang',
generateBundle: [Function: generateBundle]
}
],
sourcemap: true,
sourcemapExcludeSources: true,
exports: 'auto'
}
],
plugins: [
{
name: 'node-externals',
resolveId: [Function: resolveId],
buildStart: [Function: buildStart]
},
{
name: 'node-resolve',
buildStart: [Function: buildStart],
generateBundle: [Function: generateBundle],
resolveId: [AsyncFunction: resolveId],
load: [Function: load],
getPackageInfoForId: [Function: getPackageInfoForId]
},
{
name: 'commonjs',
buildStart: [Function: buildStart],
resolveId: [Function: resolveId],
load: [Function: load],
transform: [Function: transform],
moduleParsed: [Function: moduleParsed]
},
{ name: 'json', transform: [Function: transform] },
{
name: 'babel',
options: [Function: options],
resolveId: [Function: resolveId],
load: [Function: load],
transform: [Function: transform]
}
],
treeshake: false
}
Actual Behaviour
Namespaced imports are exported correctly.
It seems to work in the REPL (but cant control preserve modules), so not sure what's happening here: https://rollupjs.org/repl/?version=2.53.0&shareable=JTdCJTIybW9kdWxlcyUyMiUzQSU1QiU3QiUyMm5hbWUlMjIlM0ElMjJtYWluLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmV4cG9ydCUyMColMjBhcyUyMG90aGVyJTIwZnJvbSUyMCcuJTJGb3RoZXIuanMnJTNCJTIyJTJDJTIyaXNFbnRyeSUyMiUzQXRydWUlN0QlMkMlN0IlMjJuYW1lJTIyJTNBJTIyb3RoZXIuanMlMjIlMkMlMjJjb2RlJTIyJTNBJTIyZXhwb3J0JTIwZnVuY3Rpb24lMjBmb28oKSUyMCU3QiU3RCU1Q25leHBvcnQlMjBmdW5jdGlvbiUyMGJhcigpJTIwJTdCJTdEJTIyJTdEJTVEJTJDJTIyb3B0aW9ucyUyMiUzQSU3QiUyMmZvcm1hdCUyMiUzQSUyMmNqcyUyMiUyQyUyMm5hbWUlMjIlM0ElMjJteUJ1bmRsZSUyMiUyQyUyMmFtZCUyMiUzQSU3QiUyMmlkJTIyJTNBJTIyJTIyJTdEJTJDJTIyZ2xvYmFscyUyMiUzQSU3QiU3RCU3RCUyQyUyMmV4YW1wbGUlMjIlM0FudWxsJTdE
Rollup Version
2.53.0
Operating System (or Browser)
Linux, macOS
Node Version (if applicable)
10+
Link To Reproduction
https://github.com/milesj/rollup-preserve-namespaces
PR I encountered it: milesj/boost#151
Expected Behaviour
It looks like namespace imports that are not used but are exported are dropped, for example this fails:
However, namespace imports that are used within the same file that are exported persist, for example this passes:
Discovery
I started updating a project of mine to the latest Rollup version, and immediately noticed that a ton of unit tests are failing with the following errors (as seen in the REPL/PR link):
This is very weird, as this code hasn't changed in a long time and is pretty straight forward. After digging into it further, it looks like namespaced imports that are exported are completely dropped and are no longer exported in the transpiled output. For example, this code:
Is transpiled to the following. Notice that
jsonandyamlexports do not exist! The files arerequired, but they do nothing.As for the other error above, it is also a namespaced import being exported (https://github.com/milesj/boost/blob/master/packages/log/src/index.ts#L7)
Attempts
I've tried different combinations of
interop,exports,treeshake,sourceMaps, and any option I could think of. None of them seemed to resolve this issue.HOWEVER, when I set
preserveModulesto false and use a single entry point, the export DOES correctly exist.Instead of
export * as X, I also tried the following. It has the same problem (https://github.com/milesj/boost/blob/master/packages/common/src/index.ts#L15).Config
The configuration is generated by Packemon, which can be found here: https://github.com/milesj/packemon/blob/master/src/rollup/config.ts
Since it's kind of abstracted away, here's a console log of the config while running the build.
Actual Behaviour
Namespaced imports are exported correctly.
It seems to work in the REPL (but cant control preserve modules), so not sure what's happening here: https://rollupjs.org/repl/?version=2.53.0&shareable=JTdCJTIybW9kdWxlcyUyMiUzQSU1QiU3QiUyMm5hbWUlMjIlM0ElMjJtYWluLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmV4cG9ydCUyMColMjBhcyUyMG90aGVyJTIwZnJvbSUyMCcuJTJGb3RoZXIuanMnJTNCJTIyJTJDJTIyaXNFbnRyeSUyMiUzQXRydWUlN0QlMkMlN0IlMjJuYW1lJTIyJTNBJTIyb3RoZXIuanMlMjIlMkMlMjJjb2RlJTIyJTNBJTIyZXhwb3J0JTIwZnVuY3Rpb24lMjBmb28oKSUyMCU3QiU3RCU1Q25leHBvcnQlMjBmdW5jdGlvbiUyMGJhcigpJTIwJTdCJTdEJTIyJTdEJTVEJTJDJTIyb3B0aW9ucyUyMiUzQSU3QiUyMmZvcm1hdCUyMiUzQSUyMmNqcyUyMiUyQyUyMm5hbWUlMjIlM0ElMjJteUJ1bmRsZSUyMiUyQyUyMmFtZCUyMiUzQSU3QiUyMmlkJTIyJTNBJTIyJTIyJTdEJTJDJTIyZ2xvYmFscyUyMiUzQSU3QiU3RCU3RCUyQyUyMmV4YW1wbGUlMjIlM0FudWxsJTdE