Repository navigation
Conversation
On an initial load, these pages sent their first requests from their components, so the requests waited for the UI config (the root route loader) and the first render. The task log waited longer: it needs the task instance's try number, so it started after the task instance request that itself waited for the first render. React Router runs the loaders of all matched routes in parallel, so route loaders now start these requests while the app loads, with the generated prefetch helpers and the same query keys the pages use. The loaders do not wait for their requests and never fail, so they do not delay or break rendering.
safaehar
requested review from
bbovenzi,
choo121600,
guan404ming,
pierrejeambrun,
ryanahamilton,
shubhamraj-git and
vatsrahul1001
as code owners
November 12, 2026 12:41
…arams The breadcrumb on every run and task page requests the Dag details, but the Dag loader is on a sibling route, so that request still waited for the first render. The log prefetch was skipped for any query string, although only try_number, region_id and region_index change its keys, so filtered log links lost it.
Contributor
|
Let's wait until #76091 is merged. I feel like we'll need a refactor |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
On an initial load, the Dag, run and task pages send their first requests from their components. Those requests wait for the root route loader (the UI config) and the first render. With the JavaScript cached, the page's data requests start 330–460 ms into the load:
/ui/config(root route loader)Requests that need another response wait longer. The task log needs the task instance's try number, so it starts only after the task instance request, which itself waits for the first render.
React Router runs the loaders of all matched routes in parallel. This adds loaders that start those requests while the app loads:
dags/:dagId: the Dag, its details and its latest run.dags/:dagId/runs/:runIdand the task instance routes (mapped or not): the Dag, its details and the run. The Dag details are the breadcrumb's query, which every run and task page renders.The loaders use the generated
prefetchUse…/ensureUse…Datahelpers, so each query key is the one the page's own query builds, and the page renders from the cache. They don't wait for their requests and never fail, so they don't delay or break rendering. If a page's query ends up with another key, it just sends its own request, as it does today.What the loaders leave to the page:
try_number,region_idorregion_index, the only parameters that change the task instance or log keys. Historical tries and loop iterations keep their current behavior. Other parameters, such as the Logs tab'slog_levelandlog_sourcefilters, keep the prefetch.try_number0, no state,up_for_retry), for which the Logs tab sends no log request either.Measurements
I measured an equivalent change on an Airflow 3.3 deployment. It had the same loaders, plus a prefetch of the Grid's first page, which this PR doesn't include. The A/B compared the same UI sources built without and with the loaders, with the JavaScript cached, against a real API server. A and B loads alternated, 10–12 rounds per page. Medians in ms from navigation start, p25–p75 in brackets:
staleTime: 0and refetches on mount when the loader's request has already finished.An earlier version of this description showed larger run- and task-page gains (−221 ms and −460 ms). They came from a non-interleaved A/B, where the API server's latency drifted between the A and B halves. The table above replaces them.
Testing
routePrefetch.test.ts(13 tests), covering:try_numberor loop coordinates are skipped;pnpm test), along withpnpm build,oxfmt,oxlint,eslintandtsc. On the latest commit, one unrelated test,UserSettingsButton"counts the teams it does not list…", failed once in a full run with a socket hang-up; it passes when run alone.No visual change: the pages render the same content, earlier.
Was generative AI tooling used to co-author this PR?
Generated-by: Claude Code (Claude Opus 5.5) following the guidelines
{pr_number}.significant.rst, in airflow-core/newsfragments. You can add this file in a follow-up commit after the PR is created so you know the PR number.