fastify / fastify-vite

Fastify plugin for Vite integration
MIT License
885 stars 73 forks source link

Generating preload directives or changing bundle included in rendered HTML #80

Open dac09 opened 2 years ago

dac09 commented 2 years ago

Prerequisites

🚀 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.

And finally, along the same lines:

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):

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.

galvez commented 2 years ago

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.

dac09 commented 2 years ago

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?

galvez commented 2 years ago

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!