npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@overworld-engine/loading

v1.5.0

Published

Asset loading progress and scene preloading

Readme

@overworld-engine/loading

资源加载进度管理:一个纯逻辑的加权任务进度 store,外加两个 React/drei 辅助 Hook(GLTF 预加载、three.js 加载进度桥接)。纯 store 与 React 部分位于不同 模块,store 可在无 React / 无浏览器环境下直接使用与测试。

纯 store:useLoadingStore

以"任务(task)"为单位跟踪加载:每个阶段或资源组注册一个任务,可设置权重, store 自动推导整体进度与加载状态。

import { useLoadingStore } from '@overworld-engine/loading'

const { beginTask, setTaskProgress, completeTask } = useLoadingStore.getState()

beginTask('models', 3)          // 权重 3
beginTask('audio')              // 权重默认 1
setTaskProgress('models', 0.5)  // 任务内进度 0–1
completeTask('audio')

useLoadingStore.getState().progress   // (3*0.5 + 1*1) / 4 = 0.625
useLoadingStore.getState().isLoading  // true(models 未完成)

API:

  • beginTask(id, weight?) — 开始(或重新开始)一个任务;权重决定其在总进度中的占比。
  • setTaskProgress(id, progress) — 更新任务内进度(自动钳制到 0–1;未知 id 会自动创建)。
  • completeTask(id) — 标记任务完成(进度置 1)。
  • reset() — 清空全部任务。
  • 派生字段:progress(0–1 加权总进度)、isLoading(存在未完成任务时为 true)、 tasks(按 id 索引的任务表)。
  • computeProgress(tasks) — 纯函数,可独立复用聚合逻辑。

已完成的任务在 reset() 之前保持注册,保证总进度分母稳定、不会回跳。

React 辅助(@react-three/drei)

import { useAssetPreload, useSceneLoadProgress } from '@overworld-engine/loading'

// 预加载 GLTF(封装 useGLTF.preload,每个 URL 仅预加载一次)
useAssetPreload(['/models/player.glb', '/models/portal.glb'])

// 在 Canvas 内桥接 drei useProgress → loadingStore(任务 id 默认 'scene-assets')
function LoadTracker() {
  const { active, progress } = useSceneLoadProgress()
  return null
}

useSceneLoadProgress(taskId?) 会在 three.js 加载器活跃期间把进度写入对应 任务,加载器空闲后自动 completeTask,并返回 drei 的原始进度快照 { active, progress, item, loaded, total }

资产清单(Asset Manifest)

把场景/游戏用到的资产声明成纯数据,按场景拆分、可组合、可提前预热:

import { defineAssetManifest, mergeManifests, preloadManifest } from '@overworld-engine/loading'

// 每个场景一份清单(defineAssetManifest 是恒等函数,只提供类型推断)
export const VILLAGE_ASSETS = defineAssetManifest({
  models: ['/models/characters/guide.glb', '/models/props/crystal.glb'],
  audio: ['/audio/bgm/village.mp3'],
  images: ['/images/village-map.png'],
})

// 组合多份清单(按类别去重、保持首次出现顺序)
const ALL_ASSETS = mergeManifests(VILLAGE_ASSETS, DUNGEON_ASSETS)

// 启动时(或进场景前)发起浏览器预加载
preloadManifest(ALL_ASSETS)
preloadManifest(VILLAGE_ASSETS, { categories: ['models'] }) // 只预热部分类别

preloadManifest 的行为:

  • models → drei useGLTF.preload(与场景组件共享同一 GLTF 缓存);
  • imagesnew Image().src;
  • audionew Audio()preload = 'auto';
  • fonts跳过,仅作清单记录(drei <Text> 自行加载字体,CSS 字体请用 @font-face / <link rel="preload">);
  • 每个 URL 每会话只预热一次;Node/SSR(无 window)环境下为 no-op。

设计说明:preloadManifest 不写 loading store、不上报进度。 这些预加载 API (useGLTF.preload / Image / Audio)本身不提供细粒度进度,注册假任务只会骗 UI。 真实的模型加载进度由 three.js 加载管理器产生,在场景挂载后经 useSceneLoadProgress 桥接进 store——清单负责"尽早开始",进度显示交给那个 Hook。

依赖

peerDependencies:reactzustand@react-three/drei。 纯 store(useLoadingStore / computeProgress)只依赖 zustand