Heim >Web-Frontend >js-Tutorial >PubNub vs. Pusher erstellen eine Echtzeit-Messaging-App in React

PubNub vs. Pusher erstellen eine Echtzeit-Messaging-App in React

DDD
DDDOriginal
2024-09-13 22:18:02715Durchsuche

Echtzeitdaten sind heutzutage eine der Grundpfeiler moderner Anwendungen. Ein System, das in der Lage ist, bidirektionale Informationen zu senden, ermöglicht es uns, über eine Vielzahl von Informationen auf dem Laufenden zu bleiben. Zu diesen Beispielen können Messaging-Anwendungen, Datenanalysen für Dashboards für Finanzdaten und Heads-up-Displays (HUDs) für erweiterte und virtuelle Anwendungen gehören. Wie ein Kampfpilot, der ein Flugzeug fliegt, oder ein Gelegenheitsnutzer, der ein Apple Vision Pro-Headset verwendet. Es gibt unzählige Anwendungsfälle für diese Technologie.

Wenn es um allgemeine IM-Anwendungen geht, eröffnet die Möglichkeit, in Echtzeit mit jemandem zu sprechen, die Tür zu so vielen einzigartigen Möglichkeiten. Durch diese neu gewonnenen Möglichkeiten ist unsere Welt immer vernetzter geworden. Im heutigen Artikel erfahren wir alles über Messaging, während wir eine Echtzeit-Messaging-Anwendung erstellen. Die Anwendung kann eine Verbindung zu zwei verschiedenen Echtzeit-Anwendungsplattformen herstellen, nämlich Pusher und PubNub.

Unsere Anwendung wird einer Basisversion der WhatsApp- und Telegram-Anwendungen ziemlich ähnlich sein. Es wird möglich sein, mehr als einen Webbrowser oder Browser-Tab zu öffnen und uns so die Möglichkeit zu geben, uns mit mehreren Benutzern anzumelden. Auf diese Weise können wir den Gruppenchat zwischen mehr als einem Benutzer testen, so wie Sie es mit einer echten Chat-Anwendung tun würden.

Unten sehen Sie, wie unser Haupt-Dashboard aussehen wird. Wie Sie sehen, gibt es Schaltflächen, mit denen Sie zu beiden Versionen unserer Messaging-App navigieren können:

PubNub vs Pusher creating a realtime messaging app in React

Und hier können Sie sehen, wie die PubNub-Version unserer App in diesem Screenshot aussieht. Es wird durch eine blaue Überschrift dargestellt:
PubNub vs Pusher creating a realtime messaging app in React

Die Pusher-Version hat eine grüne Kopfzeile und damit können Sie den Unterschied zwischen den beiden visuell erkennen:
PubNub vs Pusher creating a realtime messaging app in React

Okay, nachdem unsere kurze Einführung abgeschlossen ist, können wir jetzt einen viel gründlicheren Blick darauf werfen, wie wir sehen, wie sie sich voneinander unterscheiden. Die Codebasis für die Messaging-Anwendung finden Sie auf meinem GitHub hier: https://github.com/andrewbaisden/realtime-chat-app.

Voraussetzungen

Bevor wir beginnen, werfen Sie einen Blick auf diese Voraussetzungen und stellen Sie sicher, dass Sie alles eingerichtet haben, bevor wir beginnen.

  • Knoten und NPM installiert.
  • Eine IDE, die wie Visual Studio Code installiert ist
  • Ein Konto bei PubNub
  • Ein Konto auf Pusher

PubNub vs. Pusher

Beide Plattformen haben viele Gemeinsamkeiten, es gibt jedoch einige bemerkenswerte Unterschiede, die sie leicht unterscheiden lassen. Einer der Hauptgründe ist die Tatsache, dass ihre Architektur nicht dieselbe ist.

Architektonische Unterschiede

Bei PubNub handelt es sich um eine Cloud-Plattform, die sich um das Daten- und Nachrichten-Streaming kümmern kann. Es gibt eine sehr geringe Latenz und eine gute Serviceverfügbarkeit, da diese weltweit verfügbar ist. Die Skalierung und Infrastruktur wird von der Plattform gut gehandhabt, sodass Entwickler frei sind, an dem zu arbeiten, was wichtig ist, nämlich den Projekten.

Jetzt bieten sie mit Pusher verschiedene Bereitstellungsoptionen an, die selbst gehostet und in der Cloud gehostet werden. Wenn Sie Pusher selbst gehostet verwenden, kann es auf Ihrer eigenen benutzerdefinierten Hardware oder Software ausgeführt werden, was Ihnen viel Freiheit gibt. Wenn es um die in der Cloud gehostete Lösung geht, können Sie einen ähnlichen Service wie bei PubNub erwarten.

API- und SDK-Vergleich

Wenn wir ihre Funktionen vergleichen, können wir sehen, dass beide SDKs und Bibliotheken bieten, die von zahlreichen Programmiersprachen unterstützt werden. Dazu gehören JavaScript, Python, Java, Swift, Ruby und viele andere. Auf beiden Plattformen sind Kanäle verfügbar, sodass wir verschiedene Datenströme veröffentlichen und abonnieren können. Präsenz ist eine weitere Option. Damit können wir den Online- und Offline-Status aller Benutzer in Echtzeit auf den verschiedenen von uns eingerichteten Kanälen sehen. In Bezug auf den Nachrichtenverlauf ist es ähnlich und das Gleiche gilt auch für Push-Benachrichtigungen.

Ein weiterer toller Aspekt ist die Tatsache, dass sie reich an Funktionen sind und die Dokumentation sehr ausführlich ist, was es sehr einfach macht, die verschiedenen angebotenen Besonderheiten zu erlernen und sich mit ihnen vertraut zu machen. Die entsprechende Dokumentation finden Sie unten:

PubNub-Dokumentation: PubNub
Pusher-Dokumentation: Pusher

Implementierung einer Echtzeit-Messaging-App mit React

Zeit, an unserer Bewerbung zu arbeiten! Stellen Sie zunächst sicher, dass Sie ein Konto bei PubNub und Pusher haben. Wir werden nun schnell den Prozess der Kontoerstellung auf beiden Plattformen durchlaufen. Folgen Sie also den Anweisungen, wenn Sie noch keine Konten erstellt haben.

Erstellen eines Kontos bei PubNub

Beginnen Sie mit PubNub. Rufen Sie die Startseite der Website auf und klicken Sie auf die Schaltfläche oben rechts, um es kostenlos zu testen, wie unten gezeigt.

PubNub vs Pusher creating a realtime messaging app in React

Sie sollten nun die Registrierungsseite sehen, also fahren Sie fort und verwenden Sie das Formular, um Ihr Konto zu erstellen.

PubNub vs Pusher creating a realtime messaging app in React

Okay, jetzt sollte mit Ihrem erstellten Konto Zugriff auf das Dashboard möglich sein. Gehen Sie über das Menü zum Abschnitt „Keysets“ und suchen Sie dort nach Ihrer App und ihrem Keyset. Dies ist auch der Teil, in dem Sie eine App erstellen sollten, falls noch keine vorhanden ist.

Ihre API-Schlüssel sollten jetzt sichtbar sein. Stellen Sie daher sicher, dass die Optionen „Präsenz“ und „Persistenz“ aktiviert sind, da wir dies benötigen, um Benutzer und Daten zu verfolgen.

PubNub vs Pusher creating a realtime messaging app in React

Erstellen Sie ein Konto bei Pusher

Okay, wir sind mit unserem PubNub-Konto fertig, jetzt können wir an unserem Pusher-Konto arbeiten. Gehen Sie wie zuvor auf die Website und klicken Sie oben rechts auf der Seite auf die Schaltfläche „Anmelden“.

PubNub vs Pusher creating a realtime messaging app in React

Verwenden Sie nun auf dem folgenden Bildschirm das Formular, um ein Konto zu erstellen, wie Sie es hier sehen.

PubNub vs Pusher creating a realtime messaging app in React

Ein Kanal muss erstellt werden. Wählen Sie dazu auf der Dashboard-Seite die Schaltfläche „Verwalten“ aus.

PubNub vs Pusher creating a realtime messaging app in React
Erstellen Sie auf der nächsten Seite, die der Kanalbildschirm sein sollte, eine App, indem Sie die Schaltfläche „App erstellen“ verwenden, wie in diesem Screenshot gezeigt.

PubNub vs Pusher creating a realtime messaging app in React

Jetzt können wir mit dem Formular fortfahren und wie Sie in diesem Beispiel sehen können, sollte die Konfiguration maßgeschneidert für Ihren Anwendungsfall sein.

PubNub vs Pusher creating a realtime messaging app in React

Sobald diese Phase abgeschlossen ist, sollte die Kanalseite so angezeigt werden, wie sie hier ist.
PubNub vs Pusher creating a realtime messaging app in React
Klicken Sie im Seitenleistenmenü auf „App Keys“ und Sie erhalten dann Zugriff auf die API-Schlüssel, die Sie später benötigen.

PubNub vs Pusher creating a realtime messaging app in React

Super, die Kontoeinrichtungsphase ist nun abgeschlossen. Im nächsten Abschnitt beginnen wir mit dem Code für unsere App. Der erste Schritt besteht darin, die Projektarchitektur mit den Ordnern usw. zu erstellen. Ich habe ein Kopier- und Einfügeskript für die Befehlszeile erstellt, damit wir nicht alle Befehle manuell schreiben müssen. Erstellen Sie zunächst ein Projekt mit dem Namen „realtime-chat-app“ auf Ihrem Computer und gehen Sie dann über die Befehlszeile zum Speicherort.

Einrichten der React-Anwendung

Verwenden Sie Next.js, um ein Projekt zu erstellen, und verwenden Sie dann das Shell-Skript, um das Projekt einzurichten.

Wir beginnen mit der Ausführung dieses Befehls, um ein Next.js-Projekt zu erstellen:

npx create-next-app client

Jetzt ist es wichtig, auf dem Konfigurationsbildschirm Tailwind CSS und den App Router auszuwählen, da wir diese Optionen in diesem Projekt benötigen.

Hier ist das Shell-Skript zum Erstellen der Dateien und Ordner und zum Installieren der Abhängigkeiten. Führen Sie es einfach im selben Ordner aus. Es wird automatisch in den Client-Ordner kopiert. Wenn Sie sich bereits im Client-Ordner befinden, können Sie die erste Zeile im Skript weglassen.

cd client
npm install @pubnub/react-chat-components axios pubnub pubnub-react pusher pusher-js
touch .env.local
cd src/app
mkdir components pubnub pusher
touch components/ChatInterface.js components/ChatMessage.js components/ChatPubNub.js components/ChatPusher.js components/DashboardButton.js components/Header.js components/UserLogin.js pubnub/page.js pusher/page.js
cd ../../..
mkdir server
cd server
npm init -y
npm install express cors pusher dotenv
touch index.js .env
cd ..

Hier ist viel los, also schauen wir mal, was dieses Skript macht:

  • Installieren der Abhängigkeiten für unser Projekt, das die Pakete sowie die PubNub- und Pusher-Pakete enthält
  • Erstellen von Umgebungsvariablendateien für unsere API-Schlüssel
  • Erstellen der Dateien, Ordner und Komponenten für unsere gesamte App
  • Einrichten eines Backend-Servers, den Pusher für den API-Zugriff benötigt
  • Erstellen der Serverdateien für Routing- und Logikzwecke

Sehen Sie sich diesen Screenshot an. So sollte unser Projekt in Ihrer IDE aussehen:

PubNub vs Pusher creating a realtime messaging app in React

The hard work is done that build script did most of the work we just have to add the code to the files.

Right our first file is the globals.css file so clear all the code in that file and replace it with what is shown here:

@tailwind base;
@tailwind components;
@tailwind utilities;

body {
  background-color: rgb(15 23 42);
}

Code cleanup has been done in this file and now we have a background colour for our application.

Onto the layout.css file. Continuing from what we just did replace all the code with this new code:

import { Ubuntu } from 'next/font/google';
import './globals.css';

const ubuntu = Ubuntu({
  subsets: ['latin'],
  weight: ['300', '400', '500', '700'],
});

export const metadata = {
  title: 'Realtime Chat App',
  description: 'Generated by create next app',
};

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body className={ubuntu.className}>{children}</body>
    </html>
  );
}

Ubuntu is now the default font in our application.

All thats left in this section is to replace all of the code in our next.config.mjs file with this code:

/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        hostname: 'res.cloudinary.com',
      },
    ],
  },
};

export default nextConfig;

Cloudinary was added as an image host so now we can use it throughout our app.

And with that the project setup phase is done so in the next section we will work on the main files for our codebase. First we will do PubNub and then we will do Pusher.

Integrating PubNub

The initilisation and configuration part will be the first one to tackle. You must sign into your PubNub account, and find the application you made at the start. Locate your Keysets as well as the Publish and Subscribe Keys. Now put them inside of the .env.local file in the project.

Here is an example of where they should be put:

NEXT_PUBLIC_PUBNUB_PUBLISH_KEY=your-publish-key
NEXT_PUBLIC_PUBNUB_SUBSCRIBE_KEY=your-subscribe-key

Time to add some code to our components/ChatPubNub.js file, and this is the file where we can find the main code for subscribing to channels, handling the presence and publishing our message.

Put the code you see here into the components/ChatPubNub.js file:

import { useState, useEffect, useRef } from 'react';
import PubNub from 'pubnub';
import ChatInterface from './ChatInterface';

export default function ChatPubNub({ activeUser }) {
  const [chats, setChats] = useState([]);
  const [count, setCount] = useState(1);
  const bottomRef = useRef(null);

  let pubnub;
  const channelName = 'presence-chatroom';

  useEffect(() => {
    pubnub = new PubNub({
      publishKey: process.env.NEXT_PUBLIC_PUBNUB_PUBLISH_KEY,
      subscribeKey: process.env.NEXT_PUBLIC_PUBNUB_SUBSCRIBE_KEY,
      uuid: activeUser,
    });

    pubnub.addListener({
      message: (messageEvent) => {
        const chat = messageEvent.message;
        setChats((prevChats) => [...prevChats, chat]);
      },
    });

    const presenceChannelName = `${channelName}-pnpres`;

    pubnub.subscribe({
      channels: [channelName],
      withPresence: true,
      presenceChannels: [presenceChannelName],
    });

    const scrollToBottom = () => {
      bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
    };

    scrollToBottom();

    return () => {
      pubnub.unsubscribeAll();
    };
  }, [chats, activeUser, count]);

  const handleKeyUp = (evt) => {
    const value = evt.target.value;
    if (evt.keyCode === 13 && !evt.shiftKey) {
      const chat = { user: activeUser, message: value, timestamp: +new Date() };
      evt.target.value = '';
      pubnub.publish({
        channel: channelName,
        message: chat,
      });
    }
  };

  return activeUser ? (
    <>
      <ChatInterface
        activeUser={activeUser}
        count={count}
        chats={chats}
        handleKeyUp={handleKeyUp}
        bottomRef={bottomRef}
      />
    </>
  ) : null;
}

Here is a quick explanation of what our code does in this file. We can do subscriptions to channels, publish messages to different channels as well as handle the overall presence information. With these capabilities our app will function a lot like a group chat and with presence switched on we can see how many users are online in real-time.

We can work on our next file now which is the components/ChatInterface.js so add this code to it:

import ChatMessage from './ChatMessage';

export default function ChatInterface({
  activeUser,
  count,
  chats,
  handleKeyUp,
  bottomRef,
}) {
  return (
    <div className="flex">
      <aside className="w-64 min-w-64 bg-slate-800 p-2">
        <h1 className="text-lg text-white">Chats</h1>
        <div className="flex justify-between mt-2">
          <div className="flex">
            <div className="rounded-full bg-slate-100 h-10 w-10 mr-2"></div>
            <div className="text-sm">
              <p className="text-white">John</p>
              <p className="text-slate-400">Hello world</p>
            </div>
          </div>
          <div className="text-sm text-slate-400">Friday</div>
        </div>
      </aside>
      <section className="grow">
        <div className="bg-zinc-800 p-2">
          <div className="flex">
            <div className="rounded-full bg-slate-100 h-10 w-10 mr-2"></div>
            <div>
              <h1 className="text-2xl text-white">{activeUser}</h1>
              <span className="text-gray-300">users online: {count}</span>
            </div>
          </div>
        </div>
        <div className="bg-zinc-900 p-2 overflow-y-auto h-80 max-h-80 text-white">
          {chats.map((chat, index) => {
            const previous = Math.max(0, index - 1);
            const previousChat = chats[previous];
            const position = chat.user === activeUser ? 'right' : 'left';
            const isFirst = previous === index;
            const inSequence = chat.user === previousChat.user;
            const hasDelay =
              Math.ceil(
                (chat.timestamp - previousChat.timestamp) / (1000 * 60)
              ) > 1;
            return (
              <div key={index}>
                {(isFirst || !inSequence || hasDelay) && (
                  <div>
                    <span>{chat.user || 'Anonymous'}</span>
                  </div>
                )}

                <ChatMessage message={chat.message} position={position} />
              </div>
            );
          })}
          <div ref={bottomRef} />{' '}
        </div>
        <div className="w-full bg-zinc-800 p-2">
          <textarea
            onKeyUp={handleKeyUp}
            placeholder="Enter a message"
            className="w-full block rounded mt-2 mb-2 p-2 text-white bg-zinc-600"
          ></textarea>
        </div>
      </section>
    </div>
  );
}

Our component displays the UI for our messaging chat interface. There is a section for messaging, sending messages and a sidebar, which could hold users when they are in the group.

The next component is for the components/ChatMessage.js file and this has our chat message interface.

Add this code to the file:

export default function ChatMessage({ message }) {
  return (
    <div>
      <div className="mt-4 mb-4">
        <span className="bg-zinc-600 p-2 rounded">{message}</span>
      </div>
    </div>
  );
}

Chat bubbles should become possible thanks to this component whenever we use the chat to send messages to users.

Dashboard buttons is what we require next so add this code to our components/DashboardButton.js file:

import Link from 'next/link';
import Image from 'next/image';

export default function DashboardButton({ url, img, alt }) {
  return (
    <>
      <Link href={url}>
        <div className="rounded mr-4 bg-slate-50 hover:bg-slate-200 h-96 w-96 text-center flex items-center justify-center drop-shadow-lg uppercase">
          <Image src={img} height={200} width={200} alt={alt} />
        </div>
      </Link>
    </>
  );
}

We can now easily navigate between the PubNub and Pusher versions of our real-time messaging chat app using these reusable buttons.

Ok the navigation component is next and this is for our main header. Put this code in our file at components/Header.js:

import Link from 'next/link';

export default function Header() {
  return (
    <>
      <nav className="bg-white flex justify-around p-8 mb-4 font-bold">
        <Link href={'/'}>Dashboard</Link>
        <Link href={'/pusher'}>Pusher Chat App</Link>
        <Link href={'/pubnub'}>PubNub Chat App</Link>
      </nav>
    </>
  );
}

All our page routes are easily able to be navigated using this header component which has page links.

The login screen is next and this is the code our file at components/UserLogin.js desires:

import { useState } from 'react';
import ChatPubNub from '../components/ChatPubNub';
import ChatPusher from '../components/ChatPusher';

export default function UserLogin({ bgColor, appName }) {
  const [user, setUser] = useState(null);

  const handleKeyUp = (evt) => {
    if (evt.keyCode === 13) {
      const newUser = evt.target.value;
      setUser(newUser);
    }
  };
  return (
    <>
      <main>
        <div>
          <section>
            <div className={`p-4 ${bgColor} text-slate-100`}>
              <span>
                {user ? (
                  <span className="flex justify-between text-white">
                    <span>
                      {user} <span>is online</span>
                    </span>
                    <span>{appName}</span>
                  </span>
                ) : (
                  <span className="text-2xl text-white">
                    What is your name?
                  </span>
                )}
              </span>
              {!user && (
                <input
                  type="text"
                  onKeyUp={handleKeyUp}
                  autoComplete="off"
                  className="w-full block rounded mt-2 mb-2 p-2 text-black"
                />
              )}
            </div>
          </section>
          {appName === 'PubNub Chat' ? (
            <section>{user && <ChatPubNub activeUser={user} />}</section>
          ) : (
            <section>{user && <ChatPusher activeUser={user} />}</section>
          )}
        </div>
      </main>
    </>
  );
}

Its a pretty straightforward login screen component whereby a user can choose a name and then they get redirected to the messaging app. There is logic to check which app a user is using and it automatically sends the user to the right chat interface for that version of the app.

Lets do the pubnub/page.js route file now and add this code to it:

'use client';
import Header from '../components/Header';
import UserLogin from '../components/UserLogin';

export default function PubNub() {
  return (
    <div>
      <Header />
      <UserLogin bgColor={'bg-sky-800'} appName={'PubNub Chat'} />
    </div>
  );
}

We can find the main page route for the PubNub version messaging app.

Lastly we must add code to our page.js file in the root folder to complete our application so like before just replace the code with what we have written here:

'use client';
import DashboardButton from './components/DashboardButton';

export default function Home() {
  return (
    <>
      <div className="h-screen flex justify-center items-center">
        <div className="text-center">
          <h1 className="mb-4 text-white text-4xl">Choose a messaging app</h1>
          <div className="grid gap-2 lg:grid-cols-2 md:grid-cols-1 sm:grid-cols-1">
            <DashboardButton
              url={'/pusher'}
              img={
                'https://res.cloudinary.com/d74fh3kw/image/upload/v1715187329/pusher-logo_u0gljx.svg'
              }
              alt="Pusher Logo"
            />
            <DashboardButton
              url={'/pubnub'}
              img={
                'https://res.cloudinary.com/d74fh3kw/image/upload/v1715189173/pubnub-logo-vector_olhbio.png'
              }
              alt="PubNub Logo"
            />
          </div>
        </div>
      </div>
    </>
  );
}

Our main dashboard link can be found here which has the buttons for our PubNub and Pusher version of our application.

The PubNub messaging part of our application should be good to go now! Just cd into the client folder if you have not done so already and start the application with the usual Next.js run command:

npm run dev

Its worth mentioning that the Pusher part of our application is not going to work yet as we must complete the integrations in the upcoming section. To use the PubNub app go to the login screen, enter a name and hit the enter button and then you will see the messenger chat application screen. You can see your online status and the sidebar has a hard-coded user which is just an example.

To make the application more interactive open more browser tabs or browser windows and sign in with more users. Having a real-time group chat is now possible just like any other messaging app you are familiar with.

In the next section we shall get Pusher up and working.

Integrating Pusher

This section will take less time because we get to reuse a lot of the components we used in the earlier sections. The difference this time around is that Pusher will need to connect to our backend server to work.

Like before we are going to start with the configuration files for our .env.local and .env files in the server and client folders. We need to add the same secrets to the files. Find your application on the Pusher platform and then find the App keys.

The App keys must be added to the env files with the right variables. Take a note of this key difference. Our client .env.local env file must have NEXT_PUBLIC at the start, and the .env file in the server folder does not require it and you can see that in the examples below.

Here is our .env.local file which is in the client folder:

NEXT_PUBLIC_PUBNUB_PUBLISH_KEY=your-publish-key
NEXT_PUBLIC_PUBNUB_SUBSCRIBE_KEY=your-subscribe-key
NEXT_PUBLIC_PUSHER_APP_ID=your-app-id
NEXT_PUBLIC_PUSHER_APP_KEY=your-app-key
NEXT_PUBLIC_PUSHER_APP_SECRET=your-app-secret
NEXT_PUBLIC_PUSHER_APP_CLUSTER=your-cluster

And this is the .env file which can be found in the server folder:

PUSHER_APP_ID=your-app-id
PUSHER_APP_KEY=your-app-key
PUSHER_APP_SECRET=your-app-secret
PUSHER_APP_CLUSTER=your-cluster

Time to work on the frontend so you know the drill add this code to the components/ChatPusher.js file:

import { useState, useEffect, useRef } from 'react';
import axios from 'axios';
import Pusher from 'pusher-js';
import ChatInterface from './ChatInterface';

export default function ChatPusher({ activeUser }) {
  const [chats, setChats] = useState([]);
  const [count, setCount] = useState(0);
  const bottomRef = useRef(null);

  let channel;
  let pusher;

  useEffect(() => {
    pusher = new Pusher(process.env.NEXT_PUBLIC_PUSHER_APP_KEY, {
      cluster: process.env.NEXT_PUBLIC_PUSHER_APP_CLUSTER,
      useTLS: true,
      channelAuthorization: {
        endpoint: 'http://localhost:8000/auth',
      },
    });

    channel = pusher.subscribe('presence-chatroom');
    channel.bind('new-message', ({ chat = null }) => {
      if (chat) {
        setChats((prevChats) => [...prevChats, chat]);
      }
    });

    channel.bind('pusher:subscription_succeeded', () => {
      updateMemberCount(channel);
    });

    channel.bind('pusher:member_added', () => {
      updateMemberCount(channel);
    });
    channel.bind('pusher:member_removed', () => {
      updateMemberCount(channel);
    });

    const scrollToBottom = () => {
      bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
    };

    scrollToBottom();

    return () => {
      pusher.disconnect();
    };
  }, [chats]);

  const updateMemberCount = (presenceChannel) => {
    const memberCount = Object.keys(presenceChannel.members.members).length;
    console.log('Count people online', memberCount);
    setCount(memberCount);
  };

  const handleKeyUp = (evt) => {
    const value = evt.target.value;
    if (evt.keyCode === 13 && !evt.shiftKey) {
      const chat = { user: activeUser, message: value, timestamp: +new Date() };
      evt.target.value = '';
      axios.post('http://localhost:8000/message', chat);
    }
  };

  return activeUser ? (
    <>
      <ChatInterface
        activeUser={activeUser}
        count={count}
        chats={chats}
        handleKeyUp={handleKeyUp}
        bottomRef={bottomRef}
      />
    </>
  ) : null;
}

There are similarities here to our PubNub component which matches this. We can subscribe to the channels, publish different messages and handle the presence. Although all of this is now done via the backend which now also works with basic authentication. Unlike the PubNub version however this version can accurately see how many users are online as well as when users are active, join and leave the group chat.

An authentication route is present for authenticating users and we incorporated a message route for posting all messages to our server.

Our frontend is almost completed just one file remains so add this code to our pusher.page.js file now:

'use client';
import Header from '../components/Header';
import UserLogin from '../components/UserLogin';

export default function Pusher() {
  return (
    <div>
      <Header />
      <UserLogin bgColor={'bg-emerald-800 '} appName={'Pusher Chat'} />
    </div>
  );
}

This file ensures that our Pusher version has a working route. All thats left is to get the messaging app up and running when we do the server file next.

Before we do that we should setup our run script in our package.json file so add this script to it:

"scripts": {
"start": "node index.js"
},

Alright, last file! Add this code to our index.js file in the server folder so we can complete the backend:

const cors = require('cors');
const Pusher = require('pusher');
const express = require('express');
require('dotenv').config();
const crypto = require('crypto');
const dev = process.env.NODE_ENV !== 'production';
const port = process.env.PORT || 8000;

const pusher = new Pusher({
  appId: process.env.PUSHER_APP_ID,
  key: process.env.PUSHER_APP_KEY,
  secret: process.env.PUSHER_APP_SECRET,
  cluster: process.env.PUSHER_APP_CLUSTER,
  useTLS: true,
});

const server = express();
server.use(cors());
server.use(express.json());
server.use(express.urlencoded({ extended: false }));

const chatHistory = { messages: [] };

server.post('/message', (req, res) => {
  const { user = null, message = '', timestamp = +new Date() } = req.body;
  const chat = { user, message, timestamp };
  chatHistory.messages.push(chat);
  pusher.trigger('presence-chatroom', 'new-message', { chat });
  res.status(200).send('Message sent successfully.');
});
server.post('/messages', (req, res) => {
  res.json({ ...chatHistory, status: 'success' });
});

server.post('/auth', (req, res) => {
  const socketId = req.body.socket_id;
  const channel = req.body.channel_name;
  console.log('Socket and channel', socketId, channel);
  const userId = crypto.randomBytes(8).toString('hex');

  const presenceData = {
    user_id: userId,
    user_info: {
      name: 'Anonymous User',
    },
  };

  const auth = pusher.authorizeChannel(socketId, channel, presenceData);
  res.send(auth);
});

server.listen(port, (err) => {
  if (err) throw err;
  console.log(`Server is running on port: ${port} http://localhost:${port}`);
});

Just a quick run through of this file so we can understand how it works. If you don't know its an Express server file which can connect to the Pusher API and it has routes for the authentication, message posting, in addition to getting chat history for all messages.

For connectivity, cors is implemented, so we don't get any of those annoying errors when trying to connect to different servers. The crypto module is used to doing various tasks like hash generation and encrypting and decrypting data.

With our codebase at MVP status, all you have to do is run the backend server in a different terminal window with the following command as shown below:

npm run start

So our server will run on port 8000 and you can change this in the server code if need be. Of course our Next.js application runs on port 3000, they need to be on different ports for obvious reasons. You already know how to use the PubNub version, the Pusher version works much the same.

Congratulations you have reached the end of this tutorial and created a working real-time messaging application!

Conclusion

Thats it we have completed the tutorial, learned about both real-time messaging applications and built a working demo application. As you have learned both platforms offer a similar feature set although Pusher has self-hosted and cloud options whereas PubNub offers only the later.

Ultimately your choice of platform will come down to what you make of their pros and cons. They have a free plan, so testing them is pretty easy to do. Pusher has flexible pricing in contrast to PubNubs strict pricing that offers much cheaper starter options priced at $98 compared to $49 for the Pusher startup option.

Das obige ist der detaillierte Inhalt vonPubNub vs. Pusher erstellen eine Echtzeit-Messaging-App in React. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn