vitejs / vite

Next generation frontend tooling. It's fast!
http://vitejs.dev
MIT License
66.72k stars 5.98k forks source link

Global namespace pollution when using rollupOptions.output.format umd #17608

Open TomPradat opened 1 month ago

TomPradat commented 1 month ago

Describe the bug

I'm building a bundle with umd format as a target. When doing so I expect the result bundle to be wrapped in an iife function. The configuration looks like this :

  build: {
    rollupOptions: {
      output: {
        format: "umd",
        entryFileNames: "bundle.js",
      },
    },
  },

Instead, I have variables declared outside the iife :

image

This is a problem because the variables' declaration might override previous variables with the same name. This is how I encountered the issue.

Workaround :

So far, I have used a homemade plugin to wrap my final code in a iife :

import { defineConfig } from "vite";

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        format: "umd",
        entryFileNames: "bundle.js",
      },
    },
  },
  plugins: [viteWrapCodeInIIFE({ files: ["bundle.js"] })],
});

function viteWrapCodeInIIFE(options = {}) {
  return {
    name: "vite-wrap-code-in-iife",
    apply: "build",
    enforce: "post",
    generateBundle(outputOptions, bundle) {
      for (const [fileName, chunkOrAsset] of Object.entries(bundle)) {
        if (
          chunkOrAsset.type === "chunk" &&
          options.files &&
          options.files.includes(fileName)
        ) {
          chunkOrAsset.code = `(function () {${chunkOrAsset.code}})();`;
        }
      }
    },
  };
}

I'm willing to work on a PR. I believe the fix would be an extension of the https://github.com/vitejs/vite/pull/7948 so that is also applies when rollupOptions.output.format is umd or iife.

Reproduction

See steps

Steps to reproduce

  1. Bootstrap a vite project
npm init vite@latest test -- --template vanilla && cd test && npm install
  1. Install the "react-query" package that causes the build to have variables defined outside the iife
npm install @tanstack/react-query
  1. Create a vite.config.js with the umd format as a target
cat <<EOF > vite.config.js
import { defineConfig } from "vite";

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        format: "umd",
        entryFileNames: "bundle.js",
      },
    },
  },
});
EOF
  1. Change the main.js
cat <<EOF > main.js
import { QueryClient } from "@tanstack/react-query";

const queryClient = new QueryClient();
EOF
  1. Build the bundle
npm run build
  1. See the result in dist/bundle.js

System Info

System:
    OS: macOS 13.4.1
    CPU: (8) arm64 Apple M1 Pro
    Memory: 330.16 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 18.16.0 - ~/.nvm/versions/node/v18.16.0/bin/node
    Yarn: 3.5.1 - ~/.nvm/versions/node/v18.16.0/bin/yarn
    npm: 9.5.1 - ~/.nvm/versions/node/v18.16.0/bin/npm
    pnpm: 8.15.4 - ~/Library/pnpm/pnpm
    bun: 1.0.14 - ~/.bun/bin/bun
  Browsers:
    Brave Browser: 124.1.65.132
    Chrome: 126.0.6478.127
    Firefox Nightly: 121.0a1
    Safari: 16.5.2
  npmPackages:
    vite: ^5.3.1 => 5.3.3

Used Package Manager

npm

Logs

No response

Validations

sapphi-red commented 1 month ago

I haven't checked deeply but I guess we should use opts.format === 'iife' || opts.format === 'umd' instead of config.build.lib for people using IIFE/UMD format without turning lib mode on. https://github.com/vitejs/vite/blob/22b299429599834bf1855b53264a28ae5ff8f888/packages/vite/src/node/plugins/esbuild.ts#L320

TomPradat commented 1 month ago

I haven't checked deeply but I guess we should use opts.format === 'iife' || opts.format === 'umd' instead of config.build.lib for people using IIFE/UMD format without turning lib mode on.

https://github.com/vitejs/vite/blob/22b299429599834bf1855b53264a28ae5ff8f888/packages/vite/src/node/plugins/esbuild.ts#L320

This is what I was thinking too 👍 . I can work on a PR as soon as this is confirmed as a bug

sapphi-red commented 1 month ago

Yeah, I think it's a bug.