javascriptconstantsminifyrollupjsterser

Rollup, multiple files, same constants name in multiple files: error in browser: Uncaught SyntaxError: Identifier 'o' has already been declared


I have a problem.

EXPLANATION

In a website I navigate on page /one, the code in the one.js file executes fine.

After a while I insert in the page (pjax, ajax: no matter how) the second code in two.js file.

The browser complains with this error:

Uncaught SyntaxError: Identifier 'o' has already been declared
- at two.js:1

REPRODUCTION and SOURCE CODE

  1. rollup.config.js:

    import resolve from 'rollup-plugin-node-resolve'
    import commonjs from 'rollup-plugin-commonjs'
    import { terser } from 'rollup-plugin-terser'
    import multiInput from 'rollup-plugin-multi-input'
    
    export default {
      input: ['src/**/*.js'],
      output: {
        format: 'esm',
        dir: 'dist/js'
      },
      plugins: [
        multiInput({ relative: 'src' }),
        resolve({ browser: true }),
        commonjs(),
        terser()
      ]
    }
    
  2. src/one.js:

    const names1 = ['john1', 'carl1', 'bob1']
    names1.forEach(name1 => {
      console.log('name1:', name1, ', in names1:', ...names1)
    })
    
  3. src/two.js:

    const names2 = ['john2', 'carl2', 'bob2']
    names2.forEach(name2 => {
      console.log('name2:', name2, ', in names2:', ...names2)
    })
    
  4. dist/js/one.js:

    const o=["john1","carl1","bob1"];o.forEach(n=>{console.log("name1:",n,", in names1:",...o)});
    
  5. dist/js/two.js:

    const o=["john2","carl2","bob2"];o.forEach(n=>{console.log("name2:",n,", in names2:",...o)});
    

QUESTIONS

How to fix this problem?

Can we "prefix" constants name based on file name?

If of course I put everything in just one.js file it works but it's not possible because of the structure of the project.


Solution

  • You chose output.format: 'esm', which makes Rollup assume that the codes live in their own module scope. If you insert them in your page with

     <script type="module" src="/dist/js/one.js"></script>
     <script type="module" src="/dist/js/two.js"></script>
    

    I would expect them to work. If you don't want to use type="module", then use a different output format for Rollup which will wrap them in a module pattern (or IIFE) to give them their own scopes.