-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix lazy compilation #9093
Fix lazy compilation #9093
Conversation
@@ -353,10 +353,12 @@ export default class AssetGraph extends ContentGraph<AssetGraphNode> { | |||
nodeId !== traversedNodeId | |||
) { | |||
if (!ctx?.hasDeferred) { | |||
this.safeToIncrementallyBundle = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do any of the other cases here need this added?
The symptoms I saw was that while the asset graph was correctly updated after a previously lazy bundle was requested, the bundle graph was not - so I've focused on cases where dependency nodes have changed from deferred to not deferred, rather than asset nodes.
packages/core/core/src/Parcel.js
Outdated
@@ -321,6 +321,10 @@ export default class Parcel { | |||
}; | |||
} | |||
|
|||
// If this bundle was previously a placeholder, it now no longer is as it has | |||
// been requested. | |||
bundleNode.value.isPlaceholder = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this is the right place or way to do this - is it "safe" to mutate a bundleNode
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm kinda weird but probably ok since we only store the bundle graph in the cache when parcel exits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I just had another look and I have a feeling this might no longer be required with the this.safeToIncrementallyBundle = false;
fixes, as they'll cause the bundle graph to be recreated and the placeholder flag will be appropriately set.
My tests seem to pass without this line, I'll just validate it's the safeToIncrementallyBundle
change that's fixing the issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, I've removed this change as the other change (which I made later) in AssetGraph
fixes the issue this was fixing.
2c22a39
to
92ee5eb
Compare
2eb85ac
to
43d98d0
Compare
assert(await distDirIncludes(['index.js', /^lazy-1\./, /^lazy-2\./])); | ||
}); | ||
|
||
it('should lazy compile properly when same module is used sync/async', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test still fails on this branch, it has been pulled in as an intentional broken test (hence the draft PR).
The "fix" is to remove the conditions for shouldBuildLazily
in JSRuntime
(e.g.:
parcel/packages/runtimes/js/src/JSRuntime.js
Lines 360 to 369 in 7ff54c7
// Also do this when building lazily or the runtime itself could get deduplicated and only | |
// exist in the parent. This causes errors if an old version of the parent without the runtime | |
// is already loaded. | |
if ( | |
bundle.env.outputFormat === 'commonjs' || | |
bundle.env.isLibrary || | |
options.shouldBuildLazily | |
) { | |
externalBundles = [mainBundle]; | |
} else { |
With the code as it is, the whole bundle group doesn't get loaded - so when the uses-static-component-async
bundle loads, it doesn't trigger a load of the static-component
bundle, so it can't resolve the module.
I know that the"fix" (seen here: marcins@a36a37d) means that there is a potential issue when a bundle group grows after lazy compilation - this means Parcel can get into a state where it requires a browser refresh in order to recover. However, with the current state, a refresh won't heal as the load order is just incorrect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed in the Core meeting, the "fix" for this has now been cherry-picked onto this branch. I've updated the comments to leave behind some trace that there was lazy build specific code previously there.
b58f23e
to
a031a0f
Compare
Hey @marcins I tried out this patch but I'm still seeing some more issues with lazy mode. Here's another minimal repro that's exhibiting similar issues to what this PR was meant to fix. Maybe it'll be helpful to shake out more bugs! I can also file this as a separate issue if that's helpful. I'm still trying to get comfortable with parcel internals to propose fixes but I'm not quite there yet. Thank you for all your hard work on |
@jondlm did you build Parcel locally? This hasn't even been released in a nightly yet. |
Thanks for that repro @jondlm - I haven't tried it, but looking at the description in the README that a refresh fixes it, I have a feeling you might've run into the issue which the conditions I removed in As I couldn't find a reliable way to minimally repro this, we decided to merge the fixes for now as they definitely make things better than before, albeit requiring an occasional refresh to unstick things. Having a repro that fails with these fixes in place will definitely be handy in understanding the issue and working on a proper fix. But just to confirm as Devon asked - you still see this issue by running a locally built Parcel with this patch applied? If that's the case, then yes please - do file a separate issue. |
@devongovett I pulled commit 824ddbe, compiled the JS runtime, copied it into my project's node_modules, and then ran Parcel via bin.js. I think that should pull in all the relevant changes from this PR. Thanks for the context @marcins. I'll file a separate issue with the case I found 👍 |
You'll also need the changes in In any case, the latest |
👋 I created a fork of your original lazy-testbed repo with the steps to reproduce the additional issue that @jondlm and I are bumping into which he mentioned above. We've spent some time trying to figure out how to fix it but haven't really been able to understand the expected behavior and usage of deferred modules properly. It seems like it's very close to working but there's just like one connecting piece that should be tying lazy async bundles to the relevant shared bundles that is maybe missing. |
↪️ Pull Request
This fixes the reproduction provided in #8816 (Thanks @rayinaway), as well as a separate reproduction I created at https://github.com/marcins/lazy-testbed.
There were a couple of issues I found when trying to create a basic lazy compilation example:
A new integration test based on my testbed reproduction has been added that I first verified was failing on current
v2
branch, and verified that it now passes with these changes. In addition I tested the reproduction from #8816 and verified that Parcel with these fixes now loads those bundles correctly.Note that due to my lack of deep knowledge in the areas touched the testing is possibly not exhaustive, I possibly haven't tested some scenarios that may still fail with these changes. I did manually test adding / removing dependencies and confirming that things re-compiled correctly.
Given the scope of the changes, they shouldn't affect anything outside of
--lazy
mode, so at least they're unlikely to break other functionality.🚨 Test instructions
See repro repos above - these fail with current v2, but succeed when using Parcel linked with these changes.
✔️ PR Todo