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

Dynamic import of a peer dependency causes inconsistencies between dev and prod #17529

Open
7 tasks done
wijionejs opened this issue Jun 19, 2024 · 2 comments
Open
7 tasks done
Labels
feat: deps optimizer Esbuild Dependencies Optimization p3-minor-bug An edge case that only affects very specific usage (priority)

Comments

@wijionejs
Copy link

wijionejs commented Jun 19, 2024

Describe the bug

Issue

I've carefully read plenty of similar issues, but most of them had been already fixed and none of them had my exact structure. Any help is appreciated.

I have a couple of components in my architecture:

  • a library called library-with-dynamic-import;
  • a library's peer dependency markdown-to-text (was taken just as an example);
  • an actual application.

The library-with-dynamic-import library adds markdown-to-text as a peer dependency to its package.json and imports it using dynamic import:

import('markdown-to-text').then(mod => console.log(mod));

Then, the library's source code is built using vite library mode (the config can be found in the library's source code here) and published to the public npm registry.

The application, in its turn, installs library-with-dynamic-import and its peer dependency markdown-to-text.

In prod build everything is fine and here what I'm seeing in the console:

Screenshot 2024-06-19 at 23 58 48

However, whenever I run the development mode, the issue arises:

Screenshot 2024-06-19 at 23 57 26

As you can see from the screenshot above, there is an extra nested default in the module's object, which of course creates inconsistencies between the development and prod modes and breaks the application.

Note

If I move markdown-to-text from peerDependencies to dependencies, everything works fine in both the development and prod modes.

In a separate branch I've created a reproduction of when markdown-to-text is removed from peerDependencies and added to dependencies and built inside library-with-dynamic-import. You can verify that in this case everything is fine: https://github.com/wijionejs/vite-bug-reproduction/tree/branch_without_peer_deps

My findings

Here some of my findings that might be helpful (or not) for debugging!

Finding 1

If dynamic import of markdown-to-text is only present in library-with-dynamic-import, when library-with-dynamic-import is optimized, its dynamic import is not modified except for the path (see screenshots below).

Application main.js file:

Screenshot 2024-06-20 at 11 57 08

Optimized library-with-dynamic-import:

Screenshot 2024-06-20 at 11 54 31

Finding 2

If I also add dynamic import of markdown-to-text to the application source code, both the application's dynamic import and library-with-dynamic-import is modified with some additional logic.

Application main.js file:

Screenshot 2024-06-20 at 11 56 01

Optimized library-with-dynamic-import:

Screenshot 2024-06-20 at 11 55 50

Reproduction

https://github.com/wijionejs/vite-bug-reproduction

Steps to reproduce

  1. Clone the repository.
  2. Install the dependencies with pnpm install.
  3. Build the project with pnpm build.
  4. Run the preview mode with pnpm preview.
    4.1. Open the console and see the output.
  5. Run the development mode with pnpm dev.
    5.1. Open the console and see the output

Actual result: Everything works as expected in the prod build. However, there is an extra nested default in the development mode.

Expected result: Both the development and prod modes have the same output in the console.

System Info

System:
    OS: macOS 13.6.7
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    Memory: 234.35 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.3.1 - ~/.asdf/installs/nodejs/20.3.1/bin/node
    Yarn: 1.22.21 - ~/.asdf/installs/nodejs/20.3.1/.npm/bin/yarn
    npm: 9.6.7 - ~/.asdf/plugins/nodejs/shims/npm
    pnpm: 8.6.11 - ~/.asdf/installs/nodejs/20.3.1/.npm/bin/pnpm
  Browsers:
    Chrome: 126.0.6478.62
    Safari: 16.6
  npmPackages:
    vite: ^5.2.0 => 5.2.0

Used Package Manager

pnpm

Logs

No response

Validations

@wijionejs
Copy link
Author

I'm not sure whether it is a workaround for the bug or a real solution, but if I explicitly add markdown-to-text to optimizeDeps, it starts working correctly.

// vite.config.js
import { defineConfig } from "vite";

export default defineConfig({
  optimizeDeps: {
    include: ['markdown-to-text']
  }
});

Shouldn't it be optimized by default, given that markdown-to-text is a dependency written in commonjs?

@hi-ogawa
Copy link
Collaborator

hi-ogawa commented Jun 20, 2024

Thanks for investigating. I was also checking your reproduction and made something simpler on my own https://github.com/hi-ogawa/reproductions/tree/main/vite-17529-transitive-dynamic-cjs

I think the issue a bit more nuanced and it appears that when you have dynamic import of cjs dep inside your direct dependency, such cjs dep misses "interop" step. The comment around the code below indicates this behavior is intended, but it looks like a source of inconsistency nonetheless, so probably it's fair to say this is a bug.
(I was wondering if such inconsistency can be reproduced on esbuild alone, but haven't check that yet.)

if (needsInterop === undefined) {
// Non-entry dynamic imports from dependencies will reach here as there isn't
// optimize info for them, but they don't need es interop. If the request isn't
// a dynamic import, then it is an internal Vite error

@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 Jun 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat: deps optimizer Esbuild Dependencies Optimization p3-minor-bug An edge case that only affects very specific usage (priority)
Projects
None yet
Development

No branches or pull requests

2 participants