Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

— Knock, knock — An async templates — Who’s there? - Alexander Khokhlov | Elixir Club 13

16 visualizaciones

Publicado el

Доповідь Олександра Хохлова, Founder Nots.io, на Elixir Club 13, Dnipro, 13.04.2019
Наступна конференція - http://www.elixirkyiv.club/



Elixir and Erlang platform are all about asynchronous communications. Why don’t we use this feature while rendering templates? In this talk, Alexander unveils how we in Nots.io split HTML documents into smaller pieces and render them in parallel.


Cлідкуйте за нами у соцмережах @ElixirClubUA та #ElixirClubUA
Анонси та матеріали конференцій - https://www.fb.me/ElixirClubUA
Новини - https://twitter.com/ElixirClubUA
Фото та невимушена атмосфера - https://www.instagram.com/ElixirClubUA
*Канал організаторів мітапа - https://t.me/incredevly

Publicado en: Tecnología
  • Sé el primero en comentar

  • Sé el primero en recomendar esto

— Knock, knock — An async templates — Who’s there? - Alexander Khokhlov | Elixir Club 13

  1. 1. Alexander Khokhlov @nots_ioNots.io — Knock, knock — An async template — Who’s there?
  2. 2. Co-Founder Nots.io 01
  3. 3. README.md Code Comments JavaDoc GDocs Confluence / DokuWiki / Wiki
  4. 4. Nots.io Add docs for block of code, function, module, file, commit or branch 01
  5. 5. Notes, Tied to Code Easy to Discover Easy to Explore Easy to Get Scope Easy to Ask and Discuss 01 • Nots.io
  6. 6. We Track Relevance You always know what’s fresh and what’s not. Promotes keeping docs up-to-date. Rewarding when everything is ✅ 01 • Nots.io
  7. 7. Discuss with your Team You won’t loose a dispute that is written down. It’s tied and has context 01 • Nots.io
  8. 8. And many more awesome things 🔥 01 • Nots.io
  9. 9. Nots.io case 02 🏗
  10. 10. Choose File page 02 • Nots.io case
  11. 11. 02 • Nots.io case
  12. 12. In the template 02 • Nots.io case .branch-selector = Notsapp.Renderer.simple_component({:"dropdown/dropdown", …}) %h2 Files .tree = Notsapp.Renderer.simple_component({:"code-tree/tree", …})
  13. 13. Microservices YAY! 02 • Nots.io case
  14. 14. ⛔ ⛔ Blocking 04 .branch-selector = Notsapp.Renderer.simple_component({:"dropdown/dropdown", …}) %h2 Files .tree = Notsapp.Renderer.simple_component({:"code-tree/tree", …})
  15. 15. But we want non-blocking 02 🚀
  16. 16. Good news: It’s doable! 02
  17. 17. But first 03
  18. 18. 03 Phoenix templates
  19. 19. But first iolist() | iodata() 03 • Phoenix templates IO.puts(["Hello, ", "Elixir"]) IO.puts ["Hello, ", 69, 108, 105, 120, 105, 114] IO.puts ["Hello, ", [69, [108, [105, [120, [105, [114, ]]]]]]]
  20. 20. But first iolist() | iodata() Does not allocate new strings: Repeated chunks are created only once Does not concatenate strings/chars: Append to the list is O(1) and doesn’t require copying anything. 03 • Phoenix templates
  21. 21. Use iolist for I/O iolist() | iodata() With iolist & iodata work: Console I/O functions File I/O function :gen_tcp.send() :gen_udp.send() 03 • Phoenix templates
  22. 22. What about Elixir & Phoenix? 03 • Phoenix templates
  23. 23. At compile time Phoenix runs through the templates folder Uses EEx to convert each template into a function phoenix/lib/phoenix/template.ex 03 • Phoenix templates
  24. 24. At compile time https://www.bignerdranch.com/blog/elixir-and-io-lists-part-2-io-lists-in-phoenix/ 03 • Phoenix templates
  25. 25. At compile time 03 • Phoenix templates
  26. 26. At compile time https://www.bignerdranch.com/blog/elixir-and-io-lists-part-2-io-lists-in-phoenix/ 03 • Phoenix templates
  27. 27. At compile time https://www.bignerdranch.com/blog/elixir-and-io-lists-part-2-io-lists-in-phoenix/ 03 • Phoenix templates defmodule MyApp.SomeView do defp(index.html(var!(assigns))) do _ = var!(assigns) {:safe, [( tmp1 = ["" | "<h1>Listing Users</h1>nn<ul>n "] [tmp1 | case(for(user <- Phoenix.HTML.Engine.fetch_assign(var!(assigns), :users)) do {:safe, [( tmp1 = [( tmp1 = ["" | "n <li> “] [tmp1 | case(user.first_name()) do {:safe, data} -> data bin when is_binary(bin) -> Plug.HTML.html_escape(bin) other -> Phoenix.HTML.Safe.to_iodata(other) end] ) | " (“] … | "n</ul>nnThat's all!n"]}
  28. 28. Gosh! 03 • Phoenix templates
  29. 29. At the end of the day {:safe, [[["" | "<h1>Listing Users</h1>nn<ul>n "], [[[[["" | "n <li>"] | "Jane"] | " ("] | "1"] | ")</li>n "], [[[[["" | "n <li>"] | "Joe"] | " ("] | "2"] | ")</li>n "]] | "n</ul>nnThat's all!n"]} iolist In runtime 03 • Phoenix templates
  30. 30. Rewind ⏪ 04 .branch-selector = Notsapp.Renderer.simple_component({:"dropdown/dropdown", …}) %h2 Files .tree = Notsapp.Renderer.simple_component({:"code-tree/tree", …})
  31. 31. What if we return Task 🤔 Instead of HTML 04 • The solution task = Task.async(fn -> do_heavy_work() end) IO.puts "Do some more work" result = Task.await(task)
  32. 32. What if we return Task 🤔 in pseudocode 04 • The solution {:safe, [["" | "<div class="branch-selector"""> "], ["" | Task.async(fn -> render_dropdown() end)] , ["" | "n</div>nn"]]}
  33. 33. And when everything is ready — convert 04 • The solution defmodule Notsapp.TemplateRenderer do def process_rendered_template([h|t]) do [process_rendered_template(h) | process_rendered_template(t)] end def process_rendered_template(%Notsapp.CljTask{task: task}) do Task.await(task) end def process_rendered_template(e) do e end defmacro __using__(_opts) do quote do def render(template, assigns) do {:safe, io_list} = render_template(template, assigns) {:safe, process_rendered_template(io_list)} end end end end
  34. 34. Apply to every view 04 • The solution def view do quote do use Phoenix.View use Notsapp.TemplateRenderer # <-- use Phoenix.HTML
  35. 35. In parallel
  36. 36. Thank you 🤘
  37. 37. Alexander Khokhlov point@nots.io Nots.io nots.io blog.nots.io @nots_io facebook.com/nots.io

×