A-Frame Hot-Reload Component Reinitialization Order Lacks a Documented Configuration
0 reputation · 05 Oct 2023, 11:29 UTC
0 reputation · 05 Oct 2023, 11:29 UTC
A-Frame's hot-reload workflow, commonly provided by plugins such as aframe-hot-reload, re-instantiates a component when its source changes instead of reloading the whole page. The goal is a repeatable development environment: a scene should reach the same state after a hot reload as it does after a full refresh.
The missing constraint is ordering. A-Frame does not document a configurable reinitialization order for hot reloads. In a scene where one component reads state that a sibling component sets during its own init, the reading component can run before the provider has been re-instantiated, and the resulting order may differ between reloads. Guard flags and deferred reads in tick are developer conventions, not framework-enforced guarantees.
Is there a documented setting or lifecycle hook that makes component reinitialization order deterministic during hot reload? Should dependent reads be moved out of init into update or tick so ordering no longer matters? Is a full page refresh currently the only reliable way to reproduce production-like initialization order?
35275 reputation · 05 Oct 2023, 20:38 UTC
There is no documented setting or native lifecycle hook in A-Frame to enforce a deterministic reinitialization order specifically for hot-reload events. Because hot-reload plugins typically operate by removing and re-adding a specific component to an entity, they bypass the global declaration order established during the initial page load.
In a standard page load, A-Frame initializes components based on their declaration order in the HTML. However, a hot-reload event is a targeted mutation. When a single component is re-instantiated, it triggers its init and update methods immediately. If that component depends on state provided by a sibling component that has not been re-instantiated (or is in the process of being updated), a race condition occurs.
To ensure a repeatable development environment without relying on full page refreshes, you should move dependent reads out of init. The following patterns are the established ways to handle inter-component dependencies:
update: Use the update handler to react to changes. Since update is called after init and whenever a component property changes, it is more resilient to the timing of sibling instantiation.tick: If a component requires a state that may not exist yet, check for the existence of that state in the tick function. Once the dependency is detected, execute the logic and disable the check to avoid performance overhead.state-ready) upon completion of its init. The "consumer" component should listen for this event rather than assuming the provider is ready during its own init.A full page refresh remains the only native way to guarantee that the production initialization sequence (based on HTML declaration order) is followed exactly. To verify if your hot-reload logic is diverging from production, you can use the following diagnostic approach:
// Add to the init() of both provider and consumer components
console.log(`[${this.el.id}] ${this.componentName} initialized at ${performance.now()}`);
Compare the timestamps between a hard refresh and a hot-reload to identify the specific shift in execution order.
To provide a more specific architectural recommendation, please specify if you are using a custom build of aframe-hot-reload or a specific integration (like Vite or Webpack), as the method of component replacement can vary by plugin.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.