ProductPromotion
Logo

Elixir

made by https://0x3d.site

Building Real-Time Web Apps with Phoenix Channels
Phoenix Channels bring real-time capabilities to web applications, allowing developers to build interactive and dynamic user experiences with ease. Channels are a powerful feature of the Phoenix framework that enable bi-directional communication between clients and servers over WebSockets. In this guide, we’ll explore how to implement real-time features using Phoenix Channels, create a live chat application, broadcast messages, and scale real-time apps effectively.
2024-09-11

Building Real-Time Web Apps with Phoenix Channels

What are Phoenix Channels and How Do They Enable Real-Time Communication?

Understanding Phoenix Channels

Phoenix Channels are built on top of WebSockets, which allow for persistent, full-duplex communication channels between the client and server. Unlike traditional HTTP requests that follow a request-response model, WebSockets enable continuous, real-time data exchange.

Key Concepts:

  • Channel: A topic-based communication channel that clients can join to send and receive messages.
  • Topic: A string that identifies a specific channel. Clients subscribe to topics to participate in conversations.
  • Socket: The connection object through which messages are sent and received. Each client has a socket that interacts with one or more channels.

How Phoenix Channels Work

  1. Connection Establishment: A client establishes a WebSocket connection to the server. Phoenix uses this connection to handle real-time interactions.
  2. Joining a Channel: The client joins a channel by subscribing to a specific topic.
  3. Message Exchange: Once connected, the client and server can send messages to each other on the subscribed channel.
  4. Event Handling: Both client and server handle events such as messages or connection changes.

Setting Up a Phoenix Channel in a Web App

Creating a Phoenix Project

If you haven’t already, start by creating a new Phoenix project:

mix phx.new real_time_app --no-html --no-webpack
cd real_time_app

The --no-html and --no-webpack options are used here to create a minimal setup. You can include these options based on your project needs.

Adding Channels to Your Project

  1. Generate a Channel: Create a new channel using the Phoenix generator:

    mix phx.gen.channel Room
    

    This command generates a new channel module and related files.

  2. Define Your Channel: Edit the generated channel file lib/real_time_app_web/channels/room_channel.ex to handle incoming messages and events:

    defmodule RealTimeAppWeb.RoomChannel do
      use RealTimeAppWeb, :channel
    
      def join("room:lobby", _params, socket) do
        {:ok, socket}
      end
    
      def handle_in("message:new", %{"body" => body}, socket) do
        broadcast(socket, "message:new", %{"body" => body})
        {:noreply, socket}
      end
    end
    
    • join/3: This function is called when a client joins the channel. The room:lobby topic is used here as an example.
    • handle_in/3: This function handles incoming messages on the message:new event and broadcasts them to all clients in the channel.
  3. Update Your Socket Configuration: Configure the socket in lib/real_time_app_web/channels/user_socket.ex to include your new channel:

    defmodule RealTimeAppWeb.UserSocket do
      use Phoenix.Socket
    
      ## Channels
      channel "room:*", RealTimeAppWeb.RoomChannel
    
      ## Transports
      transport :websocket, Phoenix.Transports.WebSocket
      ...
    end
    

    This configuration sets up the RoomChannel to handle messages on any topic starting with "room:".

Creating a Live Chat Application Using Phoenix Channels

Frontend Setup

  1. Create a Simple HTML Interface: Create a basic HTML file for your chat interface. Place it in the assets directory, such as assets/static/chat.html:

    <!DOCTYPE html>
    <html>
    <head>
      <title>Chat</title>
      <script src="/js/app.js"></script>
    </head>
    <body>
      <div id="chat"></div>
      <input id="message_input" type="text" placeholder="Type a message..." />
      <button id="send_button">Send</button>
    </body>
    </html>
    
  2. Add JavaScript for Channel Communication: Edit the assets/js/app.js file to include WebSocket functionality:

    import { Socket } from "phoenix";
    
    let socket = new Socket("/socket", { params: { token: window.userToken } });
    socket.connect();
    
    let channel = socket.channel("room:lobby", {});
    
    channel.join()
      .receive("ok", resp => console.log("Joined successfully", resp))
      .receive("error", resp => console.log("Unable to join", resp));
    
    channel.on("message:new", payload => {
      let chat = document.getElementById("chat");
      let message = document.createElement("p");
      message.innerText = payload.body;
      chat.appendChild(message);
    });
    
    document.getElementById("send_button").addEventListener("click", () => {
      let messageInput = document.getElementById("message_input");
      let body = messageInput.value;
      channel.push("message:new", { body: body });
      messageInput.value = "";
    });
    

    This script connects to the Phoenix socket, joins the room:lobby channel, listens for messages, and handles sending new messages.

Running the Application

  1. Start the Phoenix Server: Run your Phoenix server to see the chat application in action:

    mix phx.server
    
  2. Access the Chat Interface: Open http://localhost:4000/chat.html in your web browser to use the chat interface.

Broadcasting Messages and Handling Events in Real Time

Broadcasting Messages

To broadcast messages to all clients connected to a channel, use the broadcast/3 function in your channel module. This function sends a message to all clients subscribed to the specified topic.

Example:

def handle_in("message:new", %{"body" => body}, socket) do
  broadcast(socket, "message:new", %{"body" => body})
  {:noreply, socket}
end

In this example, when a new message is received, it is broadcast to all clients in the "room:lobby" channel.

Handling Real-Time Events

You can handle various real-time events such as user presence, typing indicators, and more. For example, you can broadcast a typing indicator whenever a user is typing a message.

Example:

def handle_in("user:typing", %{"user_id" => user_id}, socket) do
  broadcast(socket, "user:typing", %{"user_id" => user_id})
  {:noreply, socket}
end

On the client side, handle the "user:typing" event to display typing indicators.

Scaling Real-Time Apps with Phoenix

Scaling real-time applications involves managing connections, handling large volumes of messages, and distributing load across multiple servers. Here’s how to scale Phoenix applications effectively:

Using Presence

Phoenix Presence is a library for tracking and broadcasting information about connected users and their states. It helps manage user presence and can be used for features like online status indicators.

Example Setup:

  1. Add Presence to Your Application: Configure Presence in your application’s application.ex file:

    def start(_type, _args) do
      children = [
        ...
        {Phoenix.Presence, "room:lobby"}
      ]
      ...
    end
    
  2. Track User Presence: Use Presence in your channel to track user presence:

    defmodule RealTimeAppWeb.RoomChannel do
      use RealTimeAppWeb, :channel
      alias RealTimeAppWeb.Presence
    
      def join("room:lobby", _params, socket) do
        send(self(), :after_join)
        {:ok, socket}
      end
    
      def handle_info(:after_join, socket) do
        Presence.track(socket, "user:#{socket.assigns.user_id}", %{
          online_at: inspect(System.system_time(:seconds))
        })
        {:noreply, socket}
      end
    end
    

Horizontal Scaling

For horizontal scaling, deploy your Phoenix application across multiple servers. Use a distributed database and message broker to synchronize state and messages between instances.

  • Database: Use databases that support distributed setups, like PostgreSQL with replication or distributed databases like Cassandra.
  • Message Broker: Employ message brokers such as RabbitMQ or Redis to distribute messages between server instances.

Load Balancing

Implement load balancers to distribute incoming WebSocket connections across multiple server instances. Ensure that your load balancer supports sticky sessions to maintain WebSocket connections.

Conclusion

Phoenix Channels enable powerful real-time features in web applications, allowing for seamless and interactive user experiences. By setting up channels, creating a live chat application, broadcasting messages, and scaling your application, you can harness the full potential of real-time communication with Phoenix.

As you continue to build real-time features, explore additional capabilities like presence tracking, advanced message handling, and optimization techniques to enhance the performance and scalability of your applications.

Happy coding, and may your real-time applications thrive with Phoenix Channels!

Articles
to learn more about the elixir concepts.

Resources
which are currently available to browse on.

mail [email protected] to add your project or resources here 🔥.

FAQ's
to know more about the topic.

mail [email protected] to add your project or resources here 🔥.

Queries
or most google FAQ's about Elixir.

mail [email protected] to add more queries here 🔍.

More Sites
to check out once you're finished browsing here.

0x3d
https://www.0x3d.site/
0x3d is designed for aggregating information.
NodeJS
https://nodejs.0x3d.site/
NodeJS Online Directory
Cross Platform
https://cross-platform.0x3d.site/
Cross Platform Online Directory
Open Source
https://open-source.0x3d.site/
Open Source Online Directory
Analytics
https://analytics.0x3d.site/
Analytics Online Directory
JavaScript
https://javascript.0x3d.site/
JavaScript Online Directory
GoLang
https://golang.0x3d.site/
GoLang Online Directory
Python
https://python.0x3d.site/
Python Online Directory
Swift
https://swift.0x3d.site/
Swift Online Directory
Rust
https://rust.0x3d.site/
Rust Online Directory
Scala
https://scala.0x3d.site/
Scala Online Directory
Ruby
https://ruby.0x3d.site/
Ruby Online Directory
Clojure
https://clojure.0x3d.site/
Clojure Online Directory
Elixir
https://elixir.0x3d.site/
Elixir Online Directory
Elm
https://elm.0x3d.site/
Elm Online Directory
Lua
https://lua.0x3d.site/
Lua Online Directory
C Programming
https://c-programming.0x3d.site/
C Programming Online Directory
C++ Programming
https://cpp-programming.0x3d.site/
C++ Programming Online Directory
R Programming
https://r-programming.0x3d.site/
R Programming Online Directory
Perl
https://perl.0x3d.site/
Perl Online Directory
Java
https://java.0x3d.site/
Java Online Directory
Kotlin
https://kotlin.0x3d.site/
Kotlin Online Directory
PHP
https://php.0x3d.site/
PHP Online Directory
React JS
https://react.0x3d.site/
React JS Online Directory
Angular
https://angular.0x3d.site/
Angular JS Online Directory