Update to webpack 5 / Node.js 22 / A-Frame master / three r184#218
Open
vincentfretin wants to merge 29 commits into
Open
Update to webpack 5 / Node.js 22 / A-Frame master / three r184#218vincentfretin wants to merge 29 commits into
vincentfretin wants to merge 29 commits into
Conversation
vincentfretin
commented
Dec 30, 2025
| const difficulty = difficultyBeatmap._difficulty; | ||
| const beatmapFilename = difficultyBeatmap._beatmapFilename; | ||
| if (beatFiles[beatmapFilename] === undefined) { | ||
| continue; |
Author
There was a problem hiding this comment.
I asked about that particular change Claude did.
Original behavior: If beatFiles[beatmapFilename] was undefined, it would return from the callback and never call postMessage. This meant silent failure - the worker would just hang and never respond.
New behavior: With continue, we skip missing beatmaps but always call postMessage. If data.beats ends up empty, zip-loader properly emits songloaderror.
So the new code has better error handling - it fails gracefully with an error message instead of silently hanging.
905e84c to
78915f4
Compare
Windswipe
added a commit
to Windswipe/Moon-Rider-REBORN
that referenced
this pull request
Apr 17, 2026
…e for the zip worker
…esolving: undefined@1.0.0'
beat-generator.onClearGame iterates #beatContainer.children, which per scene.html is the container attribute for every beat and plume pool — i.e. it holds all pooled entities, in-use and already-returned. Calling returnToPool on the already-returned ones produced "returned entity was not previously pooled" warnings from A-Frame's pool (30+ per pool on every game clear, matching each pool's initial size). Move the "am I currently in use?" check into returnToPool itself so the component owns that question and any caller can safely call it more than once. Drop the position.set and visible=false fixups along the way: a returned entity is paused and invisible, and its position is set fresh the next time it's handed back out. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Forward-fix for A-Frame 1.6.0+: since the component update rework in aframevr/aframe#5474, Component.destroy() actively nulls this.data. play-sound's handler reads this.data.enabled on every event, so a lingering listener after destroy fires with this.data === undefined and throws "Cannot read properties of undefined (reading 'enabled')". Store the bound handler on the component and detach it in a new remove hook. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dispose is idempotent on three.js BufferGeometry, but nulling out this.geometry afterwards makes the `if (this.geometry)` check actually mean "there's a live geometry to dispose" and releases the stale reference so GC can collect the disposed instance. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
A-Frame 1.6.0 (commit 4a89bb6e) defers component/system init until
document.readyState === 'complete', so the envmap template image is
already fully loaded by the time this system runs. The
addEventListener('load', ...) callback was attaching after the load
event had fired and never executed, leaving envmapImg.src empty and
wall shaders sampling a blank texture — wall interiors rendered black
instead of reflecting the cyan/pink gradient.
Drop the load listener and the DOMContentLoaded guard around
createMaterials() while here — both are dead code under the new
timing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Non-normal material blending modes only take effect in three.js's transparent render pass, so the additive bloom around the merkaba star at the horizon was silently dropped and the planes rendered opaquely, exposing the underlying pink merkaba as a small pink blob instead of the bright white glow. Adding transparent: true puts them back in the transparent pass where their additive blending and depthTest: false are actually honored. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
A-Frame 1.5.0 (commit c8e8241b, "Redesign enter session UI") renamed the component from vr-mode-ui to xr-mode-ui. Without the rename no component is registered, so the querySelector + click-listener code that wires up our custom #vrButton never runs and the "Click Here to Enter VR" button is dead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
A-Frame 1.7 renamed oculus-touch-controls to meta-touch-controls,
removed the orientationOffset schema property (no longer honored), and
switched tracked-controls to hardcoded gripSpace. A-Frame also
dropped daydream-controls and gearvr-controls some releases ago.
- controller.js: setAttribute 'meta-touch-controls' instead of
'oculus-touch-controls'; drop the no-op orientationOffset; drop
daydream-controls registration and cursor config.
- debug-controller.js, super-keyboard.js, state/index.js: reflect the
same rename; drop daydream-controls/gearvr-controls entries (the
has3DOFVR list collapses to a single value).
- scene.html: the old per-controller blade rotation
(controllerType.indexOf('oculus') !== -1 ? '135 0 0' : '90 0 0')
was compensating for targetRaySpace pose. With gripSpace as the new
default, '90 0 0' is correct for every controller — verified in VR.
Drop the conditional.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
We load A-Frame from a CDN <script> tag in index.html; the local
vendor/aframe-master{,.min}.js{,.map} copies haven't been referenced
since that switch and just added noise to the repo.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
A-Frame already attaches THREE.BufferGeometryUtils (see aframe/src/lib/three.js), so the r103-era trimmed copy in vendor/BufferGeometryUtils.js is redundant. It also broke under webpack 5 because it referenced THREE as an implicit global. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Audited vendor/Curve.js and vendor/CatmullRomCurve3.js against modern
three.js: the CatmullRomCurve3 fixes (intPoint modulo, this.points
reset in fromJSON) are upstream already, and the Curve.js
optional-target GC patches for getPoints/getSpacedPoints/getLengths
are never exercised on a hot path in supercurve.js — the per-frame
getPointAt/getTangentAt calls already go through the upstream
optional-target overloads on getPoint/getTangent.
Use upstream THREE.Curve / THREE.CatmullRomCurve3 directly via the
THREE global A-Frame exposes and drop the two require() lines at the
top of supercurve.js.
Add `externals: { three: 'THREE' }` to webpack.config.js so the one
`import ... from 'three'` in src/lib/FontLoader.js resolves to
window.THREE instead of bundling a second copy of three.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
THREE.Math was removed from three.js in r125 — the helpers live on THREE.MathUtils now. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- panel-shader.js, supercurve-shader.js: A-Frame aframevr/aframe#5310 removed updateVariables and the attributes array from the Shader base class. Delegate the uniform-update work to the inherited base update via the prototype chain so our registerPanel/registerCurve side effect still runs. - trail.js: THREE.VertexColors was removed in three.js r125 — the material property is now a plain boolean. - scene.html: set renderer="colorManagement: false" so colors and textures keep the pre-1.3.0 behavior our custom GLSL was authored against. Without this A-Frame enables THREE.ColorManagement and switches outputColorSpace to sRGB, which throws off every shader that mixes raw color uniforms. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The *BufferGeometry aliases were removed from three.js: - tail.js: THREE.PlaneBufferGeometry → THREE.PlaneGeometry - wall.js: THREE.BoxBufferGeometry → THREE.BoxGeometry aframe-slice9-component still references THREE.PlaneBufferGeometry internally, so alias it back to THREE.PlaneGeometry in src/index.js before the require. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
beatsaver now serves cover images with permissive CORS headers, so the beatproxy rewrite is dead weight. Use the raw coverURL from versions[0] directly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The supermedium-sync in 8456119 dropped two pieces that are required for keyboards that ship a hover sprite (our `superkeyboard` model does — `keyboard-hover.png`): 1. Setting `src: hoverImg` on the color plane material (normal blending, sampled texture) instead of the additive-solid-color glow. 2. UV manipulation so the per-key plane samples only that key's region of the sprite. Since modern three.js replaced `geometry.faceVertexUvs` with BufferGeometry, switch to `texture.offset` + `texture.repeat` which gives the same result. Without this, the hover plane was drawn as a flat white (or `keyHoverColor`) rectangle on top of each key — an opaque white square with the letter erased behind it. The additive-glow path is preserved for keyboards without a hover sprite, and setAttribute declares `blending: 'additive'` directly instead of relying on a componentinitialized listener (which now fires synchronously and was being attached too late). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
68e0132 to
f2bf1cf
Compare
- package.json: vendor/ was removed from the repo, so drop it from the predeploy cp list. - webpack.config.js: set publicPath to 'auto'. On moonrider.xyz it still resolves to /build/ (same as the old '/build'), and it also lets the build work when served from a subpath (e.g. a GitHub Pages fork at /moonrider/). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Drop the "Get Updates on Our Upcoming VR Projects!" email capture form — the endpoint (supermedium.com/mail/subscribe) and associated tracking no longer make sense here. Keep a small Discord link in the bottom-left corner so the community pointer is still visible. Removes: the #subscribeForm block in index.html, the associated CSS (#subscribeForm, inputs, buttons), and initSubscribeForm() plus its DOMContentLoaded listener in src/index.js. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The absolute /assets/img/banner.jpg path only resolves correctly when the site is served from the root of a domain. A relative path works regardless of the base path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I didn't manage to run that project on an old version of Node.js with nvm,
so I updated webpack from version 4 to 5 so we can run the project on latest Node.js LTS 22.
I removed all babel transforms, none were used actually, also removed the unused zip-loader dependency.
webpack 5 doesn't include nodejs polyfills anymore, so it was easier to rewrite the zip worker, Claude Claude Opus 4.5 replaced unzip-js + Node.js polyfills with fflate - a modern, fast, pure JS zip library that works natively in browsers without polyfills. It's also smaller and faster.
Things that were fixed are the star, controllers reconnection and haptics (with the update to aframe master), the hover on the keyboard letters, the song cover, better perf running at 90fps (because latest aframe contains the pool component optimization, that was in Dec 24 2022 included in 1.4.0 aframe release), remove the subscribe to newsletter that doesn't exist anymore.
Nice to have before merging: