React でリアルタイム メッセージング アプリを作成する PubNub と Pusher の比較

DDD
リリース: 2024-09-13 22:18:02
オリジナル
698 人が閲覧しました

リアルタイム データは、最近の最新アプリケーションの中核となる柱の 1 つです。双方向に情報を発信できるシステムを構築することで、さまざまな情報を常に最新の状態に保つことができます。このような例には、メッセージング アプリケーション、財務データに使用されるダッシュボードのデータ分析、拡張アプリケーションや仮想アプリケーションで使用されるヘッドアップ ディスプレイ (HUD) などが含まれます。航空機を操縦する戦闘機のパイロットや、Apple Vision Pro ヘッドセットを使用する一般消費者などです。このテクノロジーには無限のユースケースがあります。

一般的な IM アプリケーションについて言えば、リアルタイムで誰かと会話できる機能があれば、非常に多くのユニークな可能性への扉が開かれます。これらの新しく発見された機能の結果、私たちの世界はさらにつながりやすくなりました。今日の記事では、リアルタイム メッセージング アプリケーションを構築しながら、メッセージングについてすべて学びます。アプリケーションは、Pusher と PubNub という 2 つの異なるリアルタイム アプリケーション プラットフォームに接続できるようになります。

私たちのアプリケーションは、WhatsApp および Telegram アプリケーションの基本的な必要最低限​​のバージョンにかなり似ています。複数の Web ブラウザーまたはブラウザー タブを開くことができるようになり、複数のユーザーでサインインできるようになります。このようにして、実際のチャット アプリケーションの場合と同じように、複数のユーザー間のグループ チャットをテストできます。

以下に、メイン ダッシュボードがどのように見えるかを示します。メッセージング アプリの両方のバージョンに移動するボタンがあることがわかります:

PubNub vs Pusher creating a realtime messaging app in React

そして、このスクリーンショットで、アプリの PubNub バージョンがどのように見えるかを確認できます。これは青いヘッダーで表されます:
PubNub vs Pusher creating a realtime messaging app in React

プッシャー バージョンには緑色のヘッダーがあり、これにより 2 つの違いを視覚的に区別できるようになります:
PubNub vs Pusher creating a realtime messaging app in React

簡単な紹介は完了しました。今度は、それらが互いにどのように対照的であるかを確認しながら、より徹底的に見ていきます。メッセージング アプリケーションのコードベースは、私の GitHub にあります: https://github.com/andrewbaisden/realtime-chat-app.

前提条件

始める前に、これらの前提条件を確認し、すべての設定が完了していることを確認してください。

  • ノードと npm がインストールされました。
  • Visual Studio Code のようにインストールされた IDE
  • PubNub のアカウント
  • Pusher のアカウント

パブナブ vs プッシャー

両方のプラットフォームには多くの共通点がありますが、区別しやすいようにいくつかの顕著な違いがあります。主な問題の 1 つは、アーキテクチャが同じではないという事実です。

アーキテクチャの違い

PubNub の場合、データとメッセージのストリーミングを処理できるクラウド プラットフォームです。世界中で利用できるため、サービスの可用性が高く、遅延が非常に短くなります。スケーリングとインフラストラクチャはプラットフォームによって適切に処理されるため、開発者は重要なプロジェクトに自由に取り組むことができます。

Pusher では、セルフホスト型とクラウド ホスト型のさまざまな導入オプションを提供しています。セルフホスト型を使用する場合、Pusher は独自のカスタム ハードウェアまたはソフトウェア上で実行できるため、非常に自由度が高くなります。クラウドホスト型ソリューションに関しては、PubNub と同様のサービスが期待できます。

API と SDK の比較

これらの機能を比較すると、どちらも多数のプログラミング言語でサポートされている SDK とライブラリを提供していることがわかります。これらには、JavaScript、Python、Java、Swift、Ruby などが含まれます。チャネルは両方のプラットフォームで利用できるため、さまざまなデータ ストリームのパブリッシュとサブスクライブが可能になります。プレゼンスも別のオプションであり、これを使用すると、設定したさまざまなチャネルですべてのユーザーのオンラインおよびオフラインのステータスをリアルタイムで確認できます。メッセージ履歴に関しても同様の話であり、プッシュ通知にも同じことが当てはまります。

もう 1 つの優れた点は、機能が豊富であり、ドキュメントが非常に充実しているため、提供されているさまざまな特徴を簡単に学習して把握できるという事実です。それぞれのドキュメントは以下で見つけることができます:

PubNub ドキュメント: PubNub
プッシャーのドキュメント: プッシャー

React を使用したリアルタイム メッセージング アプリの実装

アプリケーションに取り組む時間です!まず、PubNub と Pusher にアカウントがあることを確認してください。まず、両方のプラットフォームでアカウントを作成するプロセスを簡単に説明します。まだアカウントを作成していない場合は、手順に従ってください。

PubNub でアカウントを作成する

PubNub から始めて、Web サイトのホームページにアクセスし、右側の上部にあるボタンをクリックして、以下に示すように無料で試してください。

PubNub vs Pusher creating a realtime messaging app in React

登録ページが表示されるので、フォームを使用してアカウントを作成してください。

PubNub vs Pusher creating a realtime messaging app in React

アカウントが作成されたので、ダッシュボードにアクセスできるようになりました。メニューを使用して「キーセット」セクションに移動し、アプリとそのキーセットを見つけます。これは、まだアプリがない場合は作成する必要がある部分でもあります。

これで API キーが表示されるはずです。ユーザーとデータを追跡するために必要なので、プレゼンスと永続化のオプションがオンになっていることを確認してください。

PubNub vs Pusher creating a realtime messaging app in React

Pusherでアカウントを作成する

これで PubNub アカウントの作成は完了です。今度は Pusher アカウントに取り掛かりましょう。以前と同様に、Web サイトにアクセスし、ページの右上隅にあるサインアップ ボタンをクリックします。

PubNub vs Pusher creating a realtime messaging app in React

次の画面で、ここに表示されているようにフォームを使用してアカウントを作成します。

PubNub vs Pusher creating a realtime messaging app in React

チャネルを作成する必要があるため、ダッシュボード ページで管理ボタンを選択して作成します。

PubNub vs Pusher creating a realtime messaging app in React
次のページ (チャンネル画面) で、このスクリーンショットに示すように、アプリの作成ボタンを使用してアプリを作成します。

PubNub vs Pusher creating a realtime messaging app in React

これでフォームに進むことができます。この例でわかるように、構成はユースケースに合わせて調整する必要があります。

PubNub vs Pusher creating a realtime messaging app in React

その段階が完了すると、チャンネル ページはここのように表示されるはずです。
PubNub vs Pusher creating a realtime messaging app in React
サイドバー メニューにある [アプリ キー] をクリックすると、後で必要な API キーにアクセスできます。

PubNub vs Pusher creating a realtime messaging app in React

アカウントのセットアップ段階は完了しました。次のセクションでは、アプリのコードを開始します。最初のステップは、フォルダーなどを使用してプロジェクト アーキテクチャを作成することです。すべてのコマンドを手動で記述する必要がないように、コマンド ライン用のコピー アンド ペースト スクリプトを作成しました。まず、コンピューター上に realtime-chat-app という名前のプロジェクトを作成し、コマンド ラインを使用してその場所に移動します。

React アプリケーションのセットアップ

Next.js を使用してプロジェクトを作成し、シェル スクリプトを使用してプロジェクトをセットアップします。

まず、次のコマンドを実行して Next.js プロジェクトを作成します。

npx create-next-app client
ログイン後にコピー

このプロジェクトではこれらのオプションが必要なので、設定画面で Tailwind CSS と App Router を選択することが重要です。

ここにあるのは、ファイルとフォルダーを作成し、依存関係をインストールするためのシェル スクリプトです。同じフォルダー内で実行するだけで、自動的にクライアント フォルダーに移動されます。すでにクライアント フォルダーにいる場合は、スクリプトの最初の行を省略できます。

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 ..
ログイン後にコピー

ここでは多くのことが行われているので、このスクリプトが何をしているのか見てみましょう:

  • パッケージ、PubNub および Pusher パッケージを含むプロジェクトの依存関係をインストールします
  • API キーの環境変数ファイルを作成する
  • アプリ全体のファイル、フォルダー、コンポーネントを作成する
  • Pusher が API アクセスに必要とするバックエンド サーバーをセットアップする
  • ルーティングとロジックを目的としたサーバー ファイルの構築

この画面を見てください。これは、IDE でプロジェクトがどのように表示されるかを示しています:

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.

以上がReact でリアルタイム メッセージング アプリを作成する PubNub と Pusher の比較の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート