-
Couldn't load subscription status.
- Fork 221
Adding incremental Frontend Server-compatible DDC builders + supporting infrastructure #4240
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
base: master
Are you sure you want to change the base?
Conversation
…r fine modules for hot reload
PR HealthChangelog Entry ✔️
Changes to files need to be accounted for in their respective changelogs. This check can be disabled by tagging the PR with |
Can you say more about the affect this has on the structure of compilations? Are we doing more work by turning off SCCs? My assumption was that SCCs allowed us to limit the scope of an invalidation. |
|
@davidmorgan Thanks! It's a huge change, so please take your time. I wasn't able to configure it in a prettier way since I'm flying out for two weeks. I'm highly unopinionated wrt testing, but it was definitely a struggle to get @biggs0125 The SCCs here operate on a the import-graph level. DDC's old module system requires that cyclic dependencies be 'unified' into a single module. Both the Frontend Server and build_runner doing this non-deterministically might cause With SCCs enabled, Re: failures. I think some tests are failing due to API changes without pinning new versions? I'll add those (maybe in a separate PR) if the current approach looks sound. |
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 generally looks good, a few comments re: scratch_space.
Re: testing :)
You sort of don't need to pass assetGraph, it's serialized to the readerWriter and the next build will read it if it's there.
But, the next build will discard the asset graph if any builders changed, so you have to pass the exact same builders each time, which means you will get a full build the first time you call it anyway.
You commented with build.yaml ordering is not respected, and that's true. Adding workarounds for that is not too pretty, it's getting very close to a real build but now with quite a lot of configuration that doesn't exactly match a real build.
Would you be up for trying a different way of testing that is a real build?
I added tests recently that make it easy to set up some packages, run build_runner for real and check the output. Since you want persistent processes, watch mode would make sense, so something like:
| // Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file |
There is an example web build using the same test infra here
The test infra is currently internal to build_runner, mainly build_runner/test/common/build_runner_tester.dart, if it looks useful let's just hack around that for now and I'll work out how best to clean it up, I guess adding to build_test is one option.
Package publishing
Documentation at https://github.com/dart-lang/ecosystem/wiki/Publishing-automation. |
|
@davidmorgan Wow, the tests in Thanks for the review - back from vacation! |
|
It looks like you made some changes in response to my comments but I don't see any responses to the comments so I'm not sure if you're done--please let me know if/when I should take another look. Thanks! |
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.
Welcome back!
Looking good so far.
There are some CI failures, could you take a look at those please?
| /// defaults to [BuildLog.failurePattern] so that `expect` will stop if the | ||
| /// process reports a build failure. | ||
| /// | ||
| /// if [expectFailure] is set, then both [pattern] and [failOn] must be |
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.
Hmmmm multiple expectations is a bit awkward, I wonder if there's a nicer way.
Would it work to accumulate lines and return them, then the second expectation can be checked on the result?
Looking at how this method is used, I think maybe something like this:
- most callers are not using the result, so how about the base method is
Future<void> expect. - a few callers are using the single matching line, so how about
Future<String> expectAndGetLinefor that - and then I think you can do what you want with the full accumulated output until the match, how about
Future<List<String>> expectAndGetBlock
?
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.
I like that change, but I the newly added tests' reqs are:
- we should be able to expect that a test throws
- we should be able to match on more complex patterns (more than one line of match)
The problem with returning a block is that expect waits on a stream until it times out for 30s or encounters pattern, so we don't have a good way to determine when a block is finished accumulating. Really it should just accept a List<Matcher> and return if all matchers are successful. Thoughts?
Whoops, looks like I had unpublished comments that you addressed by coincidence. Sorry about that! Now published. |
@davidmorgan Oh no - you didn't see my comments? I can ping you when things are fully ready, but I've been in and out since I'm sick with something mysterious lol @nshahan Thanks for reviewing! I updated some of the formatting based on your feedback. It looks like I've encountered a windows pathing issue in some SDK lib. I'll investigate tomorrow :( |
Glues FES into build_runner, which is our first step towards hot reload + build_runner.
The high level workflow is:
build_runner(hot-reload ready).Major changes:
DdcFrontendServerBuilderto our set of DDC builders (enabled via theweb-hot-reloadconfig). This builder keeps aPersistentFrontendServerinstance alive across rebuilds. Compile/recompile requests are queued via aFrontendServerProxyDriverresource.scratch_spaceto record both 1) the main app entrypoint and 2) updated local files from theentrypoint_markerbuilder and themodule_builderbuilder respectively. These are side effects that break certain stateful 'guarantees' of standard build_runner execution. Theentrypoint_markerbuilder runs before any of the downstream DDC builders and finds the web entrypoint, as Frontend Server must receive the same entrypoint on every compilation request.build_runnerbe disabled.Test changes:
build_testto permit incremental builds. This involves passing the asset graph + asset reader/writer across build results and only performing cleanup operations after a series of rebuilds.build_testdoesn't supportruns_beforeand other ordering rules inbuild.yaml, so the above changes allows a kind of imperative ordering, which is important for testingentrypoint_marker.Minor changes:
scratch_spaceso that rebuilds only retain modified files.scratch_spacepackage_config.jsonspecs (packageUriandrootUri). The previous values didn't seem to make sense to me, but I'm also not familiar with how that's standardized inscratch_space.fileanduuiddeps tobuild_modules.Currently doesn't support live-reloading (functionality appears to have been broken a while ago). This'll be added in an upcoming change and permit
webdev-like auto-hot-reload on save (on top of manual).Enable this by adding the following to a project's
build.yaml: