Closed FredKSchott closed 4 years ago
This approach sounds good to me, thinking about how to do all of this. This contains a lot of information.
Is it okay to send "update" events as we traverse the DependencyTree, or should we send them all at once in a batch?
I'm trying to consider the impact of non-batching and I think I'm getting there. What if we have a function that is shared across x components. Won't we potentially render a stale tree if we have a series of updates rather than one big batch?
How do we track our progress through the DependencyTree so that we never call updateOrBubble() twice on the same node (or, would we ever need to?)
I think we should keep a Set
of visited modules in that update-series to be safe, module graphs can often reference themselves and used cyclicly
I think we should keep a Set of visited modules in that update-series to be safe, module graphs can often reference themselves and used cyclicly
+1
Won't we potentially render a stale tree if we have a series of updates rather than one big batch?
Yea, I think we the need to make the accept call synchronous, then. Right now we await it like a promise but I think sync-only is fine
Revisiting the following statement:
I'm trying to consider the impact of non-batching and I think I'm getting there. What if we have a function that is shared across x components. Won't we potentially render a stale tree if we have a series of updates rather than one big batch?
Since we are doing it in two passes:
It should not be possible to get stale trees due to an outdated parent.
Also we added the rewriting of imports, imagine a scenario where B (no accept) bubbles up to A (accept). When A is triggered again the import of B will be stale, that's why beforee we send a hot response back we'll rewrite the imports to match the ?mtime
A was requested with
Implemented in https://github.com/pikapkg/snowpack/pull/335 Going to pull a generalized solution into here next
Merged here + snowpack
published within snowpack v2.0.0-rc.3
+ esm-hmr v0.1.0
Requirements
accept()
handler, the client needs a way to "bubble up" the change event to be handled by it's parent(s)import.meta.hot
API changes, if possibleThe "Let the Server Do All The Work" Proposal
No change to the Server->Client interface. Keep existing update message format:
{type: 'update': url}
.The server stores a representation of your website dependency tree in memory:
DependencyTree { dependents: url[]; dependencies: url[]; isHmrEnabled: boolean; } }
At server startup, DependencyTree is empty.
Every time we serve a file, we scan the JS response and then update the DependencyTree with information about that one file. This never scans more than that one response.
Every time a file changes, we call
updateOrBubble(file)
:function updateOrBubble(url) { node = DependencyTree[url]; if (node.isHmrEnabled) { send to the client:
{type: 'update': url: file}
} else if (node.dependents.length > 0) { node.dependents.map(updateOrBubble); } else { // We've reached the top, trigger a full page refresh send to the client:{type: 'reload'}
} }Open Questions