S
SolidJS•14mo ago
lemonad

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
andi
andi•14mo ago
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
lemonad
lemonadOP•14mo ago
@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.
andi
andi•14mo ago
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:
const { something } = await import("second-package");
const { something } = await import("second-package");
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 would
lemonad
lemonadOP•14mo ago
Ah, 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 😄
frontend build: ../dist/assets/Hello-ef0d64f9.js 2.71 kB │ gzip: 1.43 kB │ map: 9.75 kB
frontend build: ../dist/assets/App-01dc259b.js 355.24 kB │ gzip: 91.67 kB │ map: 1,224.62 kB
frontend build: ../dist/assets/Hello-ef0d64f9.js 2.71 kB │ gzip: 1.43 kB │ map: 9.75 kB
frontend build: ../dist/assets/App-01dc259b.js 355.24 kB │ gzip: 91.67 kB │ map: 1,224.62 kB
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.
andi
andi•14mo ago
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
lemonad
lemonadOP•14mo ago
@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
render(
() => (
<Show when={App}>
<Router>
<App />
</Router>
</Show>
),
document.getElementById("app") as HTMLElement,
);
render(
() => (
<Show when={App}>
<Router>
<App />
</Router>
</Show>
),
document.getElementById("app") as HTMLElement,
);
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
<Routes>
<Route
path="/"
element={<Hello mainRoutesLoaded={mainRoutesLoaded()} />}
/>
<MainRoutes
setMainRoutesLoaded={setMainRoutesLoaded}
/>
</Routes>
<Routes>
<Route
path="/"
element={<Hello mainRoutesLoaded={mainRoutesLoaded()} />}
/>
<MainRoutes
setMainRoutesLoaded={setMainRoutesLoaded}
/>
</Routes>
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 Routes:
<>
<Route
path="..."
<>
<Route
path="..."
Want results from more Discord servers?
Add your server