Spec-Zone.ru › Ruby on Rails 5.0

модуль ActionController::Streaming

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

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

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

Этот подход был представлен в Rails 3.1 и все еще улучшается. Некоторые Rack-мидлвары могут не работать, и нужно быть осторожным при использовании потоковой передачи. Эти моменты будут устранены в скором времени.

Для использования потоковой передачи вам потребуется версия Ruby, поддерживающая волокна (волокна поддерживаются начиная с версии 1.9.2 основного реализация Ruby).

Потоковая передача может быть легко добавлена к шаблону, для этого достаточно передать опцию :stream.

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

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

Потоковая передача может быть избыточной для простых действий, таких как 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 работает только с шаблонами. Рендеринг :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.

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

При потоковой передаче 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. Пожалуйста, ознакомьтесь с документацией для получения дополнительной информации: unicorn.bogomips.org/Unicorn/Configurator.html#method-i-listen

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

Passenger

Описание в разработке.

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

Spec-Zone.ru

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