Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Turbo Stream - unconventional usage

Krzysztof
December 21, 2023

Turbo Stream - unconventional usage

This presentation is from march-may 2022 so from earlier days of Turbo, and focuses on Turbo Stream and a rather non-standard usage of it. It touches briefly on the basics of it, but it interested more in showing a more advanced usage.
Comes with a demo app https://github.com/krzykamil/turbo_prez

Krzysztof

December 21, 2023
Tweet

More Decks by Krzysztof

Other Decks in Programming

Transcript

  1. Agenda 1. Turbo/! ◦ Turbo Stream basics 2. Demo app

    ◦ Step by step analysis 3. Summary 4. Resources - QA
  2. Basics - TLDR; Turbo, Hotwire: • Turbo is part of

    Hotwire • Hotwire minimizes the need for Javascript (huray!), by delivering HTML "over the wire" • Hotwire is used more and more in RoR environment • Focus is to render templates on the server side, deliver them to the client without rendering the whole page, but only the needed part of it • No need to refresh the whole page to see the changes from client actions on the page (form submissions, path changes (SPA-like)) • TurboStream "delivers page changes over WebSocket, Server-Sent Events or in response to form submissions"
  3. Basics - stream in html template This is how it

    looks in pure HTML (ofc. rails gives helpers to generate that, coming up in the next slide)
  4. Basics When broadcast is sent, something like this appear in

    the DOM for a brief moment Turbo internal JS kicks in, changes the HTML. You do not have to do anything else on the FE
  5. This makes for some pretty impressive stuff • Real time

    updates to pages - no reloads • Faster development of common and uncommon FE tasks and problems • No Javascript • Reactive elements with no javascript • Server-side handling of frontend problems • No JS • Can be used outside Rails (although, in this case has to be used through DSL in Typescript) • Other than that, using Turbo minimizes or obliterates your need for Javascript
  6. But all of this you can learn from the documentation.

    For now the documentation is sparse and covers just the basics. If you want a more advanced turbo usage, you are left with just the source code and turbo-rails gem for help We do not want to always have to deal with partials and put everything in the controller or add even more stuff to already big rails models There are multiple operations in most systems, that affect the data of the application, that in turn affects the view. Why not simplify and speed up the process of clicking through and refreshing pages? Basically lets introduce side effects of backend actions to the view more directly, without coupling
  7. Few words about resources The gem for turbo on rails

    is good (IMHO), and the source code good is clean and has a lot of comments that are helpful for us to use TurboStream in a more interesting way There is still little resources so far around Turbo, and most of them are repetitive, show you the same thing that the documentation does
  8. Demo app stack • Sidekiq • Trailblazer Cells (you could

    replace that with githubs ViewComponents) • turbo-rails gem (just for the streams) • redis (used by ActionCable that in turn is used by TurboStream) • Blog (original I know) • Rails 6.0.2 • Ruby 3.0.2
  9. Our demo case: • User is displaying a index page

    of a blog • Author of the blog has created a structure of the page that has 1 post exposed, then two in a next line, and then 3 in the next line • Author of the blog wants the entire structure of what post is exposed or in what line to change from time to time, without the users reloading to see the change
  10. Videos presentation link • A big part of the page

    can be updated - the cell is a part of the entire view, it is not the entire view • The layout was not rendered again, just the cell html was redone • rake task that fires sidekiq and sidekiq itself had no knowledge of client session, yet the client view was altered • Pretty much everything happens on server side, no JS was written here by me
  11. The code - What we with the implementation 1. Minimize

    changes in html 2. Opt-in through cell 3. Decide how to render in cell 4. Only render if stream active
  12. Minimize changes in html Default turbo approach involves adding html

    (or rails helpers) to a lot of partials if you use turbo the default way. This often also leads to more code in controllers (some parts of turbo require special format handling). If you add turbo to an existing rails app, you will end up adding quite a lot of HTML and controller code (still better than a lot of JS). Using view components like cells help minimize that
  13. Opt-in through cell I wanted to use cells/githubs view components

    cause they are mose reusable and make the htmls smaller. Also it is hard to render a partial from a sidekiq worker. Also it makes it easy to search for all components that use turbo It is also nice to have a ruby object that determines what to do and when, with the broadcast signal received
  14. Decide how to render in cell From external places that

    can affect the view it would be nice to simply call always the same object with as simple parameters as possible and be done with it. Do not couple the view with the backend. I don't want the BE to know what cell its rendering since that would couple it to the view We want to use a general object to avoid coupling stuff like workers to cells
  15. Only render if stream is active I need BE to

    know that someone will receive a broadcast, to not render html without a need Do not waste resources, specially given ActionCable problems with being up to date Since backend is decoupled from the user sessions and you can't access ActionCable easily from anywhere I wanted to avoid simply always broadcasting in hopes someone is listening.
  16. Some other usages this could give us: • Could be

    integrated with event sourcing (the original usage I worked with) • Could work across microservices • As well as gems (this implementation itself could be a gem) • As well as rails engines • In short - as long as you can access the redis instance and registry of cells using streams you can make it work
  17. Can be used to make BE business logic affect FE

    for live users immediately. This can be done from any place in the code not just the controller-model It's a tool with great potential, its fast and the source code of the ruby gem, that serves as a bridge to the actual Turbo is written well Turbo Stream Uses Action Cable but is missing some tools that would make it much easier to use, for example there is no easy way to detect current live session/clients. You need to dig into redis if you configure Action Cable to use it, you check that. Its a young tool with most of the materials on the web so far only repeating the documentation Basecamp provided, not being very innovative
  18. Closing notes So far the best, most comprehensive Hotwire (mostly

    focused on Turbo) tutorial I saw was this: https://www.hotrails.dev This presentation used a sample app, which code is public on: https://github.com/krzykamil/turbo_p rez