Ramonda

RMD049 — Two lazy functions with the same source

const make = (path: string) => () => import(path);

<AsyncLoad lazy={make("./Dashboard")} onLoading={<i />} errorFallback={<i />} />
<AsyncLoad lazy={make("./Settings")} onLoading={<i />} errorFallback={<i />} />
<AsyncLoad cacheKey="./Dashboard" lazy={make("./Dashboard")} onLoading={<i />} errorFallback={<i />} />
<AsyncLoad cacheKey="./Settings" lazy={make("./Settings")} onLoading={<i />} errorFallback={<i />} />

AsyncLoad identifies a module by the source of its lazy, which works when that source names one. () => import("./Thing") says what it loads, so the same import written in two components is two different functions with one meaning — and they share a cache entry, which is what you want.

A lazy a factory built names nothing: the path it closed over is not part of the source, so every module the factory produces stringifies the same. Left alone, the first would load and cache and the second would render the first one's module — nothing failing, nothing logged, and which module you got depending on which rendered first.

Which of the two you have written cannot be read from the text of the function — the source a bundler leaves behind is its own business, and a rule looking for a literal specifier would read one bundler's output correctly and another's backwards. So nothing is guessed: when a second lazy meets a key that is already taken, its module is loaded and compared. The module system serves a genuine duplicate from its own registry, so the ordinary case pays one resolved promise and confirms the sharing.

A module that turns out to be a different one is given a key of its own. It then renders what it asked for; what it loses is the shared cache entry — a loading frame the second time. cacheKey gives that back, and a route table that builds its lazies from a list is the usual way to meet this.

See lazy loading for the whole picture.

Next