Dalam tutorial ini, saya akan menunjukkan cara mengimplementasikan aplikasi chat real-time dengan Node.js, Socket.IO dan MongoDB, dan kemudian kita akan men-deploy aplikasi ini ke Modulus bersama-sama.
Pertama-tama, izinkan saya menunjukkan kepada Anda tampilan akhir dari aplikasi yang akan kita miliki di akhir artikel.
Node.js akan menjadi inti dari aplikasi, dengan Express sebagai MVC, MongoDB untuk database, dan Socket.IO untuk komunikasi real-time. Setelah selesai, kami akan menyebarkan aplikasi kami ke Modulus. Bagian MongoDB sebenarnya ada di dalam Modulus.
1. Skenario
- John ingin menggunakan aplikasi kita, dan membukanya di browser.
- Pada halaman pertama, dia memilih nama panggilan yang digunakan saat mengobrol, dan masuk untuk mengobrol.
- Di area teks dia menulis sesuatu dan menekan Enter.
- Teks dikirim ke layanan RESTful (Express) dan teks ini ditulis ke MongoDB.
- Sebelum menulis di MongoDB, teks yang sama akan disiarkan ke pengguna yang saat ini masuk ke aplikasi obrolan.
Seperti yang Anda lihat, ini adalah aplikasi yang sangat sederhana, tetapi mencakup hampir semua hal untuk aplikasi web. Tidak ada sistem saluran dalam aplikasi ini, tetapi Anda dapat menyalin kode sumber dan menerapkan modul saluran untuk latihan.
2. Desain Proyek Dari Awal
Saya akan mencoba menjelaskan bagian-bagian kecil dari proyek terlebih dahulu dan menggabungkannya di akhir. Saya akan mulai dari ujung belakang ke ujung depan. Jadi, mari kita mulai dengan objek domain (model MongoDB).
2.1. Model
Untuk abstraksi database, kita akan menggunakan Mongoose. Dalam proyek ini, kami hanya memiliki satu model yang disebut Message
. Model pesan ini hanya berisi text
, createDate
, dan author
User
, karena kami tidak akan sepenuhnya menerapkan sistem registrasi/login pengguna. Akan ada halaman penyedia nama panggilan sederhana, dan nama panggilan ini akan disimpan ke cookie. Ini akan digunakan dalam Message
model sebagai teks di author
bidang. Anda dapat melihat contoh model JSON di bawah ini:
{ text: "Hi, is there any Full Stack Developer here?" author: "john_the_full_stack", createDate: "2015.05.15" }
Untuk membuat dokumen seperti ini, Anda dapat mengimplementasikan model dengan menggunakan fungsi Mongoose di bawah ini:
var mongoose = require('mongoose') var Message = new mongoose.Schema({ author: String, message: String, createDate: { type: Date, default: Date.now } }); mongoose.model('Message', Message)
Cukup impor modul Mongoose, tentukan model Anda dengan bidang dan atribut bidangnya dalam format JSON, dan buat model dengan nama Message
. Model ini akan disertakan di halaman yang ingin Anda gunakan.
Mungkin Anda memiliki pertanyaan tentang mengapa kami menyimpan pesan di database, padahal kami sudah menyiarkan pesan ini ke pengguna di saluran yang sama. Memang benar bahwa Anda tidak harus menyimpan pesan obrolan, tetapi saya hanya ingin menjelaskan lapisan integrasi basis data. Bagaimanapun, kami akan menggunakan model ini dalam proyek kami di dalam pengontrol. Pengendali?
2.2. Pengontrol
Seperti yang saya katakan sebelumnya, kami akan menggunakan Express untuk bagian MVC. Dan C
di sini adalah singkatan dari Controller
. Untuk proyek kami, hanya akan ada dua titik akhir untuk pengiriman pesan. Salah satunya adalah untuk memuat pesan obrolan terbaru, dan yang kedua adalah untuk menangani pesan obrolan yang dikirim untuk disimpan dalam database, dan kemudian disiarkan ke saluran.
..... app.get('/chat', function(req, res){ res.sendFile(__dirname + '/index.html'); }); app.get('/login', function(req, res){ res.sendFile(__dirname + '/login.html'); }); app.post('/messages', function(req, res, next) { var message = req.body.message; var author = req.body.author; var messageModel = new Message(); messageModel.author = author; messageModel.message = message; messageModel.save(function (err, result) { if (!err) { Message.find({}).sort('-createDate').limit(5).exec(function(err, messages) { io.emit("message", messages); }); res.send("Message Sent!"); } else { res.send("Technical error occurred!"); } }); }); app.get('/messages', function(req, res, next) { Message.find({}).sort('-createDate').limit(5).exec(function(err, messages) { res.json(messages); }); }); .....
Kontroler pertama dan kedua hanya untuk menyajikan file HTML statis untuk halaman chat dan login. Yang ketiga adalah untuk menangani permintaan posting ke /messages
titik akhir untuk membuat pesan baru. Di pengontrol ini, pertama-tama badan permintaan dikonversi ke model Pesan, lalu model ini disimpan ke database dengan menggunakan fungsi Mongoose save
.
Saya tidak akan terlalu mendalami Mongoose—Anda dapat melihat dokumentasi untuk detail lebih lanjut. Anda dapat memberikan fungsi panggilan balik untuk fungsi simpan untuk memeriksa apakah ada masalah atau tidak. Jika berhasil, kami telah mengambil lima catatan terakhir yang diurutkan dalam urutan menurun menurut createDate
, dan telah menyiarkan lima pesan ke klien di saluran.
Oke, kita telah menyelesaikan MC
. Mari beralih ke View
bagian.
2.3. Lihat
Secara umum, mesin template seperti Jade, EJS, Handlebars, dll., dapat digunakan dalam Express. Namun, kami hanya memiliki satu halaman, dan itu adalah pesan obrolan, jadi saya akan menyajikan ini secara statis. Sebenarnya, seperti yang saya katakan di atas, ada dua pengontrol lagi untuk melayani halaman HTML statis ini. Anda dapat melihat berikut ini untuk menyajikan halaman HTML statis.
app.get('/chat', function(req, res){ res.sendFile(__dirname + '/index.html'); }); app.get('/login', function(req, res){ res.sendFile(__dirname + '/login.html'); });
Endpoint ini hanya melayani index.html dan login.html dengan menggunakan res.sendFile
. Keduanya index.html dan login.html berada di folder yang sama dengan server.js, itulah sebabnya kami menggunakan __dirname
sebelum nama file HTML.
2.4. Ujung Depan
Di halaman depan, saya telah menggunakan Bootstrap dan tidak perlu menjelaskan bagaimana saya berhasil melakukannya. Sederhananya, saya telah mengikat fungsi ke kotak teks, dan setiap kali Anda menekan tombol Enter kunci atau Kirim tombol, pesan akan dikirim ke layanan back-end.
Halaman ini juga memiliki file js Socket.IO yang diperlukan untuk mendengarkan saluran yang disebut message
. Modul Socket.IO sudah diimpor di bagian belakang, dan saat Anda menggunakan modul ini di sisi server, modul ini secara otomatis menambahkan titik akhir untuk menyajikan file js Socket.IO, tetapi kami menggunakan yang disajikan dari cdn <script src="//cdn.socket.io/socket.io-1.3.5.js"></script>
. Setiap kali ada pesan baru masuk ke saluran ini, secara otomatis akan terdeteksi dan daftar pesan akan disegarkan dengan lima pesan terakhir.
<script> var socket = io(); socket.on("message", function (messages) { refreshMessages(messages); }); function refreshMessages(messages) { $(".media-list").html(""); $.each(messages.reverse(), function(i, message) { $(".media-list").append('<li class="media"><div class="media-body"><div class="media"><div class="media-body">' + message.message + '<br/><small class="text-muted">' + message.author + ' | ' + message.createDate + '</small><hr/></div></div></div></li>'); }); } $(function(){ if (typeof $.cookie("realtime-chat-nickname") === 'undefined') { window.location = "/login" } else { $.get("/messages", function (messages) { refreshMessages(messages) }); $("#sendMessage").on("click", function() { sendMessage() }); $('#messageText').keyup(function(e){ if(e.keyCode == 13) { sendMessage(); } }); } function sendMessage() { $container = $('.media-list'); $container[0].scrollTop = $container[0].scrollHeight; var message = $("#messageText").val(); var author = $.cookie("realtime-chat-nickname"); $.post( "/messages", {message: message, author: author}, function( data ) { $("#messageText").val("") }); $container.animate({ scrollTop: $container[0].scrollHeight }, "slow"); } }) </script>
Ada satu cek lagi dalam kode di atas:bagian cookie. Jika Anda belum memilih nama panggilan apa pun untuk mengobrol, itu berarti cookie tidak disetel untuk nama panggilan tersebut, dan Anda akan secara otomatis diarahkan ke halaman login.
Jika tidak, lima pesan terakhir akan diambil dengan panggilan Ajax sederhana ke /messages
titik akhir. Dengan cara yang sama, setiap kali Anda mengeklik Kirim atau tekan tombol Enter kunci, pesan teks akan diambil dari kotak teks, dan nama panggilan akan diambil dari cookie, dan nilai-nilai itu akan dikirim ke server dengan permintaan posting. Tidak ada pemeriksaan ketat untuk nama panggilan di sini, karena saya ingin fokus pada bagian waktu nyata, bukan bagian otentikasi pengguna.
Seperti yang Anda lihat, keseluruhan struktur proyek ini sangat sederhana. Mari datang ke bagian penyebaran. Seperti yang saya katakan sebelumnya, kami akan menggunakan Modulus, salah satu PaaS terbaik untuk menerapkan, menskalakan, dan memantau aplikasi Anda dalam bahasa pilihan Anda.
3. Penerapan
3.1. Prasyarat
Hal pertama yang muncul di benak saya adalah menunjukkan kepada Anda cara menerapkan, tetapi untuk penerapan yang sukses, kami memerlukan database yang berfungsi. Mari kita lihat cara membuat database di Modulus dan kemudian melakukan penyebaran.
Buka dasbor Modulus setelah membuat akun. Klik Database menu di sebelah kiri, dan klik Buat Database.
Isi kolom yang diperlukan dalam formulir popup seperti di bawah ini.
Saat Anda mengisi bidang yang wajib diisi dan mengeklik Buat, itu akan membuat database MongoDB untuk Anda, dan Anda akan melihat URL database Anda di layar. Kami akan menggunakan MONGO URI , jadi salin URI itu.
Dalam proyek kami, URI Mongo diambil dari variabel lingkungan MONGO_URI
, dan Anda perlu mengatur variabel lingkungan itu di dasbor. Buka dasbor, klik Proyek menu, pilih proyek Anda dalam daftar, dan klik Administrasi di menu sebelah kiri. Di halaman ini, Anda akan melihat bagian variabel lingkungan saat Anda menggulir halaman ke bawah, seperti yang ditunjukkan di bawah ini.
Anda dapat menerapkan ke Modulus dengan dua cara:
- mengunggah file ZIP proyek dengan menggunakan dasbor
- penerapan dari baris perintah dengan menggunakan Modulus CLI
Saya akan melanjutkan dengan opsi baris perintah, karena yang lain mudah dilakukan. Pertama-tama, instal Modulus CLI:
npm install -g modulus
Buka folder proyek Anda dan lakukan perintah berikut untuk masuk ke Modulus.
modulus login
Ketika Anda melakukan perintah di atas, Anda akan diminta untuk memasukkan nama pengguna dan kata sandi:
Jika Anda telah membuat akun dengan menggunakan GitHub, Anda dapat menggunakan --github
pilihan.
modulus login --github
Sekarang Anda sudah masuk ke Modulus, dan saatnya membuat proyek. Gunakan perintah berikut untuk membuat proyek:
modulus project create "Realtime Chat"
Saat Anda menjalankan fungsi ini, Anda akan ditanya tentang runtime. Pilih opsi pertama, yaitu Node.js, dan kedua Anda akan ditanya ukuran servo, dan Anda dapat menyimpannya sebagai default.
Kami telah membuat proyek, dan kali ini kami akan menyebarkan proyek kami saat ini ke Modulus. Jalankan perintah berikut untuk mengirim proyek saat ini ke Obrolan Waktu Nyata proyek di sisi Modulus.
modulus deploy
Ini akan menyebarkan proyek Anda dan Anda akan mendapatkan URL proyek yang sedang berjalan di akhir pesan penerapan yang berhasil:
Realtime Chat running at realtime-chat-46792.onmodulus.net
Seperti yang Anda lihat, penerapan ke Modulus sangat mudah!
Modulus CLI memiliki perintah yang sangat membantu untuk digunakan selama penerapan proyek Anda atau saat runtime. Misalnya, untuk mengekor log proyek yang sedang berjalan, Anda dapat menggunakan modulus project logs tail
, untuk membuat database MongoDB gunakan modulus mongo create <db-name>
, untuk mengatur variabel lingkungan gunakan modulus env set <key> <value>
, dll. Anda dapat melihat daftar lengkap perintah dengan menggunakan bantuan Modulus.