ساخت یک اپلیکیشن چت ساده با Node.js — از صفر تا صد
برای توسعه یک اپلیکیشن چت باید یک سیستم ارسال و دریافت همزمان دادهها را طراحی کنیم. انجام این کار به وسیله پایگاههای داده رابطهای و فراخوانیهای ایجکس (Ajax) ممکن نخواهد بود. البته به لطف فناوری وب سوکت (WebSocket) و کتابخانه Socket.io این کار به آسانی ممکن میشود. با مجله فرادرس همراه شوید تا مرحله به مرحله نسبت به ساخت چنین اپلیکیشنی اقدام کنیم.
فناوریهای مورد نیاز
در ادامه مجموعه فناوریهایی که در این اپلیکیشن استفاده میشوند را معرفی کردهایم.
WebSockets و Socket.io
WebSockets یک پروتکل است که امکان مبادله همگام دوسویه بین کلاینت و سرور را فراهم میسازد. در وب کلاسیک، یک کلاینت درخواستی به سرور ارسال میکند و سرور با بازگرداندن دادههایی به آن پاسخ میدهد. این سیستم مسئول یک اپلیکیشن چت است.
در WebSockets سرور همچنان میتواند دادهها را به کلاینت ارسال کند؛ اما کلاینت نیز میتواند چنین کاری را انجام دهد. یک WebSocket نوعی لوله ارتباطی است که از دو طرف باز است. Socket.io یک کتابخانه مبتنی بر این پروتکل است که امکان بهرهبرداری آسان از WebSockets را فراهم ساخته است.
مافیای جاوا اسکریپت
Node.js یک فناوری پشتیبانی شده از سوی جاوا اسکریپت است که از سوی سرور به وسیله PHP، روبی یا پایتون اجرا میشود. جاوا اسکریپت از رویدادها استفاده میکند. Node.js این خصوصیت را حفظ کرده است به طوری که امکان نوشتن کد ناهمگام در آن به سهولت فراهم شده است.
Node.js یک نرمافزار مدیریت بسته خاص برای خود دارد که نام آن npm است. این نرمافزار امکان نصب، بهروزرسانی و حذف بستهها را به آسانی میسر میکند. در این راهنما قصد داریم از express.js استفاده کنیم. express.js یک میکرو فریمورک وب مبتنی بر Node.js است.
راهاندازی محیط توسعه
قبل از هر چیز باید محیط توسعه خود را پیکربندی کنیم. نخستین کاری که باید در این زمینه انجام دهید، آغاز کردن npm است. به این منظور یک پنجره ترمینال جدید باز کنید، سپس یک ریپازیتوری جدید ایجاد کنید که شامل پروژه باشد، در نهایت به آن مراجعه کرده و npm را مقداردهی نمایید:
$ mkdir createSimpleApp $ cd createSimpleApp $ npm init
Npm از شما اطلاعاتی را میخواهد. اگر میخواهید این مرحله را رد کنید، میتوانید با زدن مکرر اینتر به انتها برسید. اینک اگر به پروژه خود نگاه کنید، یک فایل جدید در آن مشاهده میکنید که package.json نام دارد. این فایل همه وابستگیهای شما را در خود جای داده است.
بنابراین اکنون آماده هستیم که بستههای مورد نیاز خود را برای توسعه اپلیکیشن چت نصب کنیم. ما به این بستهها نیاز خواهیم داشت:
- Express: میکرو فریمورک وب اپلیکیشن برای node.js
- Nodemon: بستهای است که هر تغییری را شناسایی کرده و سرور ما را ریاستارت میکند. ما از آن به جای دستور کلاسیک node استفاده خواهیم کرد.
- ejs: یک موتور قالب برای سادهسازی تولید کد HTML.
- Soket.io: بسته مشهوری که به مدیریت WebSockets میپردازد.
نصب این موارد در محیط توسعه کار بسیار آسانی است:
$ npm install --save package_name
با استفاده از دستور فوق میتوانید هر 4 بسته مورد نظر را نصب کنید. در ادامه در فایل package.json میتوانید این خط را به کلید scripts خود اضافه کنید:
“start”: “nodemon app”
با استفاده از این خط، میتوانید اپلیکیشن را تنها با استفاده از یک دستور از nodemon اجرا نمایید:
$ npm run start
اینک محیط ما راهاندازی شده است و آماده توسعه اپلیکیشن خود هستیم.
اپلیکیشن چت
در این بخش از راهنما به توضیح موارد مرتبط با اپلیکیشن چت میپردازیم.
معماری اپلیکیشن
قبل از هر چیز باید فرایند توسعه اپلیکیشن را به دو بخش سرور و کلاینت تقسیم کنیم. ما برای ساخت اپلیکیشن و اجرا کردن آن به توسعه هر دو بخش میپردازیم.
سرور توسط node.js مدیریت خواهد شد تا همه جنبههای فنی اعم از اجرای بسته و وبسایت را فراهم کند. این کد از سوی کلاینت دیده نخواهد شد. بخش کلاینت روی رایانه کلاینت بارگذاری میشود و او میتواند به فایلها دسترسی داشته باشد. (html/css و js).
سمت سرور
ما باید فایل app.js را که سرور و همه بستهها را راهاندازی میکند ایجاد نماییم:
1const express = require('express')
2const app = express()
3
4
5//set the template engine ejs
6app.set('view engine', 'ejs')
7
8//middlewares
9app.use(express.static('public'))
10
11
12//routes
13app.get('/', (req, res) => {
14 res.send('Hello World')
15})
16
17//Listen on port 3000
18server = app.listen(3000)
قطعه کد فوق در واقع اپلیکیشن اکسپرس ما را مقداردهی اولیه میکند. اینک اگر به آدرس http://localhost:3000 مراجعه کنید یک پیام مناسب دریافت خواهید کرد. اکنون ما باید صرفاً socket.io را پیکربندی کنیم تا بتوانیم وارد دنیای WebSocket بشویم.
1//socket.io instantiation
2const io = require("socket.io")(server)
3
4//listen on every connection
5 io.on('connection', (socket) => {
6console.log('New user connected')
7})
در قطعه کد فوق شیء io امکان دسترسی به کتابخانه socket.io را در اختیار ما قرار میدهد. شیء io اکنون به هر اتصال به اپلیکیشن ما گوش میدهد. هر بار که یک کاربر جدید اتصال مییابد، پیام «New user connected» را در کنسول ما نشان میدهد. اگر تلاش کنید مرورگرتان را روی localhost بارگذاری مجدد کنید، هیچ اتفاقی نمیافتد، زیرا کد سمت کلاینت هنوز آماده نیست.
تا به اینجا socket.io تنها در سمت سرور نصب شده است. در ادامه ما همین فرایند را در سمت کلاینت نیز اجرا میکنیم.
سمت کلاینت
ما صرفاً باید یک خط کد را در فایل app.js تغییر دهیم. در واقع ما نمیخواهیم پیام «Hello World» را نمایش دهیم؛ بلکه میخواهیم یک پنجره واقعی با کادر گفتگو داشته باشیم که کاربر «نام کاربری/پیام» خود را در آن وارد کرده و ارسال کند. به این منظور باید هنگام دسترسی به ریشه «/» یک فایل html را رندر کنیم (که در این مورد فایل ejs خواهد بود).
بنابراین باید متد رندر را روی شیء res اعمال کنیم:
1//routes
2app.get('/', (req, res) => {
3 res.render('index')
4})
در سمت دیگر باید یک پوشه views ایجاد کنیم که دارای فایلی به نام index.ejs در خود است. فایل CSS نیز در یک پوشه به نام public خواهد بود:
اینک آدرس localhost:3000 روی localhost به صورت زیر است:
بدین ترتیب ما اینک قالب ابتدایی خود را داریم و باید socket.io را روی هر کلاینت که تلاش خواهد کرد به سرور ما وصل شود نصب کنیم. به این منظور باید کتابخانه socket.io را در سمت کلاینت ایمپورت کنیم:
1<script src=”https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
تنها روش برای کار با socket.io در یک فایل js. است. از این رو در انتهای بدنه فایل خود کد زیر را اضافه کنید:
1script src=”http://code.jquery.com/jquery-latest.min.js"></script>
2<script src=”chat.js”></script>
در ادامه یک فایل به نام chat.js در پوشه public ایجاد کنید. در این مرحله کافی است کد زیر را در آن وارد کنیم:
1$(function(){
2//make connection
3 var socket = io.connect('http://localhost:3000')
4});
همان طور که احتمالاً حدس میزنید وقتی کلاینت این فایل را بارگذاری کند، به طور خودکار متصل میشود و یک سوکت جدید ایجاد میکند. بنابراین وقتی صفحه را رفرش کنید، با یک پیام «New user connected» در ترمینال خود مواجه میشوید.
ارسال و دریافت دادهها
در ادامه دادههایی که باید ارسال و دریافت شوند را توضیح دادهایم.
Username
زمانی که یک کاربر به اپلیکیشن ما وصل میشود، برای او یک نام کاربری پیشفرض مانند «anonymous» تنظیم میکنیم. به این منظور باید به سمت سرور برویم (app.js) و یک کلید به سوکت خود اضافه کنیم. در عمل سوکت نشان میدهد که هر کلاینت به سرور ما وصل شده است.
1//listen on every connection
2io.on('connection', (socket) => {
3 console.log('New user connected')
4
5 //default username
6 socket.username = "Anonymous"
7
8 //listen on change_username
9 socket.on('change_username', (data) => {
10 socket.username = data.username
11 })
12})
ما همچنین به هر فراخوانی که به «change_username» صورت میگیرد، گوش میدهیم اگر پیامی به این رویداد ارسال شود، نام کاربری تغییر خواهد یافت.
در سمت کلاینت هدف ما این است که معکوس این کار را انجام دهیم. هر بار که دکمه change username کلیک شود، کلاینت یک رویداد با یک مقدار جدید ارسال خواهد کرد.
1$(function(){
2 //make connection
3 var socket = io.connect('http://localhost:3000')
4
5 //buttons and inputs
6 var message = $("#message")
7 var username = $("#username")
8 var send_message = $("#send_message")
9 var send_username = $("#send_username")
10 var chatroom = $("#chatroom")
11
12 //Emit a username
13 send_username.click(function(){
14 socket.emit('change_username', {username : username.val()})
15 })
16
17});
Message
در مورد پیامها نیز از همان مفهوم نام کاربری استفاده میکنیم. بدین ترتیب فایل chat.js به صورت زیر خواهد بود:
1$(function(){
2 //make connection
3 var socket = io.connect('http://localhost:3000')
4
5 //buttons and inputs
6 var message = $("#message")
7 var username = $("#username")
8 var send_message = $("#send_message")
9 var send_username = $("#send_username")
10 var chatroom = $("#chatroom")
11
12 //Emit message
13 send_message.click(function(){
14 socket.emit('new_message', {message : message.val()})
15 })
16
17 //Listen on new_message
18 socket.on("new_message", (data) => {
19 console.data('data');
20 chatroom.append("<p class='message'>" + data.username + ": " + data.message + "</p>")
21 })
22
23 //Emit a username
24 send_username.click(function(){
25 socket.emit('change_username', {username : username.val()})
26 })
27});
فایل app.js نیز اکنون به شکل زیر در آمده است:
1//listen on every connection
2io.on('connection', (socket) => {
3 console.log('New user connected')
4
5 //default username
6 socket.username = "Anonymous"
7
8 //listen on change_username
9 socket.on('change_username', (data) => {
10 socket.username = data.username
11 })
12
13 //listen on new_message
14 socket.on('new_message', (data) => {
15 //broadcast the new message
16 io.sockets.emit('new_message', {message : data.message, username : socket.username});
17 })
18})
در مورد رویداد new_message میبینید که ما مشخصه sockets را برای io فراخوانی میکنیم. این مشخصه همه سوکتهای اتصال یافته را نشان میدهد. از این رو این خط کد در عمل یک پیام را به همه سوکتها ارسال میکند. ما میخواهیم یک پیام را که از سوی کاربر به همه ارسال شده است (و خودش را نیز شامل میشود) نمایش دهیم.
درتصویر زیر شکل نهایی اپلیکیشن چت را مشاهده میکنید:
بهبودهای جزئی
ما میتوانیم بهبودهای جزئی در اپلیکیشن خود ایجاد کنیم تا واقعگرایانهتر شود. بدین منظور پیام «XXX is typing…» را اضافه میکنیم.
انجام این کار بسیار آسان است. پس از افزودن یک عنصر HTML در فایل index.ejs باید یک شنونده رویداد jQuery برای تایپ کردن اضافه کنیم و یک رویداد سوکت به نام typing را به سرور بفرستیم:
1 //Emit typing
2 message.bind("keypress", () => {
3 socket.emit('typing')
4 })
5
6 //Listen on typing
7 socket.on('typing', (data) => {
8 feedback.html("<p><i>" + data.username + " is typing a message..." + "</i></p>")
9})
در سمت دیگر منتظر شنیدن رویداد typing میمانیم و یک پیام منتشر میکنیم. منظور از انتشار (broadcast)، ارسال یک پیام به همه افراد به جز سوکتی است که آن رویداد را آغاز کرده است:
1 //listen on typing
2 socket.on('typing', (data) => {
3 socket.broadcast.emit('typing', {username : socket.username})
4})
سخن پایانی
اینک میبینید که کدنویسی این اپلیکیشن بسیار ساده است. شاید تا پیش از آن که با WebSockets و socket.io آشنا شوید، فکر میکردید که کدنویسی این نوع اپلیکیشن بسیار دشوار باشد؛ اما با مطالعه این نوشته دیدیم که تا چه حد نوشتن چنین اپلیکیشنی میتواند ساده باشد. برای بهبود این اپلیکیشن میتوان موارد زیر را نیز به آن افزود:
- سیستم ثبتنام با امکان چتهای فرد به فرد
- نگهداری سابقه همه گفتگوها
- نشان دادن وضعیت آنلاین/آفلاین
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای طراحی و توسعه پروژه های وب
- مجموعه آموزش های پروژه محور برنامه نویسی
- ساخت وب اپلیکیشن RESTful با استفاده از Express ،Node.js و MongoDB – از صفر تا صد
- Node.js چیست و چه نقشی در توسعه وب دارد؟ — به زبان ساده
- Node.js و ابزارها و تکنیکها برای ساخت سرورهای قدرتمند و سریع
- آموزش راه اندازی و اجرای Express ،Node.js و MongoDB — راهنمای گام به گام
- آموزش وب سوکت | راهنمای رایگان و جامع — به زبان ساده
==
ببخشید خیلی گنگ توضیح دادین من که با ترمینال خیلی کار نکردم نمی دونم از چه برنامه ای باید ترمینال رو براز کنم .
vscode یا …
؟؟؟
شما به احتمال زیاد این مطلب رو از خود socket.io ترجمه کردید اگه حداقل تصاویرش رو هم قرار میدادی و کد هارو درهم نمینوشتید جذابیت بیشتری داشت