Skip to content

Terser plugin generates duplicate imports with preserveModules and mangle and nameCache #1660

@Basssiiie

Description

@Basssiiie
  • Rollup Plugin Name: @rollup/plugin-terser
  • Rollup Plugin Version: v0.4.4
  • Rollup Version: v4.9.4
  • Operating System (or Browser): WIndows 10, 64-bit
  • Node Version: v18.18.0
  • Link to reproduction (⚠️ read below):
  1. This branch.
  2. Run npm install
  3. Run npm build to generate incorrect minified files.
  4. Optionally run npm run build:examples to see the examples unable to import the library because it contains duplicate imports in some files.
  5. Look in dist/esm/src/ to find the output files.

Expected Behavior

Expect no duplicate imports in each module.

Actual Behavior

Duplicate imports in certain files, for example in this file theres's two imports called x:

import { __extends as t } from '../../../node_modules/tslib/tslib.es6.mjs';
import { isStore as x } from '../../bindings/stores/isStore.mjs'; // Duplicate 'x' 1
import { read as S } from '../../bindings/stores/read.mjs';
import { isNumber as ft, isNullOrUndefined as ct, isObject as x } from '../../utilities/type.mjs'; // Duplicate 'x' 2
import { openEvent as vt, updateEvent as lt } from '../constants.mjs';
import { Control as T } from './control.mjs';

File: dist/esm/src/elements/controls/viewport.mjs

Which file it picks changes often when I try something different. Sometimes it's multiple files in the project.

When another project then tries to use this library, the build failes with:

[!] RollupError: Identifier "x" has already been declared
../../dist/esm/src/elements/controls/viewport.mjs (8:62)
 6: import { read as S } from '../../bindings/stores/read.mjs';
 7:
 8: import { isNumber as ft, isNullOrUndefined as ct, isObject as x } from '../../utilities/type.mjs';
                                                                  ^
 9:
10: import { openEvent as vt, updateEvent as lt } from '../constants.mjs';
    at Object.error (D:\Projects\Typescript\OpenRCT2-FlexUI\examples\AllWidgets\node_modules\rollup\dist\shared\parseAst.js:279:30)
    at Module.error (D:\Projects\Typescript\OpenRCT2-FlexUI\examples\AllWidgets\node_modules\rollup\dist\shared\rollup.js:14184:28)
    at Module.addImport (D:\Projects\Typescript\OpenRCT2-FlexUI\examples\AllWidgets\node_modules\rollup\dist\shared\rollup.js:14734:22)
    at ImportDeclaration.initialise (D:\Projects\Typescript\OpenRCT2-FlexUI\examples\AllWidgets\node_modules\rollup\dist\shared\rollup.js:11400:28)
    at new NodeBase (D:\Projects\Typescript\OpenRCT2-FlexUI\examples\AllWidgets\node_modules\rollup\dist\shared\rollup.js:6069:14)
    at new ImportDeclaration (D:\Projects\Typescript\OpenRCT2-FlexUI\examples\AllWidgets\node_modules\rollup\dist\shared\rollup.js:11393:1)
    at Program.parseNode (D:\Projects\Typescript\OpenRCT2-FlexUI\examples\AllWidgets\node_modules\rollup\dist\shared\rollup.js:6180:27)
    at new NodeBase (D:\Projects\Typescript\OpenRCT2-FlexUI\examples\AllWidgets\node_modules\rollup\dist\shared\rollup.js:6068:14)
    at new Program (D:\Projects\Typescript\OpenRCT2-FlexUI\examples\AllWidgets\node_modules\rollup\dist\shared\rollup.js:12422:9)
    at Module.setSource (D:\Projects\Typescript\OpenRCT2-FlexUI\examples\AllWidgets\node_modules\rollup\dist\shared\rollup.js:14565:20)

Additional Information

I've spend hours looking into it, testing various scenarios and browsing this plugin's and Terser's source code, and I'm suspecting it has something to do with the default mangle.nth_identifier. In some specific scenarios it seems to generate a duplicate id which does not get discarded with a specific setup of imports. I've also been able to reproduce it by replacing the default identifier with my own very predictable identifier.

Furthermore:

  • I've tried to disable parallelism by allowing only a single worker for both Rollup and Terser, but this did not affect any of the aforementioned behaviour.
  • I'm sure it's related to usage of preserveModules, because turning this off and generating a single file works fine. Though, I want to stick with preserveModules for my project, so this is not a solution for me.

I've also spent a few hours trying to create a smaller example set up, but unfortunately I wasn't successful in that, as this id generator is just too unpredictable for me to really understand it. So I'm sorry for the big example project.

I hope there's someone out there who knows a bit more about how this works internally.

Thank you for your time!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions