Hi! I know the basis of threejs and am creating a 3D modelling portfolio for a friend. We have chosen Fiber for me to also control things better as a web dev, so I am not sure if this appropriately goes here or leans more towards Stack Overflow. In any way, thanks for all feedback!
The main issue I have right now is that the loading time seems a bit too long. 3D model optimization is off the table since that’s what’s to showcase in the portfolio.
Upon arrival, the screen stays blank (with the “root” html content in any case) and takes about 3 seconds to load into the Drei and then takes about 0.5s loading before actually showing the scene.
The problem to tackle is that white screen time. I have seen many threejs projects that show a loading screen in (I suppose) threejs. Would this be possible to do in React? Maybe link a js file with the loading screen, or set a script in the root? Thanks in advance.
I fixed the whitescreen by adding a loading screen in the index.html like so:
<body>
<div id="preloader">
<img src="./textures/test.png" alt="Loading..." class="loadingLogo" />
</div>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
<script>
// Hide the preloader once the main content has loaded
window.addEventListener("load", function () {
const preloader = document.getElementById("preloader");
if (preloader) {
preloader.style.display = "none";
}
});
</script>
</body>
Hope it helps!
Somewhat ironically, an animated gif can be good for this because they run on a separate thread and animate even while you’re blocking the main thread.
in react loading is inbuilt, with suspense. for instance this is how you bundle split/lazy load the whole canvas. threejs and the scene and its models won’t be part of the initial load that way. the site will be there instantly.
import { lazy, Suspense } from 'react'
// import ThreeApp from './Scene'
const ThreeApp = lazy(() => import("./Scene"))
export function App() {
return (
<div>
...
<Suspense fallback={<Loader />}>
<ThreeApp />
</Suspense>
you can use suspense to await the canvas itself and all of its loading assets and models
<Suspense fallback={<div>im loading</div>}>
<Canvas>
<SomeModel />
you can use suspense within canvas to await any async asset
<Canvas>
<Suspense fallback={<SpinningCube />}>
<SomeModel />
i would still suggest you compress your models no matter what. a glb shouldn’t be bigger than 1-2mb, you can compress environment maps and textures as well. here’s an easy tool to reduce models:
npx gltfjsx yourmodel.glb --transform
overall i would try to avoid loading screens. they are often just a cover for bad practices. if you optimize assets and code you do not need it. compress all assets, use bundle splitting, only load stuff when you need it, make sure your bundler supports tree shaking so that it creates the smallest /dist possible.
Thanks for the solution! Will give it a try too.
Thanks for the feedback. Since I’m very new to optimization I did, indeed, want to cover up bad practices… But thanks for taking some time to give some guidelines. I’ll implement everything you said; thank you!