модуль 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 в вашем макете, и вы хотите использовать потоковую передачу, вам придётся рендерить весь шаблон (и, возможно, выполнить все запросы) перед отправкой заголовка и всех ресурсов, что убивает смысл потоковой передачи. По этой причине Rails 3.1 вводит новый помощник под названием 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.