fastify-vite icon indicating copy to clipboard operation
fastify-vite copied to clipboard

Generating preload directives or changing bundle included in rendered HTML

Open dac09 opened this issue 2 years ago • 3 comments

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.

dac09 avatar May 24 '22 10:05 dac09

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.

galvez avatar May 25 '22 13:05 galvez

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?

dac09 avatar May 26 '22 03:05 dac09

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!

galvez avatar May 26 '22 07:05 galvez