Interactive

By this point, you may be noticing that each concept builds on the previous one. Elixir makes productive, explicit layers available to programmers who can use them to build concurrent applications. Phoenix introduces beautiful, concurrent abstractions for use in beautiful APIs.

For the first four years, the Phoenix team worked at building this infrastructure, and this past year we’ve seen the culmination of this investment in new, exciting APIs for building interactive applications. The best example is Phoenix LiveView, a library for building applications without custom JavaScript. Until the right infrastructure was in place, LiveView could be only a dream.

Building interactive applications does require APIs that shield many different concerns from an end user, but APIs are just the tip of the iceberg. Underneath that tip is a tremendous amount of infrastructure. Let’s take a peak beneath the surface.

Scaling by Forgetting

Traditional web servers scale by treating each tiny user interaction as an identical stateless request. The application doesn’t save state between requests at all. It simply looks up the user and simultaneously looks up the context of the conversation in a user session. Presto. All scalability problems go away because there’s only one type of connection.

But there’s a cost. The developer must keep track of the state for each request, and that burden can be particularly arduous for newer, more interactive applications with intimate, long-running rich interactions. As a developer, until now, you’ve been forced to make a choice between applications that intentionally forget important details to scale and applications that try to remember too much and break under load.

Processes and Channels

With Elixir, you can create hundreds of thousands of lightweight processes without breaking a sweat. Lightweight processes also mean lightweight connections, and that matters because connections can be conversations. Whether you’re building a chat on a game channel or a map to the grocery store, you won’t have to juggle the details by hand anymore. This application style is called channels, and Phoenix makes it easy. Here’s what a typical channels feature might look like:

 def​ handle_in(​"​​new_annotation"​, params, socket) ​do
  broadcast! socket, ​"​​new_annotation"​, %{
 user:​ %{​username:​ ​"​​anon"​},
 body:​ params[​"​​body"​],
 at:​ params[​"​​at"​]
  }
 
  {​:reply​, ​:ok​, socket}
 end

You don’t have to understand the details. Just understand that when your application needs to connect your users and broadcast information in real time, your code can get much simpler and faster.

Even now, you’ll see many different types of frameworks begin to support channel-style features, from Java to JavaScript and even Ruby. Here’s the problem. None of them comes with the simple guarantees that Phoenix has: isolation and concurrency. Isolation guarantees that if a bug affects one channel, all other channels continue running. Breaking one feature won’t bleed into other site functionality. Concurrency means one channel can never block another one, whether code is waiting on the database or crunching data. This key advantage means that the UI never becomes unresponsive because the user started a heavy action. Without those guarantees, the development bogs down into a quagmire of low-level concurrency details.

You may also be wondering whether keeping an open connection per user can scale. The Phoenix team decided to benchmark their channels abstraction and they were able to reach two million connections on a single node.[4] And while that proves Phoenix Channels scale vertically (i.e., on powerful machines), it also scales horizontally. If you need to run a cluster of Phoenix instances, Phoenix will broadcast messages across all nodes out of the box, without a need for external dependencies.

It’s true, you can build these kinds of applications without Phoenix, but building them without the guarantees of isolation and concurrency is never pleasant. The results will almost universally be infected with reliability and scalability problems, and your users will never be as satisfied as you’d like to make them.

Presence and LiveView

As Phoenix grows and matures, the team continues to provide tools developers can use to build interactive applications. The first addition was support for tracking presence. Tracking which users are connected to a cluster of machines is a notoriously difficult problem. But in Phoenix, it takes as little as ten lines of code to track which users, fridges, cars, doors, or houses are connected to your application. In a world that is getting more and more connected, this feature is essential.

The best part about presence is that it doesn’t require any external dependencies. Regardless of whether you are running two Phoenix nodes or twenty, those nodes will communicate with each other, making sure to track connections regardless of where they happen in the cluster. You get a fantastic feature set right out of the box.

The most recent interactive development tool is LiveView. LiveView allows developers to build rich, interactive real-time applications without writing custom JavaScript.[5] For the JavaScript developers out there, it can be summarized as “server-side React”. Here is a simple counter built with LiveView:

 defmodule​ DemoWeb.CounterLive ​do
 use​ Phoenix.LiveView
 
 def​ render(assigns) ​do
 ~​L​"""
  <span><%= @val %></span>
  <button phx-click="inc">+</button>
  """
 end
 
 def​ mount(_session, socket) ​do
  {​:ok​, assign(socket, ​val:​ 0)}
 end
 
 def​ handle_event(​"​​inc"​, _, socket) ​do
  {​:noreply​, update(socket, ​:val​, &(&1 + 1))}
 end
 end

When Phoenix renders the page the first time, it works just like any other static page. That means browsers get a fast first-page view and search engines have something to index. Once rendered, Phoenix connects to the LiveView on the server, using WebSockets and Channels. LiveView applications are breathtakingly simple:

  • A function renders a web page.
  • That function accepts state as an input and returns a web page as output.
  • Events can change that state, bit by bit.

State is a simple data structure that can hold whatever you want it to. Events that change your state can come from a button or a form on a web page. Other events can come from your application, like a low-battery sensor elsewhere in your application.

The best part is that LiveView is smart enough to send only what changes, and only when it changes. And once again, all you need to make this work is Phoenix.

Combine LiveView with Phoenix’s ability to broadcast changes and track users in a cluster and you have the most complete tooling for building rich and interactive applications out of the box.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.103.204