Svelte中先加载全局加载器再异步加载Three.js大动画组件的方案
优化实现思路(Svelte + Three.js 全屏预加载器)
1. 优先渲染加载器,避免初始阻塞
直接在根组件(如App.svelte)最外层编写加载器DOM,默认显示,让浏览器优先渲染加载器,无需等待任何JS打包块或资源加载完成。加载器的CSS建议内联或放在全局样式最顶部,避免出现无样式闪烁(FOUC)。
<script> let loaded = false; let loadError = false; import { onMount } from 'svelte'; import { fade } from 'svelte/transition'; </script> <!-- 优先渲染的全屏加载器 --> {#if !loaded && !loadError} <div class="loader-overlay" transition:fade={{ duration: 300 }}> <div class="loader-spinner"></div> <p>加载资源中...</p> </div> {:else if loadError} <div class="error-state">加载失败,请刷新页面重试</div> {:else} <!-- Three.js动画组件,加载完成后才渲染 --> <ThreeScene /> {/if} <style> .loader-overlay { position: fixed; inset: 0; background: #1a1a1a; display: flex; flex-direction: column; align-items: center; justify-content: center; z-index: 9999; color: #fff; } .loader-spinner { width: 60px; height: 60px; border: 4px solid #333; border-top-color: #0070f3; border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } </style>
2. 懒加载Three.js及依赖,分离打包块
不要在根组件顶部同步导入Three.js核心或大型动画组件,改用**动态import()**异步加载,将非初始必需的代码拆分到独立打包块,减小初始加载体积,让加载器更快显示。
<script> // ... 其他变量定义 onMount(async () => { try { // 异步加载Three.js核心(可指定子模块减小体积,如仅加载需要的Loader) await import('three/addons/loaders/GLTFLoader.js'); // 异步加载自定义动画组件 const { default: ThreeScene } = await import('./components/ThreeScene.svelte'); // 批量加载资源(模型、纹理、 shader 等) await Promise.all([ loadGLTFModel('/models/animation.glb'), loadTexture('/textures/envmap.hdr') ]); loaded = true; } catch (err) { loadError = true; console.error('资源加载失败:', err); } }); // 封装资源加载函数 async function loadGLTFModel(url) { const { GLTFLoader } = await import('three/addons/loaders/GLTFLoader.js'); return new Promise((resolve, reject) => { new GLTFLoader().load(url, resolve, null, reject); }); } </script>
3. 添加加载进度反馈
使用Three.js的LoadingManager统一管理所有资源加载,实时更新进度值,给用户明确的加载状态,避免等待焦虑。
<script> import { LoadingManager } from 'three'; let progress = 0; onMount(async () => { const manager = new LoadingManager(); // 实时更新加载进度 manager.onProgress = (_url, loadedItems, totalItems) => { progress = Math.round((loadedItems / totalItems) * 100); }; manager.onLoad = () => loaded = true; // 绑定manager到所有资源加载器 const gltfLoader = new GLTFLoader(manager); await gltfLoader.loadAsync('/models/animation.glb'); // 其他资源加载... }); </script> {#if !loaded} <div class="loader-overlay"> <div class="progress-bar"> <div class="progress-fill" style="width: {progress}%"></div> </div> <p>{progress}% 加载中...</p> </div> {/if}
4. 预加载关键资源加速加载
在index.html的<head>中添加<link rel="preload">,让浏览器优先加载Three.js打包块、核心模型/纹理等关键资源,缩短总加载时间。
<head> <!-- 预加载Three.js组件打包块 --> <link rel="preload" href="/build/three-scene.js" as="script"> <!-- 预加载核心3D模型 --> <link rel="preload" href="/models/animation.glb" as="fetch" crossorigin> </head>
内容的提问来源于stack exchange,提问作者Noir
相关产品推荐
相关产品推荐

