vitejs / vite

Next generation frontend tooling. It's fast!
http://vite.dev
MIT License
68.2k stars 6.15k forks source link

esbuild minifier mangles top-level variable names in umd library build #5426

Closed wmzy closed 2 years ago

wmzy commented 3 years ago

Describe the bug

vite 2.5.7 image

after update to vite 2.6.11 image

this pr changed the default minify to esbuild

Reproduction

  1. create project
    npm init vite@latest test -- --template vanilla && cd test && npm i
  2. config
    
    import { defineConfig } from 'vite';

// https://vitejs.dev/config/ export default defineConfig({ build: { lib: { name: 'test', entry: 'main.js', }, }, });

3. edit main.js
```js
const a = {};
console.log({...a})
  1. build
    npx vite build && cat dist/test.umd.js
  2. result(formated)
    
    var c = Object.defineProperty;
    var o = Object.getOwnPropertySymbols;
    var d = Object.prototype.hasOwnProperty,
    s = Object.prototype.propertyIsEnumerable;
    var f = (n, e, i) =>
    e in n
      ? c(n, e, { enumerable: !0, configurable: !0, writable: !0, value: i })
      : (n[e] = i),
    t = (n, e) => {
    for (var i in e || (e = {})) d.call(e, i) && f(n, i, e[i]);
    if (o) for (var i of o(e)) s.call(e, i) && f(n, i, e[i]);
    return n;
    };
    (function (n) {
    typeof define == 'function' && define.amd ? define(n) : n();
    })(function () {
    'use strict';
    console.log(t({}, {}));
    });

### System Info

```shell
System:
    OS: macOS 11.6
    CPU: (8) x64 Intel(R) Core(TM) i5-8279U CPU @ 2.40GHz
    Memory: 2.99 GB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 15.10.0 - ~/.n/bin/node
    Yarn: 1.22.10 - ~/.n/bin/yarn
    npm: 7.5.3 - ~/.n/bin/npm
  Browsers:
    Chrome: 95.0.4638.54
    Firefox: 90.0.2
    Safari: 14.1.2
  npmPackages:
    @vitejs/plugin-react-refresh: ^1.3.3 => 1.3.3 
    vite: ^2.4.4 => 2.4.4

Used Package Manager

npm

Logs

No response

Validations

haoqunjiang commented 3 years ago

What's the problem here?

wmzy commented 3 years ago

@sodatea A random global variable can easily conflict with other lib. This has laid an implicit trap for all users.

gamperl commented 2 years ago

This problem can be solved by setting the esbuild output format to iife. Add format: 'iife' to the minify options.

bluwy commented 2 years ago

@wmzy I still don't quite understand the issue here, has this quirk happened out in the wild? Maybe I'm missing something, but I don't see a problem from the repro. Can you show how a random global variable cause issues in the repro?

wmzy commented 2 years ago

@bluwy Naming conflicts may arise if multiple libraries are loaded at the same page.

E.g

// lib1
var c = Object.defineProperty;
var o = Object.getOwnPropertySymbols;
var d = Object.prototype.hasOwnProperty,
  s = Object.prototype.propertyIsEnumerable;
......

c d o maybe redefine at another lib:

lib2
var o = Object.defineProperty;
var d = Object.getOwnPropertySymbols;
var c = Object.prototype.hasOwnProperty,
  s = Object.prototype.propertyIsEnumerable;
......
bluwy commented 2 years ago

I guess the same could probably be said for unminified variables, and the chance of it happening would be the same too. That was where I'm a bit confused of, though I've never actually had an issue like this in the wild. I'm assuming bundlers know what they're doing and would immediately use the var variables before the rest of the code evaluate and changes it.

flucivja commented 2 years ago

I've experienced same issue, when I loaded 2 different bundles which were built using vitejs into UMD format, JS crashed on very strange error, it took me while until I figured out that those bundles conflicted with each other on those global variables created by esbuild. I fixed it by custom plugin wrapping whole UMD module into IIFE before saving it to file.

wmzy commented 2 years ago

@bluwy There is a small chance that unminified variables may conflicted with other lib which not build by vitejs. But it won't conflicted with one build by vitejs.

Of course the correct way is to eliminate global variables.

jeffhuys commented 2 years ago

We had the same problems arising in our code base. At first, it was "flaky", as just merging a new branch would fix it most of the time (new code, new build, new random variable names). Over time, it got more and more prevalent, until this week where we just couldn't get a working version.

Our setup is 2 web apps "joined together" using Single-SPA, which means we need to use format: 'system'.

Simply downgrading to ^2.5.10 fixed our issues. However, we'd like to stay up-to-date, of course, so I hope we can find another way to fix this.

wmzy commented 2 years ago

@jeffhuys Use terser minify will fix this.

Vite does not follow version semantics, and upgrades require caution. We got scammed many times.