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

ssrLoadModule does not load nested dependency #3609

Closed
6 tasks done
michenly opened this issue May 31, 2021 · 9 comments
Closed
6 tasks done

ssrLoadModule does not load nested dependency #3609

michenly opened this issue May 31, 2021 · 9 comments

Comments

@michenly
Copy link

michenly commented May 31, 2021

Describe the bug

Original issue discovered: #3464 (reply in thread)

I have a vite plugin that make use of the ssr argument in resolveId hook. The main purpose of the plugin is to replace @shopify/polyfills/fetch with @shopify/polyfills/fetch.node when its on the server and @shopify/polyfills/fetch.browser when it is on the client.

This plugins work on the client side, but break when ssrLoadModule is use to load the server entry point.

Some investigations

I have tired to replace @shopify/polyfills/fetch with a random virtual module (ie. virtual:fetch-polyfill) and that work.

Reproduction

Use the branch https://github.com/michenly/app-proving-ground/tree/vite-ssr-dep

Case 1: client side only with a index file

  • Run yarn dev
  • See the application working with a list displayed in the browser.

Case 2: ssr using vite middleware and ssrLoadModule

  • Run yarn run ssr
  • See the application fail with the following error

Screen Shot 2021-05-31 at 5 04 50 PM

Case 3: same as 2, but using virtual module

  • Change @shopify/polyfills/fetch to virtual:fetch-polyfill in both the plugin and the client import in GraphQL.tsx
  • Run yarn run ssr
  • See the following error which mean the module is broken. But it is loaded on server side.

Screen Shot 2021-05-31 at 5 04 12 PM

System Info

Output of npx envinfo --system --npmPackages vite,@vitejs/plugin-vue --binaries --browsers:

System:
    OS: macOS 11.3.1
    CPU: (8) x64 Intel(R) Core(TM) i7-8559U CPU @ 2.70GHz
    Memory: 338.92 MB / 16.00 GB
    Shell: 4.4.23 - /usr/local/bin/bash
  Binaries:
    Node: 16.1.0 - /usr/local/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 7.11.2 - /usr/local/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  Browsers:
    Chrome: 90.0.4430.212
    Firefox: 72.0.2
    Safari: 14.1
  npmPackages:
    vite: ^2.2.3 => 2.2.3

Used package manager: yarn


Before submitting the issue, please make sure you do the following

@Aslemammad
Copy link
Contributor

@michenly One time I encountered the error "Error when evaluating ..." I fixed that specific error by adding it to the SSR externals

    name: 'vitext',
    config: () => ({
      ssr: {
        external: [
          'prop-types',
          'react-helmet-async',
          'vitext/document',
          'vitext/react',
        ],
      },
 ...

@aleclarson
Copy link
Member

aleclarson commented Jul 12, 2021

While ssrLoadModule does use resolveId hooks on the URL passed to it, those hooks will not be used for bare imports (which @shopify/polyfills/fetch is) from within the loaded module.

This is by design, as bare imports are assumed to be installed in node_modules.

As I understand it, you have two options here:

  • Wait for #3951 to be merged, then try using resolve.alias
  • Add an exports field to the package.json of @shopify/polyfills so that NodeJS requires the right module

@michenly
Copy link
Author

hi @aleclarson @shopify/polyfills actually does have an exports field.

the problem is that my alias need to be decided bases on ssr value (use node polyfill=@shopify/polyfills/fetch.node in server & browser polyfill=@shopify/polyfills/fetch.browser in client)

so unless resolve.alias in the future would accept a method with ssr value as param it wont work in my situation.

can you tell me a little more about what is consider a bare imports? Since @shopify/polyfills/fetch does not actually resolve to anything maybe there are more things that can be check?

@aleclarson
Copy link
Member

The exports field you linked does not have a key for ./fetch (without .node or whatever).

See this example for guidance.

@michenly
Copy link
Author

@aleclarson oh interesting! can there be other keyword other than browser or node ? If you have any doc I can peek at that would be wonderful.

I am assuming the idea is Vite (and maybe webpack?) will automatically use the node & browser field without me having to alias them myself?

@aleclarson
Copy link
Member

It depends. To support the exports field, Vite uses the resolve.exports package, which has a conditions option for deciding which keywords to look for. Note that Vite SSR does not use that package, but this will change with #3951.

@michenly
Copy link
Author

Thank you so much for the explanation Alec! It had been really helpful!

@bluwy
Copy link
Member

bluwy commented Mar 9, 2022

Hi @michenly, does this issue still relevant in Vite? From Alec's explanation, it does seem like ssrLoadModule is working as intended, and exports should be used instead to control loading for node or the browser instead of having a Vite plugin to control that.

@bluwy
Copy link
Member

bluwy commented Mar 14, 2022

I think the correct solution here is to use exports to load between node and browser, or alias as a workaround for the package. Closing as it seems to be working as intended.

@bluwy bluwy closed this as completed Mar 14, 2022
@github-actions github-actions bot locked and limited conversation to collaborators Mar 29, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants