Loading screen for app
I'm a bit out of my depth with this question but essentially, I've got a Solid app running on embedded devices which in some rare cases have really poor wifi so the initial load of the page takes a long time without the user getting feedback on what's going on. I've been contemplating two solutions: one where I add a loader in JS that loads the solid app (but here the problem is that I don't quite know how to integrate this with Vite and everything) or one where a small part of the Solid app loads first and then the major part load later. I much prefer the second solution but then I run into the problem that I do not want all components lazy loaded individually (because the app might lose wifi later and then the available functionality depends on what parts the user have visited). I want everything else to be loaded as a single chunk if that makes sense. It seems like this might not be possible but I wanted to pose the question just in case.
It is quite possible that I'm going about this entirely backwards so please let me know if there's some alternate solution I'm not thinking of : )
6 Replies
this depends a lot on how your app is structured but for an idea that might point you into the right direction
split your codebase into 2 packages, and use the manualChunks rollup option in vite to create 2 chunks for your app based on the 2 packages (https://vitejs.dev/guide/build.html#chunking-strategy)
make sure that the second chunk is dynamically imported only when it's needed
you might run into many issues though depending on what you need to set up in the second chunk, global stuff like routes and such will probably have to stay in the initial chunk
@andi Thanks so much for the tip! I'm actually already using manualChunks already but the problem I don't know how to solve with separating it into two chunks like I think you suggest is that I don't know how to lazy load (or similar) the entire second, major chunk. I don't want to lazy load each component separately because then parts of the app might become unavailable when offline.
Just splitting it into chunks will not help, I believe, as then both chunks will still be loaded by the main page. I'll try though.
so if you split them into two packages, anything that you use from the second chunk would come from an import, something like
import {something} from "second-package"
this is the part that's hard, but if you structure your app in such a way that any functionality coming from the second package you import like this:
and you only trigger those imports when you actually want the second chunk to be fetched, i think it might work
you could probaly set up an experiment manually, with some js files you create yourself by hand with some simple functions and see if you can make the second one only be fethched when you click a button or run a function from the browser console
it might also just not worked, i've never tried this before but logically it seems like it wouldAh, didn't think about imports being promises. I tried some stuff now but I have to figure out how to create a minimal chunk for the routing as well as a minimal chunk for the initial page that doesn't depend on the entire vendor chunk.
(I'm using the
splitVendorChunkPlugin
vite plugin)
The vendor chunk is unfortunately 400kb compressed (1.1Mb uncompressed) due to Plotly 😄
Ah, it's actually more that I need to figure out how to async import all the other stuff so that the App routing + Hello page does not depend on all other components.
Another problem is that as soon as I put something in manualChunks
, it is added to index.html
as a separate download. Perhaps that easy to fix though as using lazy
doesn't do it.you could explore other options too
like reducing the whole bundle size, maybe review your dependencies and reimplement the ones that are too big with code that works just for your app
usually generic libraries have a lot of extra code to handle things that you might not ever run into in your app
@andi Just wanted to get back to you with an update. I have managed to progress quite a bit, only thing I haven't managed is to split out vendor stuff for the main chunk (which is now > 1MB). Something I would like to do as that changes rarely compared to the application code. These are some of the things I did:
I removed all code splitting from the vite config (
manualChunks
, splitVendorChunkPlugin
) as that was putting things in my index.html
to be immediately loaded.
I made some changes to index.html
such as adding basic styling for the body and a div
showing "Loading..." which is hidden once the solid app loads. This is pretty much only shown if the network is super slow.
In my index.tsx
, I lazy load App
and then use
I don't really remember why I set it up this way but I think it was to make the initial chunk to load as small as possible.
In App
, I lazy load my main routes and then use
The first thing I do in MainRoutes
is set the signal mainRoutesLoaded
so that I can progress to the main app from the Hello
loading screen.
Thanks for the help on the way!
Adding that MainRoutes
is just returning a list of Route
s: