Spec-Zone.ru › Ruby on Rails 5.2

модуль ActionController::Streaming

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

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

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

Этот подход был представлен в 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. Проверьте документацию для получения дополнительной информации: bogomips.org/unicorn/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