You are here

protected function BigPipe::sendPreBody in Drupal 8

Same name and namespace in other branches
  1. 9 core/modules/big_pipe/src/Render/BigPipe.php \Drupal\big_pipe\Render\BigPipe::sendPreBody()
  2. 10 core/modules/big_pipe/src/Render/BigPipe.php \Drupal\big_pipe\Render\BigPipe::sendPreBody()

Sends everything until just before </body>.

Parameters

string $pre_body: The HTML response's content until the closing </body> tag.

array $no_js_placeholders: The no-JS BigPipe placeholders.

\Drupal\Core\Asset\AttachedAssetsInterface $cumulative_assets: The cumulative assets sent so far; to be updated while rendering no-JS BigPipe placeholders.

1 call to BigPipe::sendPreBody()
BigPipe::sendContent in core/modules/big_pipe/src/Render/BigPipe.php
Sends an HTML response in chunks using the BigPipe technique.

File

core/modules/big_pipe/src/Render/BigPipe.php, line 322

Class

BigPipe
Service for sending an HTML response in chunks (to get faster page loads).

Namespace

Drupal\big_pipe\Render

Code

protected function sendPreBody($pre_body, array $no_js_placeholders, AttachedAssetsInterface $cumulative_assets) {

  // If there are no no-JS BigPipe placeholders, we can send the pre-</body>
  // part of the page immediately.
  if (empty($no_js_placeholders)) {
    $this
      ->sendChunk($pre_body);
    return;
  }

  // Extract the scripts_bottom markup: the no-JS BigPipe placeholders that we
  // will render may attach additional asset libraries, and if so, it will be
  // necessary to re-render scripts_bottom.
  list($pre_scripts_bottom, $scripts_bottom, $post_scripts_bottom) = explode('<drupal-big-pipe-scripts-bottom-marker>', $pre_body, 3);
  $cumulative_assets_initial = clone $cumulative_assets;
  $this
    ->sendNoJsPlaceholders($pre_scripts_bottom . $post_scripts_bottom, $no_js_placeholders, $cumulative_assets);

  // If additional asset libraries or drupalSettings were attached by any of
  // the placeholders, then we need to re-render scripts_bottom.
  if ($cumulative_assets_initial != $cumulative_assets) {

    // Create a new HtmlResponse. Ensure the CSS and (non-bottom) JS is sent
    // before the HTML they're associated with.
    // @see \Drupal\Core\Render\HtmlResponseSubscriber
    // @see template_preprocess_html()
    $js_bottom_placeholder = '<nojs-bigpipe-placeholder-scripts-bottom-placeholder token="' . Crypt::randomBytesBase64(55) . '">';
    $html_response = new HtmlResponse();
    $html_response
      ->setContent([
      '#markup' => BigPipeMarkup::create($js_bottom_placeholder),
      '#attached' => [
        'drupalSettings' => $cumulative_assets
          ->getSettings(),
        'library' => $cumulative_assets
          ->getAlreadyLoadedLibraries(),
        'html_response_attachment_placeholders' => [
          'scripts_bottom' => $js_bottom_placeholder,
        ],
      ],
    ]);
    $html_response
      ->getCacheableMetadata()
      ->setCacheMaxAge(0);

    // Push a fake request with the asset libraries loaded so far and dispatch
    // KernelEvents::RESPONSE event. This results in the attachments for the
    // HTML response being processed by HtmlResponseAttachmentsProcessor and
    // hence the HTML to load the bottom JavaScript can be rendered.
    $fake_request = $this->requestStack
      ->getMasterRequest()
      ->duplicate();
    $html_response = $this
      ->filterEmbeddedResponse($fake_request, $html_response);
    $scripts_bottom = $html_response
      ->getContent();
  }
  $this
    ->sendChunk($scripts_bottom);
}