diff --git a/core/modules/toolbar/js/toolbar.anti-flicker.js b/core/modules/toolbar/js/toolbar.anti-flicker.js
new file mode 100644
index 0000000000000000000000000000000000000000..43946ba8dc647e470811c7ce98dc2109654734f1
--- /dev/null
+++ b/core/modules/toolbar/js/toolbar.anti-flicker.js
@@ -0,0 +1,72 @@
+/**
+ * @file
+ * Prevents flicker of the toolbar on page load.
+ */
+
+(() => {
+  const toolbarState = sessionStorage.getItem('Drupal.toolbar.toolbarState')
+    ? JSON.parse(sessionStorage.getItem('Drupal.toolbar.toolbarState'))
+    : false;
+  // These are classes that toolbar typically adds to <body>, but this code
+  // executes before the first paint, when <body> is not yet present. The
+  // classes are added to <html> so styling immediately reflects the current
+  // toolbar state. The classes are removed after the toolbar completes
+  // initialization.
+  const classesToAdd = ['toolbar-loading', 'toolbar-anti-flicker'];
+  if (toolbarState) {
+    const {
+      orientation,
+      hasActiveTab,
+      isFixed,
+      activeTray,
+      activeTabId,
+      isOriented,
+      userButtonMinWidth,
+    } = toolbarState;
+
+    classesToAdd.push(
+      orientation ? `toolbar-${orientation}` : 'toolbar-horizontal',
+    );
+    if (hasActiveTab !== false) {
+      classesToAdd.push('toolbar-tray-open');
+    }
+    if (isFixed) {
+      classesToAdd.push('toolbar-fixed');
+    }
+    if (isOriented) {
+      classesToAdd.push('toolbar-oriented');
+    }
+
+    if (activeTray) {
+      // These styles are added so the active tab/tray styles are present
+      // immediately instead of "flickering" on as the toolbar initializes. In
+      // instances where a tray is lazy loaded, these styles facilitate the
+      // lazy loaded tray appearing gracefully and without reflow.
+      const styleContent = `
+      .toolbar-loading #${activeTabId} {
+        background-image: linear-gradient(rgba(255, 255, 255, 0.25) 20%, transparent 200%);
+      }
+      .toolbar-loading #${activeTabId}-tray {
+        display: block; box-shadow: -1px 0 5px 2px rgb(0 0 0 / 33%);
+        border-right: 1px solid #aaa; background-color: #f5f5f5;
+        z-index: 0;
+      }
+      .toolbar-loading.toolbar-vertical.toolbar-tray-open #${activeTabId}-tray {
+        width: 15rem; height: 100vh;
+      }
+     .toolbar-loading.toolbar-horizontal :not(#${activeTray}) > .toolbar-lining {opacity: 0}`;
+
+      const style = document.createElement('style');
+      style.textContent = styleContent;
+      style.setAttribute('data-toolbar-anti-flicker-loading', true);
+      document.querySelector('head').appendChild(style);
+      if (userButtonMinWidth) {
+        const userButtonStyle = document.createElement('style');
+        userButtonStyle.textContent = `
+        #toolbar-item-user {min-width: ${userButtonMinWidth}.px;}`;
+        document.querySelector('head').appendChild(userButtonStyle);
+      }
+    }
+  }
+  document.querySelector('html').classList.add(...classesToAdd);
+})();
diff --git a/core/modules/toolbar/toolbar.libraries.yml b/core/modules/toolbar/toolbar.libraries.yml
index 061bd7a98b4d527f4bdcedb2a4cf359b3656d34c..af520b8f89a972d3402259a97499015a18946c35 100644
--- a/core/modules/toolbar/toolbar.libraries.yml
+++ b/core/modules/toolbar/toolbar.libraries.yml
@@ -28,6 +28,7 @@ toolbar:
     - core/once
     - core/drupal.displace
     - toolbar/toolbar.menu
+    - toolbar/toolbar.anti-flicker
 
 toolbar.menu:
   version: VERSION
@@ -50,3 +51,9 @@ toolbar.escapeAdmin:
     - core/drupal
     - core/drupalSettings
     - core/once
+toolbar.anti-flicker:
+  # Block the page from being loaded until anti-flicker is initialized.
+  version: VERSION
+  header: true
+  js:
+    js/toolbar.anti-flicker.js: {}
diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module
index e5ebb050393b219fc23adf4ca8bb3b3c323d7217..feeb1d4b2aa7df49ce9c390cbaeee2a8987b7bed 100644
--- a/core/modules/toolbar/toolbar.module
+++ b/core/modules/toolbar/toolbar.module
@@ -7,7 +7,6 @@
 
 use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Render\Element;
-use Drupal\Core\Render\Markup;
 use Drupal\Core\Render\RenderContext;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Template\Attribute;
@@ -49,101 +48,6 @@ function toolbar_theme($existing, $type, $theme, $path) {
   return $items;
 }
 
-/**
- * Implements hook_page_attachments().
- */
-function toolbar_page_attachments(array &$page) {
-  // This JavaScript code provides temporary styles while the toolbar loads, so
-  // it better visually resembles the appearance it will have once fully loaded.
-  // @todo investigate potential alternatives to this approach in
-  //   https://www.drupal.org/i/3355381
-  $anti_flicker_js = <<<JS
-(function() {
-  const toolbarState = sessionStorage.getItem('Drupal.toolbar.toolbarState')
-    ? JSON.parse(sessionStorage.getItem('Drupal.toolbar.toolbarState'))
-    : false;
-  // These are classes that toolbar typically adds to <body>, but this code
-  // executes before the first paint, when <body> is not yet present. The
-  // classes are added to <html> so styling immediately reflects the current
-  // toolbar state. The classes are removed after the toolbar completes
-  // initialization.
-  const classesToAdd = ['toolbar-loading', 'toolbar-anti-flicker'];
-  if (toolbarState) {
-    const {
-      orientation,
-      hasActiveTab,
-      isFixed,
-      activeTray,
-      activeTabId,
-      isOriented,
-      userButtonMinWidth
-    } = toolbarState;
-
-    classesToAdd.push(
-      orientation ? `toolbar-` + orientation + `` : 'toolbar-horizontal',
-    );
-    if (hasActiveTab !== false) {
-      classesToAdd.push('toolbar-tray-open');
-    }
-    if (isFixed) {
-      classesToAdd.push('toolbar-fixed');
-    }
-    if (isOriented) {
-      classesToAdd.push('toolbar-oriented');
-    }
-
-    if (activeTray) {
-      // These styles are added so the active tab/tray styles are present
-      // immediately instead of "flickering" on as the toolbar initializes. In
-      // instances where a tray is lazy loaded, these styles facilitate the
-      // lazy loaded tray appearing gracefully and without reflow.
-      const styleContent = `
-      .toolbar-loading #` + activeTabId + ` {
-        background-image: linear-gradient(rgba(255, 255, 255, 0.25) 20%, transparent 200%);
-      }
-      .toolbar-loading #` + activeTabId + `-tray {
-        display: block; box-shadow: -1px 0 5px 2px rgb(0 0 0 / 33%);
-        border-right: 1px solid #aaa; background-color: #f5f5f5;
-        z-index: 0;
-      }
-      .toolbar-loading.toolbar-vertical.toolbar-tray-open #` + activeTabId + `-tray {
-        width: 15rem; height: 100vh;
-      }
-     .toolbar-loading.toolbar-horizontal :not(#` + activeTray + `) > .toolbar-lining {opacity: 0}`;
-
-      const style = document.createElement('style');
-      style.textContent = styleContent;
-      style.setAttribute('data-toolbar-anti-flicker-loading', true);
-      document.querySelector('head').appendChild(style);
-
-      if (userButtonMinWidth) {
-        const userButtonStyle = document.createElement('style');
-        userButtonStyle.textContent = `#toolbar-item-user {min-width: ` + userButtonMinWidth +`px;}`
-        document.querySelector('head').appendChild(userButtonStyle);
-      }
-    }
-  }
-  document.querySelector('html').classList.add(...classesToAdd);
-})();
-JS;
-
-  // The anti flicker javascript is added as an inline tag so it is executed
-  // as early as possible. This enables it to add classes that prevent
-  // flickering before the first paint.
-  $page['#attached']['html_head'][] = [
-    [
-      '#tag' => 'script',
-      '#attributes' => [
-        'type' => 'text/javascript',
-        'data-toolbar-anti-flicker-loading' => TRUE,
-      ],
-      // Process through Markup to prevent character escaping.
-      '#value' => Markup::create($anti_flicker_js),
-    ],
-    'anti_flicker_js',
-  ];
-}
-
 /**
  * Implements hook_page_top().
  *
diff --git a/core/profiles/demo_umami/tests/src/FunctionalJavascript/PerformanceTest.php b/core/profiles/demo_umami/tests/src/FunctionalJavascript/PerformanceTest.php
index baecf5b8387e9ca066e95c288ea43f3c7542788a..9af5caf95ad68bc8d690ea5f42aa9d2ebc761c32 100644
--- a/core/profiles/demo_umami/tests/src/FunctionalJavascript/PerformanceTest.php
+++ b/core/profiles/demo_umami/tests/src/FunctionalJavascript/PerformanceTest.php
@@ -35,7 +35,7 @@ public function testFrontPagePerformance(): void {
     $this->drupalGet('<front>');
     $this->assertSession()->pageTextContains('Umami');
     $this->assertSame(2, $this->stylesheetCount);
-    $this->assertSame(1, $this->scriptCount);
+    $this->assertSame(2, $this->scriptCount);
   }
 
 }