Mithril m.mount on a legacy-managed DOM node: teardown and route prefix conflicts during incremental migration
0 reputation · 22 Feb 2024, 16:44 UTC
0 reputation · 22 Feb 2024, 16:44 UTC
I am planning an incremental migration of a small single-page application to Mithril (v2.x) without downtime. The goal is to use m.route and m.mount so that selected routes render new Mithril components while the rest of the page continues to be served by the existing legacy framework.
The open uncertainty is how Mithril's redraw and lifecycle behavior interacts with DOM nodes already controlled by another library. The documentation describes mounting on an arbitrary DOM element, but it is not explicit about what happens when that element was previously initialized by different code, or whether m.route.prefix preserves scroll position and focus when swapping implementations under the same prefix.
Specifically:
m.mount handle cleanup when attached to a DOM element previously initialized by another framework — does unmounting remove only Mithril's own listeners and children?m.route.prefix intercepts paths that a legacy global router also handles, and does either side risk double-handling navigation?32775 reputation · 22 Feb 2024, 18:50 UTC
1. Cleanup after m.mount on a legacy‑managed node
m.mount replaces the target element’s innerHTML with the virtual‑DOM output of the component tree.unmount (or when a new component is mounted over the same node), Mithril removes only the event listeners and DOM nodes it created. It does not touch listeners that were added by other frameworks unless those listeners were attached via m.mount itself.addEventListener or jQuery .on()) will survive a Mithril unmount, but any listeners that were delegated through Mithril’s internal m.mount call will be cleaned up.2. Route prefix clashes with a legacy router
m.route.prefix merely matches the beginning of the URL (e.g., /app). It does not intercept the event that actually changes the URL – that is still handled by the browser’s hashchange or popstate events.3. Scroll position and focus preservation
window.scrollY or element focus. On a route swap the page scrolls to the top and focus is lost.const prevScroll = window.scrollY;
const prevFocus = document.activeElement;
m.route.set('/new');
// after the new component has rendered
m.redraw(() => {
window.scrollTo(0, prevScroll);
if (prevFocus) prevFocus.focus();
});
4. Practical Checklist for the Migration
if (!document.querySelector('#app .mithril')) {
legacyInit();
}m.mount on the same element and store a reference to the component instance.m.mount(null, null) to unmount and rely on Mithril’s cleanup. Verify via console.log that event listeners are removed.hashchange/popstate listeners for the m.route.prefix path.m.route.set or in the Mithril component’s onunload hook.5. Diagnostic Detail Needed
To refine the recommendation, could you confirm whether the legacy framework attaches its event listeners directly to the target DOM element, or does it use event delegation on a higher‑level ancestor?
Mithril’s m.mount cleans up only what it owns, route prefixes can clash if both routers are active, and scroll/focus preservation is not automatic. By guarding legacy listeners, disabling overlapping router events, and adding explicit scroll/focus handling, you can achieve a zero‑downtime incremental migration.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.