модуль ActionController::Streaming
Контроллер действий Streaming
Разрешает передавать представления клиенту по частям по мере их рендеринга.
По умолчанию, Rails рендерит представления, сначала рендеринга шаблона, а затем макета. Ответ отправляется клиенту после рендеринга всего шаблона, выполнения всех запросов и обработки макета.
Streaming изменяет порядок рендеринга, сначала рендеринга макета, а затем каждой части макета по мере её обработки. Это позволяет быстро передать заголовок HTML (который обычно находится в макете) клиенту, что позволяет загрузить JavaScript и CSS раньше, чем обычно.
Некоторые промежуточные программы 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>
Первые два символа (">) необходимы в случае, если исключение происходит во время рендеринга атрибутов для данного тега. Вы можете проверить истинную причину исключения в своём логере.
Поддержка веб-серверов
Все серверы, совместимые с Rack 3+, поддерживают потоковую передачу.
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.