Spec-Zone.ru › Ruby on Rails 7.2

модуль ActionController::Streaming

Контроллер Action Streaming

Позволяет передавать представления клиенту по частям, по мере их отрисовки.

По умолчанию, Rails отрисовывает представления, сначала отрисовав шаблон, а затем макет. Ответ отправляется клиенту после полной отрисовки шаблона, выполнения всех запросов и обработки макета.

Streaming изменяет порядок отрисовки, сначала отрисовывая макет, а затем каждую его часть по мере обработки. Это позволяет быстро передать заголовок HTML (обычно находящийся в макете) клиенту, что обеспечивает более раннюю загрузку JavaScript и стилей.

Некоторые промежуточные программные компоненты Rack могут не работать корректно при использовании потоковой передачи, поэтому необходимо быть внимательным. Подробнее об этом см. раздел Промежуточные программные компоненты в Streaming.

Streaming можно легко добавить к заданному шаблону, достаточно передать опцию :stream в render.

class PostsController
  def index
    @posts = Post.all
    render stream: true
  end
end

Когда использовать потоковую передачу

Streaming может быть излишним для простых действий, таких как new или edit. По-настоящему потоковая передача полезна для ресурсоёмких действий, например, при выполнении большого количества запросов к базе данных.

В таких действиях желательно отложить выполнение запросов как можно дальше. Например, рассмотрим следующее действие dashboard:

def dashboard
  @posts = Post.all
  @pages = Page.all
  @articles = Article.all
end

Большинство запросов здесь выполняются в контроллере. Для использования потоковой передачи его следует переписать следующим образом:

def dashboard
  # Allow lazy execution of the queries
  @posts = Post.all
  @pages = Page.all
  @articles = Article.all
  render stream: true
end

Обратите внимание, что :stream работает только с шаблонами. Rendering :json или :xml с :stream не будут работать.

Взаимодействие между макетом и шаблоном

При потоковой передаче отрисовка происходит сверху вниз, а не изнутри наружу. Rails начинается с макета, а шаблон отрисовывается позже, когда достигается его yield.

Это означает, что если ваше приложение в настоящее время полагается на переменные экземпляра, установленные в шаблоне, для использования в макете, они не будут работать при использовании потоковой передачи. Правильный способ взаимодействия между макетом и шаблоном, независимо от того, используется ли потоковая передача или нет, — это использование content_for, provide, и yield.

Рассмотрим простой пример, где макет ожидает, что шаблон укажет, какой заголовок использовать:

<html>
  <head><title><%= yield :title %></title></head>
  <body><%= yield %></body>
</html>

Вы будете использовать content_for в шаблоне, чтобы указать заголовок:

<%= content_for :title, "Main" %>
Hello

И конечным результатом будет:

<html>
  <head><title>Main</title></head>
  <body>Hello</body>
</html>

Однако, если content_for вызывается несколько раз, конечный результат будет содержать все вызовы, объединённые вместе. Например, если у нас есть следующий шаблон:

<%= content_for :title, "Main" %>
Hello
<%= content_for :title, " page" %>

Конечный результат будет:

<html>
  <head><title>Main page</title></head>
  <body>Hello</body>
</html>

Это означает, что если в вашем макете есть yield :title, и вы хотите использовать потоковую передачу, вам придётся отрисовать весь шаблон (и, в конечном итоге, выполнить все запросы) перед передачей заголовка и всех ресурсов, что противоречит цели потоковой передачи. В качестве альтернативы, вы можете использовать помощник provide, который делает то же самое, что и content_for, но сообщает макету прекратить поиск других элементов и продолжить отрисовку.

Например, шаблон выше, использующий provide, будет:

<%= provide :title, "Main" %>
Hello
<%= content_for :title, " page" %>

Что приведёт к:

<html>
  <head><title>Main</title></head>
  <body>Hello</body>
</html>

Таким образом, при использовании потоковой передачи необходимо правильно проверить свои шаблоны и выбрать, когда использовать provide и content_for.

Для получения дополнительной информации см. ActionView::Helpers::CaptureHelper.

Заголовки, куки, сессия и всплывающие сообщения

При потоковой передаче HTTP-заголовки отправляются клиенту непосредственно перед отправкой первой строки. Это означает, что изменение заголовков, куков, сессии или всплывающих сообщений после начала отрисовки шаблона не повлияет на клиента.

Промежуточные программные компоненты

Промежуточные программные компоненты, которым необходимо манипулировать телом, не будут работать с потоковой передачей. При использовании потоковой передачи в разработке или производстве эти промежуточные программные компоненты следует отключать. Например, Rack::Bug не будет работать при потоковой передаче, так как ему необходимо вставлять содержимое в тело HTML.

Также Rack::Cache не будет работать с потоковой передачей, так как пока не поддерживает потоковые тела. При потоковой передаче Cache-Control автоматически устанавливается в «no-cache».

Ошибки

В контексте потоковой передачи обработка исключений усложняется. Это происходит потому, что часть шаблона уже была отрисована и отправлена клиенту, что делает невозможным отрисовку всей страницы с ошибкой.

В настоящее время, при возникновении исключения в режиме разработки или производства, Rails автоматически отправит клиенту:

"><script>window.location = "/500.html"</script></html>

Первые два символа (">) необходимы на случай, если исключение произойдёт во время отрисовки атрибутов для данного тега. Вы можете проверить фактическую причину ошибки в своём журнале регистрации.

Поддержка веб-серверов

Не все веб-серверы поддерживают потоковую передачу по умолчанию. Необходимо ознакомиться с инструкциями для каждого из них.

Unicorn

Unicorn поддерживает потоковую передачу, но требует конфигурации. Для этого необходимо создать файл конфигурации следующим образом:

# unicorn.config.rb
listen 3000, tcp_nopush: false

И использовать его при инициализации:

unicorn_rails --config-file unicorn.config.rb

Также вы можете настроить другие параметры, такие как :tcp_nodelay.

Дополнительную информацию можно найти в [документации](bogomips.org/unicorn/Unicorn/Configurator.html#method- i-listen).

Если вы используете Unicorn с NGINX, вам может потребоваться настроить NGINX. Streaming должен работать без проблем с Rainbows.

Passenger

Phusion Passenger с NGINX предлагает два механизма потоковой передачи из коробки.

  1. Механизм кэширования ответов NGINX, который зависит от значения опции passenger_buffer_response (по умолчанию «выключено»).

  2. Система кэширования Passenger, которая всегда включена независимо от значения passenger_buffer_response.

Когда passenger_buffer_response включено, потоковая передача выполняется на уровне NGINX, который ожидает завершения работы приложения перед отправкой ответа клиенту.

Для получения дополнительной информации см. [документацию] (www.phusionpassenger.com/docs/references/config_reference/nginx/#passenger_buffer_response).

© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API