fastify-vite
fastify-vite copied to clipboard
Generating preload directives or changing bundle included in rendered HTML
Prerequisites
- [X] I have written a descriptive issue title
- [X] I have searched existing issues to ensure the feature has not already been requested
🚀 Feature Proposal
Let's say we have an example app with the following routes:
/ -> HomePage /about -> AboutPage
And assume in the project, I've implemented code splitting (using await import
) - to make sure AboutPage and HomePage bundles are separate.
- When I land on "localhost:3000/" - the generated HTML should only contain the bundle for HomePage - and preload directives for the HomePage
- Likewise, when I land on "localhost:3000/about" the generated HTML should only contain the bundle for AboutPage - and preload directives for the HomePage
And finally, along the same lines:
- To implement "preload on hover" i.e. preload the bundle when user hovers on the link to another page
Motivation
Being able to only load the bundles required for the page being rendered.
I can currently see config values exposed for customising the template, but nothing for customising the bundle that gets added to the HTML.
Things I am unable to see a clear picture (as a Vite newbie):
- How we can use the ssr-manifest to find the bundles used in the current render path (i.e. how do we know the moduleIds, especially when rendering React?)
- How Vite or Fastify-Vite is inserting the bundle in the first place
Example
There is an example on the Vite SSR docs: https://vitejs.dev/guide/ssr.html#generating-preload-directives (with some broken links) - where they suggest that the vite-vue plugin contains support for collecting moduleIds on render - no equivalent for React.
How we can use the ssr-manifest to find the bundles used in the current render path (i.e. how do we know the moduleIds, especially when rendering React?)
Indeed, that is a question I have myself now — and is currently unanswered. With Vue, running renderToString()
(the SSR function) with a context object will get you ctx.modules
, which you can then use to do the mapping, but I haven't found a working alternative for React yet — or maybe haven't looked hard enough.
How Vite or Fastify-Vite is inserting the bundle in the first place.
The bundle comes from the /mount.js
include in index.html
.
Vite automatically transforms that, both in development and production modes.
⁂
As for code-splitting, it's already possible. The vue-hydration
example has lazy-loaded routes. For React, lazy-loading of routes now requires you to use SSR in streaming mode otherwise it just doesn't work (having React.lazy()
, that is). I'm working on a new set of examples that demonstrate all of this in place for React.
Let's keep this issue open to track this.
Thanks for the reply @galvez - and great to get the conversation started.
which you can then use to do the mapping, but I haven't found a working alternative for React yet — or maybe haven't looked hard enough
yeah me neither - its a complete mystery to me still. However - I wonder if we do codesplit across routes using import
- I wonder ssr-manifest will have the required bundles per route. What we do in Redwood is we create a "base" app bundle (included with all pages) - then dynamically load the bundles per route. We're able to do this because Webpack is smart enough to know what a shared chunk is, and what isn't. I suspect the solution here will need to be something similar.
The bundle comes from the /mount.js include in index.html.
Yup - but I wonder if we have more control over this? For example - when I go to /mystaticpage, and this page is completely prerendered (i.e. no need for js) - would I be able to disable hydration and remove the JS bundles all together?
We're able to do this because Webpack is smart enough to know what a shared chunk is, and what isn't.
This is exactly how Vite behaves as well.
would I be able to disable hydration and remove the JS bundles all together?
Yes, I'm actually almost done with an example demonstrating just that!