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

Purely dynamic import with dependency returns empty MIME type #2525

Closed
3 tasks done
elevatebart opened this issue Mar 16, 2021 · 7 comments · Fixed by #2548
Closed
3 tasks done

Purely dynamic import with dependency returns empty MIME type #2525

elevatebart opened this issue Mar 16, 2021 · 7 comments · Fixed by #2548

Comments

@elevatebart
Copy link
Contributor

⚠️ IMPORTANT ⚠️ Please do not ignore this template. If you do, your issue will be closed immediately.

Describe the bug

I want to purely dynamically import a file that has npm dependencies. When doing so, the dependencies are found and optimized at runtime. When they are found (and not yet optimized), I get the following error:

Failed to load module script: The server responded with a non-JavaScript MIME type of "". Strict MIME type checking is enforced for module scripts per HTML spec.

Reproduction

https://github.com/elevatebart/vite/tree/fix/import-depnedncy-mime-type/packages/playground/dynamic-import

In this example, I added an npm dependency to the dynamic-import playground under the 'bar' view.
When I click on the 'bar' button, I get the error before I refresh.

System Info

  • vite version: 2.1.0
  • Operating System: MacOS Big Sur
  • Node version: 12.18.3
  • Package manager (npm/yarn/pnpm) and version: yarn 1.22.3

Logs (Optional if provided reproduction)

  1. Run vite or vite build with the --debug flag.
  2. Provide the error log here.

Investigation results

On this line we return an invalid MIME type that could block some testing engines and wrongly flag some pages as faulty.

Would it make sense to simply not respond or respond with a timeout instead?

I would have this kind of idea in mind:

    if (
      server._pendingReload &&
      // always allow vite client requests so that it can trigger page reload
      !req.url?.startsWith(CLIENT_PUBLIC_PATH) &&
      !req.url?.includes('vite/dist/client')
    ) {
      // missing dep pending reload, hold request until reload happens
      server._pendingReload.then(() =>
        setTimeout(() => {
          res.end()
        }, TIMEOUT)
      )
      return
    }

Awaiting your opinion before suggesting a fix.
Surfing the Vite wave!
Amicalement

@yyx990803
Copy link
Member

Hmm yeah I think a reasonable timeout should fix this... can you try it?

@elevatebart
Copy link
Contributor Author

elevatebart commented Mar 16, 2021

I did, and it does fix it.
I am struggling to create a test.

Should I draft a Pull request?

@elevatebart
Copy link
Contributor Author

PS: I was thinking of 5 seconds timeout to take slow ws into account.

@yyx990803
Copy link
Member

Is the MIME type error the only issue here? Does it actually cause any other problems?
Maybe just setting the Content-Type header is easier.

@elevatebart
Copy link
Contributor Author

When responding with the MIME, another issue occurs saying the import does not export anything.

Uncaught (in promise) SyntaxError: The requested module '/@fs/Users/bart/Documents/github/vite/node_modules/lodash/lodash.js' does not provide an export named 'isBoolean'

The naive in me says: "The server could respond with the compiled/optimized file even with a delay and avoid the reload."
What was the reason for this full-reload? Performance? Code readability?

@elevatebart
Copy link
Contributor Author

I made a quick PR with a test for it.
The test shows how odd it is to use.

I like my initial solution because it works.
The ideal solution would be to immediately return the optimized dependency.

I will keep on hacking but since I do not know when/if I will make more progress soon, my PR can be merged as is.

@elevatebart
Copy link
Contributor Author

As a user, I might click on a dependency and get a complete re-init of my page (no state would be kept). When working on an app without routing that could prove unsavory.

I looked into avoiding this refresh, it is more complicated than I naively thought.
I understand that we not only need to optimize the dependency itself, we also need to compile the dependent. The file that calls the node dependency needs to be modified to accept the new ESModule. This re-compilation triggers its own parent re-compilation etc until the initial import request inside the HTML page. This could require a complete refresh of the HTML page but not necessarily.

I will keep on hacking and reporting my findings.

@github-actions github-actions bot locked and limited conversation to collaborators Jul 16, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants