Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Empty modules in optimized dependencies compile incorrectly #16315

Closed
7 tasks done
ef4 opened this issue Mar 29, 2024 · 4 comments · Fixed by #16436
Closed
7 tasks done

Empty modules in optimized dependencies compile incorrectly #16315

ef4 opened this issue Mar 29, 2024 · 4 comments · Fixed by #16436
Labels
feat: deps optimizer Esbuild Dependencies Optimization p3-minor-bug An edge case that only affects very specific usage (priority)

Comments

@ef4
Copy link

ef4 commented Mar 29, 2024

Describe the bug

If you create an empty module containing only export {} in an app or non-optimized dependency, and then import it into the app via import * as ..., you get back an empty module, which is correct and consistent with native browser behavior.

But if you create an empty module containing only export {} in an optimized dependency, and then import it into the app via import * as ... you get a runtime error.

It looks like the dep optimizer is replacing export {} with an empty file, which is not really a safe transformation.

Reproduction

https://github.com/ef4/empty-module-bug-repro

Steps to reproduce

The reproduction is a monorepo containing an app and a library. The vite.config.js opts into optimizing the library in order to demonstrate the bug. If you disable optimization for the library (which is vite's default behavior given that it's inside the monorepo), you can see the bug go away.

  1. Clone the reproduction repo.

  2. pnpm install

  3. cd app

  4. vite dev

  5. Observe error in browser console

    Uncaught SyntaxError: The requested module '/node_modules/.vite/deps/my-lib.js?v=9aaa7a05' does not provide an export named 'default' (at main.js:5:8)
    
  6. Edit vite.config.js to comment out include: ['my-lib']

  7. Observe that the error has gone away.

System Info

System:
    OS: macOS 14.2.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 351.59 MB / 64.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.11.0 - ~/.volta/tools/image/node/20.11.0/bin/node
    Yarn: 1.22.17 - ~/.volta/tools/image/yarn/1.22.17/bin/yarn
    npm: 10.2.4 - ~/.volta/tools/image/node/20.11.0/bin/npm
    pnpm: 8.14.1 - ~/.volta/tools/image/pnpm/8.14.1/bin/pnpm
    Watchman: 2023.02.13.00 - /opt/homebrew/bin/watchman
  Browsers:
    Chrome: 123.0.6312.87
    Safari: 17.2.1

Used Package Manager

pnpm

Logs

No response

Validations

@hi-ogawa
Copy link
Collaborator

It looks like this is how esbuild bundles export {}. I tested this on esbuild playground:

https://esbuild.github.io/try/#YgAwLjIwLjIALS1idW5kbGUgLS1mb3JtYXQ9ZXNtIC0tb3V0ZGlyPWRpc3QAZQB0ZXN0MS5tanMAZXhwb3J0IHt9AGUAdGVzdDIuY2pzAG1vZHVsZS5leHBvcnRzID0ge30AZQB0ZXN0My5tanMAY29uc3QgaGVsbG8gPSAiaGVsbG8iOwpleHBvcnQgeyBoZWxsbyB9

screenshot

image

Probably it's a bug of esbuild, but I'm not sure. Maybe esbuild side has some rational about this behavior.

@hi-ogawa
Copy link
Collaborator

Actually, esbuild stripping export {} is probably fine, but Vite side's cjs interop kicks in when there's no export and that's expecting default export, which causes an error:

// transformed import in main.js
import __vite__cjsImport4_myLib from "/node_modules/.vite/deps/my-lib.js?v=852c4ed6";

@hi-ogawa hi-ogawa added p3-minor-bug An edge case that only affects very specific usage (priority) feat: deps optimizer Esbuild Dependencies Optimization and removed pending triage labels Apr 1, 2024
@XiSenao
Copy link
Collaborator

XiSenao commented Apr 7, 2024

I think this issue may be related to the vite error in providing interop. The entry module using ESM syntax should not need to add interop.

// entry has no ESM syntax - likely CJS or UMD
if (!exports.length && !hasImports) {
return true
}

Can we determine whether the entry module uses ESM through the fourth parameter mentioned in the following document?https://github.com/guybedford/es-module-lexer?tab=readme-ov-file#esm-detection
parseResult = parse(entryContent)

@bluwy
Copy link
Member

bluwy commented Apr 9, 2024

I suppose we can! I think that would be good to use as a check too.

@github-actions github-actions bot locked and limited conversation to collaborators May 3, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feat: deps optimizer Esbuild Dependencies Optimization p3-minor-bug An edge case that only affects very specific usage (priority)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants