Skip to content

UI: Preload base React plugin bundles with the page - #74777

Merged
bbovenzi merged 3 commits into
apache:mainfrom
jlaneve:react-plugin-preload
Oct 21, 2026
Merged

bbovenzi merged 3 commits into
apache:mainfrom
jlaneve:react-plugin-preload

Conversation

@jlaneve

@jlaneve jlaneve commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

A React plugin with destination: "base" renders on every page, but the UI learns its bundle URL only from GET /api/v2/plugins, after the UI's own scripts have run. On a Fast 3G profile the browser starts the bundle download 11.3 s into the page load, so the plugin shows up late and the page moves down. The server now adds a modulepreload link to index.html for each base app's bundle, and the browser starts the download 0.2 s into the load. The UI's later import() of the same URL takes the preloaded module, so the bundle still downloads once.

Only plugins without a team get a link. The server renders the page before it knows the user, so it can't apply the team filter that GET /api/v2/plugins applies. For the same reason, a user who can't view plugins still downloads a global base plugin's bundle, which the UI never imports.

I checked this on Airflow 3.3.1 in Chromium, Firefox and WebKit, with one base plugin and a base path. Every page load downloaded the bundle once, including a bundle on another origin. On Fast 3G the plugin appeared 0.8 s after the page instead of 1.3 s. On Fast 4G it made no difference.

Call-stack diff

  GET /{rest_of_path}                       core_api/app.py
  └─ webapp()
     └─ TemplateResponse("/index.html")
        ├─ backend_server_base_url          # unchanged
+       └─ preload_bundle_urls              # computed once in init_views
+          └─ base_react_app_bundle_urls()
+             └─ get_plugin_info(["react_apps"])  # base apps, no team

  index.html
     <base href>                            # unchanged
+    <link rel="modulepreload" href>        # one per base bundle

Unchanged: ReactPlugin still loads the bundle with import() and resolves the URL against document.baseURI. The <link> follows <base>, so both resolve to the same URL.

Related: #74762


Was generative AI tooling used to co-author this PR?
  • Yes (please specify the tool below)

Generated-by: Claude Code (Claude Opus 5.5) following the guidelines


  • Read the Pull Request Guidelines for more information. Note: commit author/co-author name and email in commits become permanently public when merged.
  • For fundamental code changes, an Airflow Improvement Proposal (AIP) is needed.
  • When adding dependency, check compliance with the ASF 3rd Party License Policy.
  • For significant user-facing changes create newsfragment: {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.

A React plugin with destination "base" renders on every page, but the
UI only learns its bundle URL from the plugins endpoint after its own
scripts have run. The bundle download starts late, and the page moves
down when the plugin appears.

The server now adds a modulepreload link for each base app's bundle to
index.html, so the browser fetches it alongside the UI's scripts. The
UI's later import() of the same URL reuses the preloaded module. Only
plugins without a team are included, because the page is rendered
before the user is known.
@boring-cyborg boring-cyborg Bot added area:API Airflow's REST/HTTP API area:plugins area:UI Related to UI/UX. For Frontend Developers. kind:documentation labels Oct 15, 2026
@bbovenzi bbovenzi added the backport-to-v3-4-test Backport to v3-4-test label Oct 21, 2026
@bbovenzi bbovenzi added this to the Airflow 3.4.0 milestone Oct 21, 2026
@bbovenzi
bbovenzi merged commit 165f5ad into apache:main Oct 21, 2026
99 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-4-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

Status Branch Result
✅ v3-4-test PR Link

github-actions Bot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Oct 21, 2026
…he#74777)

* UI: Preload base React plugin bundles with the page

A React plugin with destination "base" renders on every page, but the
UI only learns its bundle URL from the plugins endpoint after its own
scripts have run. The bundle download starts late, and the page moves
down when the plugin appears.

The server now adds a modulepreload link for each base app's bundle to
index.html, so the browser fetches it alongside the UI's scripts. The
UI's later import() of the same URL reuses the preloaded module. Only
plugins without a team are included, because the page is rendered
before the user is known.

* Cover the empty and escaped cases of the preload links
(cherry picked from commit 165f5ad)

Co-authored-by: Julian LaNeve <lanevejulian@gmail.com>
aws-airflow-bot pushed a commit to aws-mwaa/upstream-to-airflow that referenced this pull request Oct 21, 2026
…he#74777)

* UI: Preload base React plugin bundles with the page

A React plugin with destination "base" renders on every page, but the
UI only learns its bundle URL from the plugins endpoint after its own
scripts have run. The bundle download starts late, and the page moves
down when the plugin appears.

The server now adds a modulepreload link for each base app's bundle to
index.html, so the browser fetches it alongside the UI's scripts. The
UI's later import() of the same URL reuses the preloaded module. Only
plugins without a team are included, because the page is rendered
before the user is known.

* Cover the empty and escaped cases of the preload links
(cherry picked from commit 165f5ad)

Co-authored-by: Julian LaNeve <lanevejulian@gmail.com>
bbovenzi pushed a commit that referenced this pull request Oct 21, 2026
…) (#75259)

* UI: Preload base React plugin bundles with the page

A React plugin with destination "base" renders on every page, but the
UI only learns its bundle URL from the plugins endpoint after its own
scripts have run. The bundle download starts late, and the page moves
down when the plugin appears.

The server now adds a modulepreload link for each base app's bundle to
index.html, so the browser fetches it alongside the UI's scripts. The
UI's later import() of the same URL reuses the preloaded module. Only
plugins without a team are included, because the page is rendered
before the user is known.

* Cover the empty and escaped cases of the preload links
(cherry picked from commit 165f5ad)

Co-authored-by: Julian LaNeve <lanevejulian@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:API Airflow's REST/HTTP API area:plugins area:UI Related to UI/UX. For Frontend Developers. backport-to-v3-4-test Backport to v3-4-test kind:documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants