TypeScriptリアルタイムアプリケーション:WebSocket、Node、Angularを使用したチャットの開発

最近、TypeScriptのみを使用して簡単なチャットを作成しました。 このプロジェクトの主な目標は、クライアントとサーバーの両方でこの言語の使用を実証するアプリケーションを作成することでした。 チャットのクライアント部分は、Angularの最新バージョンに基づいています。 サーバーはNode.jsに基づいています。 それらの間の相互作用は、WebSocketプロトコルを使用して編成されます。



この記事では、問題のチャットをゼロから作成する方法を学びます。 ちなみに、ここで彼との仕事はどのように見えるかです。









TypeScriptチャット



リアルタイムアプリケーションについて



ウィキペディアのこの定義によると、リアルタイムアプリケーションを使用すると、情報のソースを定期的に調査する必要なく、関心のあるエンティティが公開後すぐに情報を受け取ることができます。 したがって、この種のアプリケーションは、特定のアクションが即座に、遅延なく発生するという感覚をユーザーに与える必要があります。



WebSocketプロトコル



WebSocketは、双方向データチャネルを整理できるプロトコルです。 私たちの場合、これは、ブラウザーとWebサーバーがリアルタイムで通信できることを意味し、それらの間にオープンな接続がある場合、互いにメッセージを送信します。









WebSocket通信



アプリケーション構造



アプリケーションのクライアント部分とサーバー部分に関連するコードを別々のフォルダーに配置します。 完成したアプリケーションの構造を以下に示します。 プロジェクトの主要なファイルについて話すときは、以下の詳細を検討します。



server/ |- src/ |- package.json |- tsconfig.json |- gulpfile.js client/ |- src/ |- package.json |- tsconfig.json |- .angular-cli.json
      
      





WebSocket実装の選択



WebSocketプロトコルは仕様であるため 、いくつかの実用的な実装を見つけることができます。 ここでは、 JavaScript 、TypeScript、またはその他のプログラミング言語を使用できます。



この場合、 Socket.IOライブラリを使用します。 これは、リアルタイムのデータ交換機能を実装する最も高速で信頼性の高いライブラリの1つです。



サーバーでTypeScriptを使用する理由



TypeScriptはプログラマに優れた機能を提供し、開発チームは言語を最新の状態に保ちます。 さらに、タイピングを使用すると、通常のJSを使用する場合と比較して、コードのエラーの数を減らすことができます。 私にとって、これらの理由は、サーバーでTSを使用するのに十分です。



サーバーアプリケーションの初期化



package.json



ファイルを作成し 、次の依存関係をインストールします。



 npm install --save express socket.io @types/express @types/socket.io
      
      





さらに、 gulp



typescript



をプロジェクトに統合するために、いくつかの開発依存関係をインストールする必要があります。これらはすべて、完成したプロジェクトの作成とアセンブリ中に役立ちます。



 npm install --save-dev typescript gulp gulp-typescript
      
      





TypeScriptコンパイラのセットアップ



tsconfig.json



ファイルを作成し、 tsconfig.json



ファイルを入れます。



 { "files": [   "src/*.ts",   "src/model/*.ts" ], "compilerOptions": {   "target": "es5" } }
      
      





データモデルの説明



静的型付けの機能を使用して、小さなデータモデルを作成します。



 export class User {   constructor(private name: string) {} } export class Message {   constructor(private from: User, private content: string) {} } export class ChatMessage extends Message{   constructor(from: User, content: string) {       super(from, content);   } }
      
      





server/src



ディレクトリ構造を見てください:



 server/ |- src/  |- model/     |- message.model.ts     |- user.model.ts  |- index.ts  |- server.ts |- package.json |- tsconfig.json |- gulpfile.js
      
      





チャットサーバーの実装



server



ディレクトリのメインファイルはindex.ts



およびchat-server.ts



です。 1つ目はChatServer



アプリケーションの作成とエクスポートを可能にし、2つ目はexpressおよびSocket.IO構成を含みます:



index.js



ファイルのコードは次のとおりです。



 import { ChatServer } from './chat-server'; let app = new ChatServer().getApp(); export { app };
      
      





chat-server.ts



次のchat-server.ts







 import { createServer, Server } from 'http'; import * as express from 'express'; import * as socketIo from 'socket.io'; import { Message } from './model'; export class ChatServer {   public static readonly PORT:number = 8080;   private app: express.Application;   private server: Server;   private io: SocketIO.Server;   private port: string | number;   constructor() {       this.createApp();       this.config();       this.createServer();       this.sockets();       this.listen();   }   private createApp(): void {       this.app = express();   }   private createServer(): void {       this.server = createServer(this.app);   }   private config(): void {       this.port = process.env.PORT || ChatServer.PORT;   }   private sockets(): void {       this.io = socketIo(this.server);   }   private listen(): void {       this.server.listen(this.port, () => {           console.log('Running server on port %s', this.port);       });       this.io.on('connect', (socket: any) => {           console.log('Connected client on port %s.', this.port);           socket.on('message', (m: Message) => {               console.log('[server](message): %s', JSON.stringify(m));               this.io.emit('message', m);           });           socket.on('disconnect', () => {               console.log('Client disconnected');           });       });   }   public getApp(): express.Application {       return this.app;   } }
      
      





サーバークラス



上記のコードは、次のクラスとそれらの関係を提供します。









サーバークラス図



サーバーを構築して起動する



Node.jsのベースとなっているV8エンジンに必要なJavaScriptファイルを取得するために、 gulpfile.js



ファイルにbuild



タスクを追加します。



 var gulp = require("gulp"); var ts = require("gulp-typescript"); var tsProject = ts.createProject("tsconfig.json"); gulp.task("build", function () {   return tsProject.src()       .pipe(tsProject())       .js.pipe(gulp.dest("./dist")); });
      
      





ご覧のとおり、ビルドプロセスの出力(JSファイル)はdist



ディレクトリにあります。 アセンブリを完了するには、次のコマンドが必要です。



 gulp build
      
      





サーバーを起動するには、次のコマンドを使用する必要があります。



 node dist/index.js
      
      





チャットクライアント開発



Angular CLIを使用して、クライアント用のフォルダーを作成します。



 ng new typescript-chat-client --routing --prefix tcc --skip-install
      
      





プロジェクトの依存関係をインストールします。 ここでnpm install



コマンドを実行できますが、このステップではYarnを使用することを好みます。



 cd typescript-chat-client yarn install
      
      





角材コンポーネントセットをプロジェクトに追加する



Angular CLIを使用して作成されたプロジェクトで設定されたAngular Materialコンポーネントを活用するには、material.angular.ioの最新のマニュアルを参照し、それに応じて行動してください。



Angularプロジェクトの構造に関する推奨事項に従って、 shared



モジュールとmaterial



モジュールを作成します。



 client/ |- src/  |- app/     |- chat/     |- shared/        |- material/           |- material.module.ts        |- shared.module.ts     |-app.module.ts
      
      





コマンドラインからこれを行うことができます:



 ng generate module shared --module app ng generate module shared/material --module shared
      
      





これらのモジュール間の関係を評価するには、ファイルapp.module.ts



およびshared.module.ts



分析します。



ExpressとSocket.IOを接続する



次に、 express



およびsocket.io



モジュールをクライアントアプリケーションに接続する必要があります。



 npm install express socket.io --save
      
      





チャットモジュールとコンポーネント



チャットコンポーネントを作成する前に、新しいモジュールを作成します。



 ng generate module chat --module app
      
      





次に、このモジュールにコンポーネントを追加します。



 ng generate component chat --module chat
      
      





Webソケットと独自のモデルを使用するには、別のshared



フォルダーを作成shared



ます。 今回は、 chat



ディレクトリ内で:



 ng generate service chat/shared/services/socket --module chat ng generate class chat/shared/model/user ng generate class chat/shared/model/message
      
      





結果は次の構造になります。



 client/ |- src/  |- app/     |- chat/        |- shared/          |- model/             |- user.ts             |- message.ts          |- services/             |- socket.service.ts     |- shared/     |-app.module.ts
      
      





観察されたオブジェクトとWebソケット



AngularアプリケーションはRxJSをサポートしているため、監視可能なオブジェクトを使用してSocket.IOイベントを操作できます。 したがって、 socket.services.ts



ファイルは次のようになります。



 import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { Observer } from 'rxjs/Observer'; import { Message } from '../model/message'; import { Event } from '../model/event'; import * as socketIo from 'socket.io-client'; const SERVER_URL = 'http://localhost:8080'; @Injectable() export class SocketService {   private socket;   public initSocket(): void {       this.socket = socketIo(SERVER_URL);   }   public send(message: Message): void {       this.socket.emit('message', message);   }   public onMessage(): Observable<Message> {       return new Observable<Message>(observer => {           this.socket.on('message', (data: Message) => observer.next(data));       });   }   public onEvent(event: Event): Observable<any> {       return new Observable<Event>(observer => {           this.socket.on(event, () => observer.next());       });   } }
      
      





これで、サーバーからのメッセージに応答する準備ができたので、 chat.component.ts



ファイルを考慮します(ここでは、マテリアルイベントとユーザーインターフェイスイベントに関するコードは省略されています)。



 import { Component, OnInit } from '@angular/core'; import { Action } from './shared/model/action'; import { Event } from './shared/model/event'; import { Message } from './shared/model/message'; import { User } from './shared/model/user'; import { SocketService } from './shared/services/socket.service'; @Component({ selector: 'tcc-chat', templateUrl: './chat.component.html', styleUrls: ['./chat.component.css'] }) export class ChatComponent implements OnInit { action = Action; user: User; messages: Message[] = []; messageContent: string; ioConnection: any; constructor(private socketService: SocketService) { } ngOnInit(): void {   this.initIoConnection(); } private initIoConnection(): void {   this.socketService.initSocket();   this.ioConnection = this.socketService.onMessage()     .subscribe((message: Message) => {       this.messages.push(message);     });   this.socketService.onEvent(Event.CONNECT)     .subscribe(() => {       console.log('connected');     });       this.socketService.onEvent(Event.DISCONNECT)     .subscribe(() => {       console.log('disconnected');     }); } public sendMessage(message: string): void {   if (!message) {     return;   }   this.socketService.send({     from: this.user,     content: message   });   this.messageContent = null; } public sendNotification(params: any, action: Action): void {   let message: Message;   if (action === Action.JOINED) {     message = {       from: this.user,       action: action     }   } else if (action === Action.RENAME) {     message = {       action: action,       content: {         username: this.user.name,         previousUsername: params.previousUsername       }     };   }   this.socketService.send(message); } }
      
      





ChatComponent



初期化されるとすぐに、 ChatComponent



されたSocketService



オブジェクトをサブスクライブして、接続関連のイベントまたは着信メッセージを受信します。



sendMessage



sendNotification



sendNotification



は、それぞれ同じサービスを介してメッセージと通知を送信します。 通知は、新しいユーザーがチャットに参加したことをシステムに通知し、チャット参加者の名前を変更するために使用されます。



まとめ



この資料から、TypeScriptを使用してリアルタイムアプリケーションを作成する方法を学びました。TSはクライアントとサーバーの両方で使用され、WebSockets、Node.js、Angularなどのテクノロジーが関与するチャットです。 プロジェクトのソースコードはこちらにあります 。 そして、 ここに実際のチャットがあります(体験するには、ブラウザでこのページのタブをいくつか開いてください)。



親愛なる読者! TypeScriptを使用してサーバーアプリケーションを開発していますか?






All Articles