Implementing WebSockets With Elixir and Phoenix Framework
WebSockets have become a crucial part of modern web applications, enabling real-time communication between clients and servers. In this article, we'll explore how to implement WebSockets using the Elixir programming language and the Phoenix framework, which is known for its high-performance capabilities and scalability.
What is WebSocket?
WebSockets are a protocol that allows for full-duplex communication channels over a single TCP connection. Unlike traditional HTTP requests, which are request-response based, WebSockets enable continuous data streams, making them ideal for applications that require real-time updates, such as chat applications, online gaming, and live notifications.
Setting Up Your Phoenix Application
Before diving into WebSocket implementation, ensure you have Elixir and Phoenix installed on your machine. If you haven't set up a Phoenix project yet, you can create one using the following command:
mix phx.new my_app --no-ecto
Navigate to your project directory:
cd my_app
Adding WebSocket Support to Your Phoenix App
To implement WebSockets, you need to define a WebSocket channel. First, generate a channel by running:
mix phx.gen.channel Topic
This command will create a new channel module in the `lib/my_app_web/channels` directory. Open the newly created file and modify the `join` function to handle joining the channel:
defmodule MyAppWeb.TopicChannel do
use MyAppWeb, :channel
def join("topic:lobby", _message, socket) do
{:ok, socket}
end
def handle_in("new_msg", %{"body" => body}, socket) do
broadcast!(socket, "new_msg", %{body: body})
{:noreply, socket}
end
end
Configuring the Endpoint
The next step involves updating your endpoint configuration to enable WebSocket connections. Locate the `lib/my_app_web/endpoint.ex` file and ensure the following line is uncommented:
socket "/socket", MyAppWeb.UserSocket
You also need to create the UserSocket module, which defines how users can connect to different channels:
defmodule MyAppWeb.UserSocket do
use Phoenix.Socket
channel "topic:*", MyAppWeb.TopicChannel
def connect(_params, socket, _connect_info) do
{:ok, socket}
end
def id(_socket), do: nil
end
Frontend WebSocket Connection
Now that the backend is set up, it's time to implement the WebSocket connection on the client-side. In your HTML file, include the Phoenix JavaScript library:
<script src="/js/phoenix.js"></script>
Then, create a connection to the WebSocket in a separate JavaScript file. Use the following code block:
import { Socket } from "phoenix"
let socket = new Socket("/socket", {params: {userToken: "123"}})
socket.connect()
let channel = socket.channel("topic:lobby", {})
channel.join()
.receive("ok", resp => { console.log("Joined successfully", resp) })
.receive("error", resp => { console.log("Unable to join", resp) })
channel.on("new_msg", payload => {
console.log("Received new message:", payload.body)
})
document.getElementById("send_message").addEventListener("click", () => {
let input = document.getElementById("message_input").value
channel.push("new_msg", {body: input})
document.getElementById("message_input").value = ""
})
Testing Your WebSockets
Now that everything is set up, you can start your Phoenix server:
mix phx.server
Open your browser and navigate to the appropriate URL (typically http://localhost:4000). Test sending and receiving messages to verify that your WebSockets are working as expected.
Conclusion
Implementing WebSockets in an Elixir and Phoenix application allows you to build real-time features that enhance user experience significantly. With the ability to manage concurrent users and scale effortlessly, Phoenix and