{"id":362080,"date":"2024-05-21T01:27:20","date_gmt":"2024-05-21T01:27:20","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=362080"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=362080","title":{"rendered":"<span>\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0447\u0430\u0442\u0430 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e React, Node, Socket.io \u0438 HarperDB<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041e\u0431\u044b\u0447\u043d\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u041d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Socket.io, \u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043c\u043e\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u0445, \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u0435\u0434\u0448\u0438\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438.<\/p>\n<p>\u041d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u0434\u0432\u0443\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446.<\/p>\n<p>\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0432\u0445\u043e\u0434\u0430 \u0432 \u0447\u0430\u0442:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/bfb\/b82\/80b\/bfbb8280bd833d17421c5b0fe386889f.jpeg\" alt=\"How our app home page will look: a form with username input, select room dropdown and Join Room button\" title=\"\u041a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f: \u0444\u043e\u0440\u043c\u0430 \u0441 \u0432\u0432\u043e\u0434\u043e\u043c \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u044b\u0431\u043e\u0440\u0430 \u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0438 \u043a\u043d\u043e\u043f\u043a\u0430 Join Room\" width=\"475\" height=\"468\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/bfb\/b82\/80b\/bfbb8280bd833d17421c5b0fe386889f.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u041a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f: \u0444\u043e\u0440\u043c\u0430 \u0441 \u0432\u0432\u043e\u0434\u043e\u043c \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u044b\u0431\u043e\u0440\u0430 \u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0438 \u043a\u043d\u043e\u043f\u043a\u0430 Join Room<\/figcaption><\/div>\n<\/figure>\n<p>\u0418 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0441\u0430\u043c\u043e\u0433\u043e \u0447\u0430\u0442\u0430:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/a06\/058\/324\/a06058324533a73638bbdb333bd79e80.jpeg\" alt=\"The finished chat page\" title=\"\u0413\u043e\u0442\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0447\u0430\u0442\u0430\" width=\"1216\" height=\"678\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a06\/058\/324\/a06058324533a73638bbdb333bd79e80.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0413\u043e\u0442\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0447\u0430\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u043e\u0442 \u0447\u0442\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p><strong>Frontend<\/strong>:\u00a0<a href=\"https:\/\/reactjs.org\/docs\/create-a-new-react-app.html\"><u>React<\/u><\/a>\u00a0(\u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a JavaScript \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439)<\/p>\n<\/li>\n<li>\n<p><strong>\u0411\u044d\u043a\u044d\u043d\u0434<\/strong>:\u00a0<a href=\"https:\/\/nodejs.org\/en\/\"><u>Node<\/u><\/a>\u00a0\u0438\u00a0<a href=\"https:\/\/expressjs.com\/\"><u>Express<\/u><\/a>\u00a0(Express \u2014 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a NodeJS, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043b\u0435\u0433\u043a\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c API \u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u044b)<\/p>\n<\/li>\n<li>\n<p><strong>\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445:<\/strong>\u00a0<a href=\"https:\/\/harperdb.io\/\"><u>HarperDB<\/u><\/a>\u00a0(\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e SQL \u0438\u043b\u0438 NoSQL. HarperDB \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 API, \u0447\u0442\u043e \u0438\u0437\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0441 \u043e\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0438\u0441\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0431\u044d\u043a\u0435\u043d\u0434\u0430)<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u044f \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/strong>:\u00a0<a href=\"https:\/\/socket.io\/docs\/v3\/\"><u>Socket.io<\/u><\/a>\u00a0(\u0441\u043c. \u043d\u0438\u0436\u0435).<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/DoableDanny\/Realtime-chat-app-with-rooms\"><u>\u0412\u043e\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434<\/u><\/a>\u00a0(\u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u043c\u0443 \u0437\u0432\u0435\u0437\u0434\u0443).<\/p>\n<h2>\u041e\u0433\u043b\u0430\u0432\u043b\u0435\u043d\u0438\u0435<\/h2>\n<ol>\n<li>\n<p><a href=\"#id1\">\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 Socket.io?<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id2\">\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id3\">\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 &#171;Join a room&#187;<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id4\">\u041a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id5\">\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0439 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0439 Socket.io \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id6\">\u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0432 Socket.io<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id7\">\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0447\u0430\u0442\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id8\">\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 (B)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id9\">\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0445\u0435\u043c\u0443 \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0432 HarperDB<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id10\">\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Send Message (C)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id11\">\u041a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f HarperDB<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id12\">\u041a\u0430\u043a \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Socket.io<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id13\">\u041a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438\u0437 HarperDB<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id14\">\u041a\u0430\u043a \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 100 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id15\">\u041a\u0430\u043a \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u043a\u043e\u043c\u043d\u0430\u0442\u0443 \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 (A)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id16\">\u041a\u0430\u043a \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u0437 \u043a\u043e\u043c\u043d\u0430\u0442\u044b Socket.io<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id17\">\u041a\u0430\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f disconnect<\/a><\/p>\n<\/li>\n<\/ol>\n<hr\/>\n<p><a class=\"anchor\" name=\"id1\" id=\"id1\"><\/a><\/p>\n<h2>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 Socket.IO?<\/h2>\n<p>Socket.IO \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u044f.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0432\u044b \u0438\u0433\u0440\u0430\u0435\u0442\u0435 \u0432 \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0443\u044e \u0438\u0433\u0440\u0443, \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u0441\u0442\u0430\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u0432\u0430\u0448 \u00ab\u0434\u0440\u0443\u0433\u00bb \u0437\u0430\u0431\u044c\u0435\u0442 \u0432\u0430\u043c \u044d\u0444\u0444\u0435\u043a\u0442\u043d\u044b\u0439 \u0433\u043e\u043b.<\/p>\n<p>\u0421 Socket.IO \u0432\u044b \u0431\u044b \u043f\u043e\u0447\u0442\u0438 \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e \u0443\u0437\u043d\u0430\u043b\u0438 \u043e \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u043c \u0433\u043e\u043b\u0435.<\/p>\n<p>\u0411\u0435\u0437 Socket.IO \u043a\u043b\u0438\u0435\u043d\u0442\u0443, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e AJAX \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043b\u0438\u0435\u043d\u0442 \u043c\u043e\u0433 \u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c JavaScript, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043a\u0430\u0436\u0434\u044b\u0435 5 \u0441\u0435\u043a\u0443\u043d\u0434.<\/p>\n<p>\u0421 Socket.IO \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e AJAX \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u043b\u0438 \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043a\u043b\u0438\u0435\u043d\u0442\u0443, \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0435\u0435. \u042d\u0442\u043e \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u043b\u0443\u0447\u0448\u0435.\u00a0<\/p>\n<p>\u0418\u0442\u0430\u043a, Socket.IO \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043b\u0435\u0433\u043a\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u0447\u0430\u0442-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0438\u0433\u0440\u044b.<\/p>\n<p><a class=\"anchor\" name=\"id2\" id=\"id2\"><\/a><\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h2>\n<h4>1.\u00a0\u041a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0430\u043f\u043a\u0438<\/h4>\n<p>\u041d\u0430\u0447\u043d\u0438\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0432 \u0432\u0430\u0448\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u043c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 (\u0443 \u043c\u0435\u043d\u044f \u044d\u0442\u043e VS Code) \u0438 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0432 \u043a\u043e\u0440\u043d\u0435 \u0434\u0432\u0435 \u043f\u0430\u043f\u043a\u0438 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f\u043c\u0438 client \u0438 server.<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/906\/782\/f8d\/906782f8d9a0716f9e510ab43051731e.jpeg\" alt=\"Realtime chat app folder structure\" title=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0430\u043f\u043e\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0447\u0430\u0442\u0430 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438\" width=\"371\" height=\"106\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/906\/782\/f8d\/906782f8d9a0716f9e510ab43051731e.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0430\u043f\u043e\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0447\u0430\u0442\u0430 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434 React-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432 \u043f\u0430\u043f\u043a\u0435 client, \u0430 \u0431\u044d\u043a\u0435\u043d\u0434 Node\/Express \u2014 \u0432 \u043f\u0430\u043f\u043a\u0435 server.<\/p>\n<h4>2. \u041a\u0430\u043a \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430<\/h4>\n<p>\u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b \u0432 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (\u0432 VS Code \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u043d\u0430\u0436\u0430\u0432 Ctrl+&#8217; \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0439\u0434\u044f \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b -> \u043d\u043e\u0432\u044b\u0439 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b).<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c React \u0432 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0443\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e:<\/p>\n<pre><code>$ npx create-react-app client<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 React \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u043f\u0430\u043f\u043a\u0443 client \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<pre><code>$ cd client $ npm i react-router-dom socket.io-client<\/code><\/pre>\n<p>React-router-dom \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u043a \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c React \u2014 \u043f\u043e \u0441\u0443\u0442\u0438, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b.<\/p>\n<p>Socket.io-client \u2014 \u044d\u0442\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f socket.io, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u00ab\u0432\u044b\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u00bb \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440. \u041f\u043e\u043b\u0443\u0447\u0438\u0432 \u0438\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e socket.io \u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439, \u043a\u0430\u043a \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c, \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0438\u043c\u0441\u044f \u0432 \u0442\u043e\u0439 \u0436\u0435 \u043a\u043e\u043c\u043d\u0430\u0442\u0435, \u0447\u0442\u043e \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044c, \u0438\u043b\u0438 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043a socket room.<\/p>\n<p>\u0412\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u043d\u044f\u0442\u044c \u044d\u0442\u043e \u043f\u043e\u0437\u0436\u0435, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043d\u0430\u0447\u043d\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u0438 \u0438\u0434\u0435\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0434\u0430.<\/p>\n<h4>3. \u041a\u0430\u043a \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 React<\/h4>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0432\u0441\u0435 \u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u0443\u0442\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0438\u0437 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0430:<\/p>\n<pre><code>$ npm start<\/code><\/pre>\n<p>Webpack \u0441\u043e\u0431\u0435\u0440\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 React \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442 \u0435\u0433\u043e \u043d\u0430\u00a0<a href=\"http:\/\/localhost:3000\/\">http:\/\/localhost:3000<\/a>:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/c64\/d21\/8e2\/c64d218e2b9284f2f400ba2ff2c37868.jpeg\" alt=\"Create react app up and running on localhost\" title=\"\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 react \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0435\u0433\u043e \u043d\u0430 localhost\" width=\"533\" height=\"400\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c64\/d21\/8e2\/c64d218e2b9284f2f400ba2ff2c37868.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 react \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0435\u0433\u043e \u043d\u0430 localhost<\/figcaption><\/div>\n<\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 HarperDB \u2014 \u0435\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438.<\/p>\n<h3>\u041a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c HarperDB<\/h3>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430\u00a0<a href=\"https:\/\/studio.harperdb.io\/\"><u>\u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0432 HarperDB<\/u><\/a>.<\/p>\n<p>\u0417\u0430\u0442\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 HarperDB:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/415\/1e0\/010\/4151e0010a55baf4f78187975cc328a8.jpeg\" alt=\"create HarperDB instance\" title=\"\u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 HarperDB\" width=\"434\" height=\"346\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/415\/1e0\/010\/4151e0010a55baf4f78187975cc328a8.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 HarperDB<\/figcaption><\/div>\n<\/figure>\n<p>\u0427\u0442\u043e\u0431\u044b \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043e\u0431\u043b\u0430\u043a\u0430:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/195\/be1\/cd1\/195be1cd1cbd1e40cecb205f3dcfc786.jpeg\" alt=\"select HarperDB instance type\" title=\"\u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0438\u043f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 HarperDB\" width=\"819\" height=\"398\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/195\/be1\/cd1\/195be1cd1cbd1e40cecb205f3dcfc786.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0438\u043f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 HarperDB<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043e\u0431\u043b\u0430\u0447\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 (\u044f \u0432\u044b\u0431\u0440\u0430\u043b AWS):<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/bb3\/ada\/9b3\/bb3ada9b3f68cb01f5c40eea9b018b4c.jpeg\" alt=\"select HarperDB cloud provider\" title=\"\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043e\u0431\u043b\u0430\u0447\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 HarperDB\" width=\"491\" height=\"424\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/bb3\/ada\/9b3\/bb3ada9b3f68cb01f5c40eea9b018b4c.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043e\u0431\u043b\u0430\u0447\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 HarperDB<\/figcaption><\/div>\n<\/figure>\n<p>\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u0438\u043c\u044f \u043e\u0431\u043b\u0430\u0447\u043d\u043e\u043c\u0443 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0443 \u0438 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0443\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/638\/000\/58d\/63800058d6b91cd1de21fe8a54361b98.jpeg\" alt=\"select HarperDB instance credentials\" title=\"\u0417\u0430\u0434\u0430\u0435\u043c \u0443\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 HarperDB\" width=\"490\" height=\"444\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/638\/000\/58d\/63800058d6b91cd1de21fe8a54361b98.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0417\u0430\u0434\u0430\u0435\u043c \u0443\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 HarperDB<\/figcaption><\/div>\n<\/figure>\n<p>\u0423 HarperDB \u0449\u0435\u0434\u0440\u044b\u0439 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0435\u0433\u043e:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/ced\/689\/f11\/ced689f11a87e4198bc5d2ae2203ec25.jpeg\" alt=\"select HarperDB instance specs\" title=\"\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 HarperDB\" width=\"486\" height=\"661\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ced\/689\/f11\/ced689f11a87e4198bc5d2ae2203ec25.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 HarperDB<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u0437\u0430\u0439\u043c\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0438\u043d\u0443\u0442, \u0442\u0430\u043a \u0447\u0442\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 React.<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/d07\/371\/d4b\/d07371d4be816497d1782407cd7b509a.jpeg\" alt=\"HarperDB instance loading\" title=\"HarperDB instance loading\" width=\"324\" height=\"208\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d07\/371\/d4b\/d07371d4be816497d1782407cd7b509a.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>HarperDB instance loading<\/figcaption><\/div>\n<\/figure>\n<p><a class=\"anchor\" name=\"id3\" id=\"id3\"><\/a><\/p>\n<h2>\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u201cJoin a Room\u201d<\/h2>\n<p>\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/12f\/9df\/12e\/12f9df12ec03eeafd5c70e8ac11a140e.jpeg\" alt=\"How our app home page will look: a form with username input, select room dropdown and Join Room button\" title=\"\u041a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f: \u0444\u043e\u0440\u043c\u0430 \u0441 \u0432\u0432\u043e\u0434\u043e\u043c \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u044b\u0431\u043e\u0440\u0430 \u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0438 \u043a\u043d\u043e\u043f\u043a\u0430 Join Room\" width=\"475\" height=\"468\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/12f\/9df\/12e\/12f9df12ec03eeafd5c70e8ac11a140e.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u041a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f: \u0444\u043e\u0440\u043c\u0430 \u0441 \u0432\u0432\u043e\u0434\u043e\u043c \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u044b\u0431\u043e\u0440\u0430 \u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0438 \u043a\u043d\u043e\u043f\u043a\u0430 Join Room<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0432\u043e\u0434\u0438\u0442 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 \u0447\u0430\u0442\u0430 \u0438\u0437 \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430 \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0443 &#171;Join Room&#187;. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0447\u0430\u0442\u0430.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u0443 \u0434\u043e\u043c\u0430\u0448\u043d\u044e\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443.<\/p>\n<h4>1. \u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c HTML-\u0444\u043e\u0440\u043c\u0443 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u0438\u043b\u0438<\/h4>\n<p>\u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 src\/pages\/home\/index.js.<\/p>\n<p>\u041c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0441\u0442\u0438\u043b\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0434\u0443\u043b\u0435\u0439 CSS, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b: src\/pages\/home\/styles.module.css.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0430\u043f\u043e\u043a \u0434\u043e\u043b\u0436\u043d\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/43f\/339\/3a7\/43f3393a7a593da4ad4e89cb58b16b6c.jpeg\" alt=\"pages folder with home page component\" title=\"\u043f\u0430\u043f\u043a\u0430 pages \u0441 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c \u0434\u043e\u043c\u0430\u0448\u043d\u0435\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b\" width=\"218\" height=\"142\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/43f\/339\/3a7\/43f3393a7a593da4ad4e89cb58b16b6c.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u043f\u0430\u043f\u043a\u0430 pages \u0441 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c \u0434\u043e\u043c\u0430\u0448\u043d\u0435\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b<\/figcaption><\/div>\n<\/figure>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u0444\u043e\u0440\u043c\u0443 HTML:<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/pages\/home\/index.js  import styles from '.\/styles.module.css';  const Home = () => {   return (     &lt;div className={styles.container}>       &lt;div className={styles.formContainer}>         &lt;h1>{`&lt;>DevRooms&lt;\/>`}&lt;\/h1>         &lt;input className={styles.input} placeholder='Username...' \/>          &lt;select className={styles.input}>           &lt;option>-- Select Room --&lt;\/option>           &lt;option value='javascript'>JavaScript&lt;\/option>           &lt;option value='node'>Node&lt;\/option>           &lt;option value='express'>Express&lt;\/option>           &lt;option value='react'>React&lt;\/option>         &lt;\/select>          &lt;button className='btn btn-secondary'>Join Room&lt;\/button>       &lt;\/div>     &lt;\/div>   ); };  export default Home;<\/code><\/pre>\n<p>\u0412\u044b\u0448\u0435 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0432\u0432\u043e\u0434 \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 \u043e\u043f\u0446\u0438\u044f\u043c\u0438 \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u0447\u0430\u0442\u0430, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c\u0441\u044f.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u044d\u0442\u043e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432 App.js \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0430\u043a\u0435\u0442\u0430 react-router-dom. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0448\u0430 \u0434\u043e\u043c\u0430\u0448\u043d\u044f\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0443\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e &#171;\/&#187;:<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/App.js  import '.\/App.css'; import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import Home from '.\/pages\/home';  function App() {   return (     &lt;Router>       &lt;div className='App'>         &lt;Routes>           &lt;Route path='\/' element={&lt;Home \/>} \/>         &lt;\/Routes>       &lt;\/div>     &lt;\/Router>   ); }  export default App;<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0441\u0442\u0438\u043b\u0435\u0439, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b\u043e \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e:<\/p>\n<pre><code class=\"css\">\/* client\/src\/App.css *\/  html * {   font-family: Arial;   box-sizing: border-box; } body {   margin: 0;   padding: 0;   overflow: hidden;   background: rgb(63, 73, 204); } ::-webkit-scrollbar {   width: 20px; } ::-webkit-scrollbar-track {   background-color: transparent; } ::-webkit-scrollbar-thumb {   background-color: #d6dee1;   border-radius: 20px;   border: 6px solid transparent;   background-clip: content-box; } ::-webkit-scrollbar-thumb:hover {   background-color: #a8bbbf; } .btn {   padding: 14px 14px;   border-radius: 6px;   font-weight: bold;   font-size: 1.1rem;   cursor: pointer;   border: none; } .btn-outline {   color: rgb(153, 217, 234);   border: 1px solid rgb(153, 217, 234);   background: rgb(63, 73, 204); } .btn-primary {   background: rgb(153, 217, 234);   color: rgb(0, 24, 111); } .btn-secondary {   background: rgb(0, 24, 111);   color: #fff; }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u0442\u0438\u043b\u0438, \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u043d\u044b\u0435 \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b:<\/p>\n<pre><code class=\"javascript\">\/* client\/src\/pages\/home\/styles.module.css *\/  .container {   height: 100vh;   width: 100%;   display: flex;   justify-content: center;   align-items: center;   background: rgb(63, 73, 204); } .formContainer {   width: 400px;   margin: 0 auto 0 auto;   padding: 32px;   background: lightblue;   border-radius: 6px;   display: flex;   flex-direction: column;   align-items: center;   gap: 28px; } .input {   width: 100%;   padding: 12px;   border-radius: 6px;   border: 1px solid rgb(63, 73, 204);   font-size: 0.9rem; } .input option {   margin-top: 20px; }<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0430\u043a\u0436\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 &#171;Join Room&#187; \u043f\u043e\u043b\u043d\u043e\u0440\u0430\u0437\u043c\u0435\u0440\u043d\u043e\u0439, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0441\u0442\u0438\u043b\u044f:<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/pages\/home\/index.js  &lt;button className='btn btn-secondary' style={{ width: '100%' }}>Join Room&lt;\/button><\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0445\u043e\u0440\u043e\u0448\u043e:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/f49\/0a0\/5ec\/f490a05ec547fd15599390c7fe940aff.jpeg\" alt=\"Fully-styled home page\" title=\"\u041f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u0442\u0438\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0434\u043e\u043c\u0430\u0448\u043d\u044f\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\" width=\"468\" height=\"433\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f49\/0a0\/5ec\/f490a05ec547fd15599390c7fe940aff.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u041f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u0442\u0438\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0434\u043e\u043c\u0430\u0448\u043d\u044f\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430<\/figcaption><\/div>\n<\/figure>\n<h4>2. \u041a\u0430\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432 \u0444\u043e\u0440\u043c\u0443 Join Room<\/h4>\n<p>\u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u0438 \u0441\u0442\u0438\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>\u0412\u043e\u0442 \u0447\u0442\u043e \u043c\u044b \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u043b\u043e, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0443 &#171;Join Room&#187;:<\/p>\n<ol>\n<li>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u044b \u043b\u0438 \u043f\u043e\u043b\u044f \u0441 \u0438\u043c\u0435\u043d\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u043a\u043e\u043c\u043d\u0430\u0442\u043e\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0434\u0430, \u0442\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0441\u043e\u043a\u0435\u0442\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0447\u0430\u0442\u0430 (\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u043e\u0437\u0436\u0435).<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439\u00a0<em>username<\/em>\u00a0\u0438\u00a0<em>room<\/em>. \u0422\u0430\u043a\u0436\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0441\u043e\u043a\u0435\u0442\u0430.<\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u0442\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 home, \u043d\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 Chat \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f \u043a\u00a0<em>username<\/em>,\u00a0<em>room<\/em>\u00a0\u0438\u00a0<em>socket<\/em>. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043f\u043e\u0434\u043d\u0438\u043c\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0432 App.js, \u0433\u0434\u0435 \u0437\u0430\u0442\u0435\u043c \u0441\u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u044d\u0442\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c \u0434\u043e\u043c\u0430\u0448\u043d\u0435\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0447\u0430\u0442\u0430.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0441\u043e\u043a\u0435\u0442 \u0432 App.js \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u044d\u0442\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0435\u043a\u0432\u0438\u0437\u0438\u0442\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0443 &lt;Home \/>. \u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>set state<\/code>, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438\u0437 &lt;Home \/>:<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/App.js  import '.\/App.css'; import { useState } from 'react'; \/\/ Add this import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import io from 'socket.io-client'; \/\/ Add this import Home from '.\/pages\/home';  const socket = io.connect('http:\/\/localhost:4000'); \/\/ Add this -- our server will run on port 4000, so we connect to it from here  function App() {   const [username, setUsername] = useState(''); \/\/ Add this   const [room, setRoom] = useState(''); \/\/ Add this    return (     &lt;Router>       &lt;div className='App'>         &lt;Routes>           &lt;Route             path='\/'             element={               &lt;Home                 username={username} \/\/ Add this                 setUsername={setUsername} \/\/ Add this                 room={room} \/\/ Add this                 setRoom={setRoom} \/\/ Add this                 socket={socket} \/\/ Add this               \/>             }           \/>         &lt;\/Routes>       &lt;\/div>     &lt;\/Router>   ); }  export default App;<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u044d\u0442\u0438\u043c \u0440\u0435\u043a\u0432\u0438\u0437\u0438\u0442\u0430\u043c \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 Home. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0434\u0435\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0438\u0437\u0430\u0446\u0438\u044e:<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/pages\/home\/index.js  import styles from '.\/style.module.css';  const Home = ({ username, setUsername, room, setRoom, socket }) => {   return (     \/\/ ...   ); };  export default Home;<\/code><\/pre>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0431\u0438\u0440\u0430\u0435\u0442 \u0441\u0432\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u043a\u043e\u043c\u043d\u0430\u0442\u0443, \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u00a0<em>username<\/em>\u00a0\u0438\u00a0<em>room<\/em>:<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/pages\/home\/index.js  \/\/ ...  const Home = ({ username, setUsername, room, setRoom, socket }) => {   return (     &lt;div className={styles.container}>       \/\/ ...         &lt;input           className={styles.input}           placeholder='Username...'           onChange={(e) => setUsername(e.target.value)} \/\/ Add this         \/>          &lt;select           className={styles.input}           onChange={(e) => setRoom(e.target.value)} \/\/ Add this         >          \/\/ ...         &lt;\/select>          \/\/ ...     &lt;\/div>   ); };  export default Home;<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430\u00a0<code>joinRoom()<\/code>\u00a0\u0434\u043b\u044f \u0441\u043b\u0443\u0447\u0430\u044f, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0443 Join Room:<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/pages\/home\/index.js  \/\/ ...  const Home = ({ username, setUsername, room, setRoom, socket }) => {      \/\/ Add this   const joinRoom = () => {     if (room !== '' &amp;&amp; username !== '') {       socket.emit('join_room', { username, room });     }   };    return (     &lt;div className={styles.container}>       \/\/ ...                &lt;button           className='btn btn-secondary'           style={{ width: '100%' }}           onClick={joinRoom} \/\/ Add this         >           Join Room         &lt;\/button>       \/\/ ...     &lt;\/div>   ); };  export default Home;<\/code><\/pre>\n<p>\u0412\u044b\u0448\u0435, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443, \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0441\u043e\u043a\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u00a0<code>join_room<\/code>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u044a\u0435\u043a\u0442, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u0443\u044e \u043a\u043e\u043c\u043d\u0430\u0442\u0443. \u042d\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435, \u0433\u0434\u0435 \u043c\u044b \u0441\u043e\u0432\u0435\u0440\u0448\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u043b\u0448\u0435\u0431\u043d\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u043d\u0430\u0434 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c \u0434\u043e\u043c\u0430\u0448\u043d\u0435\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442 \u0432 \u043d\u0438\u0436\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438\u00a0<code>joinRoom()<\/code>, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \/chat:<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/pages\/home\/index.js  \/\/ ... import { useNavigate } from 'react-router-dom'; \/\/ Add this  const Home = ({ username, setUsername, room, setRoom, socket }) => {   const navigate = useNavigate(); \/\/ Add this    const joinRoom = () => {     if (room !== '' &amp;&amp; username !== '') {       socket.emit('join_room', { username, room });     }      \/\/ Redirect to \/chat     navigate('\/chat', { replace: true }); \/\/ Add this   };   \/\/ ...<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435: \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043a\u043e\u043c\u043d\u0430\u0442\u0443, \u0437\u0430\u0442\u0435\u043c \u043d\u0430\u0436\u043c\u0438\u0442\u0435 Join Room. \u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043f\u0430\u0441\u0442\u044c \u043d\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u00a0<a href=\"http:\/\/localhost:3000\/chat\">http:\/\/localhost:3000\/chat<\/a>\u00a0\u2014 \u043f\u043e\u043a\u0430 \u044d\u0442\u043e \u043f\u0443\u0441\u0442\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430.<\/p>\n<p>\u041d\u043e \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 Chat Page, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043a\u043e\u0435-\u0447\u0442\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.<\/p>\n<p><a class=\"anchor\" name=\"id4\" id=\"id4\"><\/a><\/p>\n<h2>\u041a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440<\/h2>\n<p>\u041d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u043f\u0440\u043e\u0441\u043b\u0443\u0448\u0438\u0432\u0430\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0441\u043e\u043a\u0435\u0442\u043e\u0432, \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u043e\u0442 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430. \u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043e\u0442 React \u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 join_room, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u044d\u0442\u043e\u0442 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f.<\/p>\n<p>\u041d\u043e \u043f\u0435\u0440\u0435\u0434 \u044d\u0442\u0438\u043c \u043d\u0443\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<h4>1. \u041a\u0430\u043a \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438<\/h4>\n<p>\u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b (\u0432 \u043a\u043e\u0434\u0435 VS: Terminal->New Terminal), \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u043f\u0430\u043f\u043a\u0443 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c, \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0439\u0442\u0435 \u0444\u0430\u0439\u043b package.json \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<pre><code>$ cd server $ npm init -y $ npm i axios cors express socket.io dotenv<\/code><\/pre>\n<ul>\n<li>\n<p>Axios \u2014 \u044d\u0442\u043e \u0448\u0438\u0440\u043e\u043a\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u043f\u0430\u043a\u0435\u0442 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a API.<\/p>\n<\/li>\n<li>\n<p>Cors \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0434\u0435\u043b\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0434\u0440\u0443\u0433\u0438\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c \u2014 \u044d\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043b\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b socket.io. \u0415\u0441\u043b\u0438 \u0432\u044b \u0435\u0449\u0435 \u043d\u0435 \u0441\u043b\u044b\u0448\u0430\u043b\u0438 \u043e CORS, \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0440\u0430\u0437\u0434\u0435\u043b \u00ab\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 CORS\u00bb<\/p>\n<\/li>\n<li>\n<p>Express \u2014 NodeJS \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0431\u044d\u043a\u0435\u043d\u0434 \u043f\u0440\u043e\u0449\u0435 \u0438 \u0441 \u043c\u0435\u043d\u044c\u0448\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u043a\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p>Socket.io \u2014 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u043e\u0431\u0449\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0447\u0442\u043e \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445.<\/p>\n<\/li>\n<li>\n<p>Dotenv \u2014 \u043c\u043e\u0434\u0443\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0437\u0430\u043a\u0440\u044b\u0442\u044b\u0435 \u043a\u043b\u044e\u0447\u0438 \u0438 \u043f\u0430\u0440\u043e\u043b\u0438 \u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438\u0445 \u0432 \u043a\u043e\u0434, \u043a\u043e\u0433\u0434\u0430 \u044d\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e.<\/p>\n<\/li>\n<\/ul>\n<p>\u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c nodemon \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 dev-\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043f\u0440\u0438 \u0432\u043d\u0435\u0441\u0435\u043d\u0438\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u0434 \u2014 \u044d\u0442\u043e \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442 \u043d\u0430\u043c \u0432\u0440\u0435\u043c\u044f \u0438 \u044d\u043d\u0435\u0440\u0433\u0438\u044e:<\/p>\n<pre><code>$ npm i -D nodemon<\/code><\/pre>\n<h4>2. \u041a\u0430\u043a \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440<\/h4>\n<p>\u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043f\u0430\u043f\u043a\u0443 index.js \u0432 \u043a\u043e\u0440\u043d\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0432 \u043d\u0435\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440:<\/p>\n<pre><code class=\"javascript\">\/\/ server\/index.js  const express = require('express'); const app = express(); const http = require('http'); const cors = require('cors');  app.use(cors()); \/\/ Add cors middleware  const server = http.createServer(app);  server.listen(4000, () => 'Server is running on port 4000');<\/code><\/pre>\n<p>\u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u0444\u0430\u0439\u043b package.json \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0441\u043a\u0440\u0438\u043f\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c nodemon \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435:<\/p>\n<pre><code class=\"javascript\">{   ...   \"scripts\": {     \"dev\": \"nodemon index.js\"   },   ... }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443:<\/p>\n<pre><code>$ npm run dev<\/code><\/pre>\n<p>\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0447\u0442\u043e \u0441\u0435\u0440\u0432\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u00a0<code>get<\/code>:<\/p>\n<pre><code class=\"javascript\">\/\/ server\/index.js  const express = require('express'); const app = express(); http = require('http'); const cors = require('cors');  app.use(cors()); \/\/ Add cors middleware  const server = http.createServer(app);  \/\/ Add this app.get('\/', (req, res) => {   res.send('Hello world'); });  server.listen(4000, () => 'Server is running on port 3000');<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043d\u0430 \u0441\u0430\u0439\u0442\u00a0<a href=\"http:\/\/localhost:4000\/\"><u>http:\/\/localhost:4000\/<\/u><\/a>:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/664\/071\/72b\/66407172bd8a5df60159731d912900ff.jpeg\" alt=\"localhost4000\" title=\"localhost4000\" width=\"322\" height=\"186\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/664\/071\/72b\/66407172bd8a5df60159731d912900ff.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>localhost4000<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u041d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043a\u043e\u0435-\u0447\u0442\u043e \u0434\u043b\u044f\u00a0<a href=\"http:\/\/socket.io\/\">Socket.io<\/a>\u00a0\u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430!<\/p>\n<p><a class=\"anchor\" name=\"id5\" id=\"id5\"><\/a><\/p>\n<h2>\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0439 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0439 Socket.io \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435<\/h2>\n<p>\u041f\u043e\u043c\u043d\u0438\u0442\u0435, \u043a\u0430\u043a \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u00a0<code>join_room<\/code>\u00a0\u0441 \u043a\u043b\u0438\u0435\u043d\u0442\u0430? \u0422\u0430\u043a \u0432\u043e\u0442, \u0441\u043a\u043e\u0440\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u043b\u0443\u0448\u0430\u0442\u044c \u044d\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u0441\u043e\u043a\u0435\u0442-\u043a\u043e\u043c\u043d\u0430\u0442\u0443.<\/p>\n<p>\u041d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u043b\u0443\u0448\u0430\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0447\u0435\u0440\u0435\u0437 socket.io-client.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0441 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430, \u0431\u044d\u043a\u0435\u043d\u0434 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0435\u0433\u043e \u0432 \u0436\u0443\u0440\u043d\u0430\u043b.<\/p>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u0441\u043e\u043a\u0435\u0442\u0430 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430.<\/p>\n<pre><code class=\"javascript\">\/\/ server\/index.js  const express = require('express'); const app = express(); http = require('http'); const cors = require('cors'); const { Server } = require('socket.io'); \/\/ Add this  app.use(cors()); \/\/ Add cors middleware  const server = http.createServer(app); \/\/ Add this  \/\/ Add this \/\/ Create an io server and allow for CORS from http:\/\/localhost:3000 with GET and POST methods const io = new Server(server, {   cors: {     origin: 'http:\/\/localhost:3000',     methods: ['GET', 'POST'],   }, });  \/\/ Add this \/\/ Listen for when the client connects via socket.io-client io.on('connection', (socket) => {   console.log(`User connected ${socket.id}`);    \/\/ We can write our socket event listeners in here... });  server.listen(4000, () => 'Server is running on port 3000');<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043b\u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 React \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443\u00a0<a href=\"http:\/\/localhost:3000\/\">http:\/\/localhost:3000\/<\/a>\u00a0\u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443.<\/p>\n<p>\u0412 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0432\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/e67\/ab1\/0bc\/e67ab10bc92a7ae244f4fa83a3532013.jpeg\" alt=\"user-connected\" title=\"user-connected\" width=\"442\" height=\"93\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e67\/ab1\/0bc\/e67ab10bc92a7ae244f4fa83a3532013.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>user-connected<\/figcaption><\/div>\n<\/figure>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e, \u043d\u0430\u0448 \u043a\u043b\u0438\u0435\u043d\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0441\u044f \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0447\u0435\u0440\u0435\u0437\u00a0<a href=\"http:\/\/socket.io\/\">socket.io<\/a>. \u0422\u0435\u043f\u0435\u0440\u044c \u043a\u043b\u0438\u0435\u043d\u0442 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u043c\u043e\u0433\u0443\u0442 \u043e\u0431\u0449\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438!<\/p>\n<p><a class=\"anchor\" name=\"id6\" id=\"id6\"><\/a><\/p>\n<h2>\u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0432 Socket.io<\/h2>\n<p>\u0418\u0437\u00a0<a href=\"https:\/\/socket.io\/docs\/v3\/rooms\/\"><u>\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Socket.io<\/u><\/a>:<\/p>\n<blockquote>\n<p><em>room<\/em>\u00a0\u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043a\u0430\u043d\u0430\u043b, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0441\u043e\u043a\u0435\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0442\u044c\u0441\u044f (<code>join<\/code>) \u0438 \u043f\u043e\u043a\u0438\u0434\u0430\u0442\u044c (<code>leave<\/code>) \u0435\u0433\u043e. \u041e\u043d \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u043e\u0434\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432.<\/p>\n<\/blockquote>\n<p>\u0418\u0442\u0430\u043a, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443, \u0430 \u0437\u0430\u0442\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432 \u044d\u0442\u043e\u0439 \u043a\u043e\u043c\u043d\u0430\u0442\u0435 \u2014 \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0443 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u041a\u0440\u0443\u0442\u043e!<\/p>\n<h3>\u041a\u0430\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 Socket.io<\/h3>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u043b\u0441\u044f \u0447\u0435\u0440\u0435\u0437\u00a0<a href=\"http:\/\/socket.io\/\">Socket.io<\/a>, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0441\u043e\u043a\u0435\u0442\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440, \u0447\u0442\u043e\u0431\u044b \u0441\u043b\u0443\u0448\u0430\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u0441\u043b\u0443\u0448\u0430\u0442\u044c \u0438\u0445 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0441\u043b\u0443\u0448\u0430\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u00a0<code>join_room<\/code>, \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435 (username \u0438 room) \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 socket room:<\/p>\n<pre><code class=\"javascript\">\/\/ server\/index.js  \/\/ Listen for when the client connects via socket.io-client io.on('connection', (socket) => {   console.log(`User connected ${socket.id}`);    \/\/ Add this   \/\/ Add a user to a room   socket.on('join_room', (data) => {     const { username, room } = data; \/\/ Data sent from client when join_room event emitted     socket.join(room); \/\/ Join the user to a socket room   }); });<\/code><\/pre>\n<h4>\u041a\u0430\u043a \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0435<\/h4>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0435, \u043a\u0440\u043e\u043c\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0432\u0448\u0435\u0433\u043e\u0441\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0435\u0434\u043e\u043c\u0438\u0442\u044c \u0438\u0445 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043a \u043d\u0438\u043c \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0438\u043b\u0441\u044f \u043d\u043e\u0432\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c:<\/p>\n<pre><code class=\"javascript\">\/\/ server\/index.js  const CHAT_BOT = 'ChatBot'; \/\/ Add this \/\/ Listen for when the client connects via socket.io-client io.on('connection', (socket) => {   console.log(`User connected ${socket.id}`);    \/\/ Add a user to a room   socket.on('join_room', (data) => {     const { username, room } = data; \/\/ Data sent from client when join_room event emitted     socket.join(room); \/\/ Join the user to a socket room      \/\/ Add this     let __createdtime__ = Date.now(); \/\/ Current timestamp     \/\/ Send message to all users currently in the room, apart from the user that just joined     socket.to(room).emit('receive_message', {       message: `${username} has joined the chat room`,       username: CHAT_BOT,       __createdtime__,     });   }); });<\/code><\/pre>\n<p>\u0412\u044b\u0448\u0435 \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u00a0<code>receive_message<\/code>\u00a0\u0432\u0441\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0435, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0438\u043b\u0441\u044f \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c, \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438: \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c, \u0438\u043c\u0435\u043d\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0432\u0448\u0435\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0427\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0432 \u043d\u0430\u0448\u0435 React-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442\u044c \u044d\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0430\u043a\u0436\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0432\u0448\u0435\u043c\u0443\u0441\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e:<\/p>\n<pre><code class=\"javascript\">\/\/ server\/index.js  io.on('connection', (socket) => {   \/\/ ...      \/\/ Add this     \/\/ Send welcome msg to user that just joined chat only     socket.emit('receive_message', {       message: `Welcome ${username}`,       username: CHAT_BOT,       __createdtime__,     });   }); });<\/code><\/pre>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 Socket.io, Socket.io \u0445\u0440\u0430\u043d\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0441\u043e\u043a\u0435\u0442\u043e\u0432 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u041d\u043e \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0438\u043c\u0435\u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432\u0441\u0435\u0445, \u043a\u0442\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0435, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u043d\u0430\u0442\u044b. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043c \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435:<\/p>\n<pre><code class=\"javascript\">\/\/ server\/index.js  \/\/ ...  const CHAT_BOT = 'ChatBot'; \/\/ Add this let chatRoom = ''; \/\/ E.g. javascript, node,... let allUsers = []; \/\/ All users in current chat room  \/\/ Listen for when the client connects via socket.io-client io.on('connection', (socket) => {     \/\/ ...          \/\/ Add this     \/\/ Save the new user to the room     chatRoom = room;     allUsers.push({ id: socket.id, username, room });     chatRoomUsers = allUsers.filter((user) => user.room === room);     socket.to(room).emit('chatroom_users', chatRoomUsers);     socket.emit('chatroom_users', chatRoomUsers);   }); });<\/code><\/pre>\n<p>\u0412\u044b\u0448\u0435 \u043c\u044b \u0442\u0430\u043a\u0436\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 chatRoomUsers \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u00a0<code>chatroom_users<\/code>, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0438\u0442\u044c \u0432\u0441\u0435 \u0438\u043c\u0435\u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0435 \u043d\u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435.<\/p>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u0434 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043d\u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434 \u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0447\u0430\u0442\u0430 \u2014 \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043b\u0438 \u043c\u044b \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u00a0<code>receive_message<\/code>.<\/p>\n<p><a class=\"anchor\" name=\"id7\" id=\"id7\"><\/a><\/p>\n<h3>\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0447\u0430\u0442\u0430<\/h3>\n<p>\u0412 \u043f\u0430\u043f\u043a\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0434\u0432\u0430 \u043d\u043e\u0432\u044b\u0445 \u0444\u0430\u0439\u043b\u0430:<\/p>\n<ol>\n<li>\n<p>src\/pages\/chat\/index.js<\/p>\n<\/li>\n<li>\n<p>src\/pages\/chat\/styles.module.css<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0438\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0447\u0430\u0442\u0430 \u0438 \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u0445:<\/p>\n<pre><code class=\"css\">\/* client\/src\/pages\/chat\/styles.module.css *\/  .chatContainer {   max-width: 1100px;   margin: 0 auto;   display: grid;   grid-template-columns: 1fr 4fr;   gap: 20px; }  \/* Room and users component *\/ .roomAndUsersColumn {   border-right: 1px solid #dfdfdf; } .roomTitle {   margin-bottom: 60px;   text-transform: uppercase;   font-size: 2rem;   color: #fff; } .usersTitle {   font-size: 1.2rem;   color: #fff; } .usersList {   list-style-type: none;   padding-left: 0;   margin-bottom: 60px;   color: rgb(153, 217, 234); } .usersList li {   margin-bottom: 12px; }  \/* Messages *\/ .messagesColumn {   height: 85vh;   overflow: auto;   padding: 10px 10px 10px 40px; } .message {   background: rgb(0, 24, 111);   border-radius: 6px;   margin-bottom: 24px;   max-width: 600px;   padding: 12px; } .msgMeta {   color: rgb(153, 217, 234);   font-size: 0.75rem; } .msgText {   color: #fff; }  \/* Message input and button *\/ .sendMessageContainer {   padding: 16px 20px 20px 16px; } .messageInput {   padding: 14px;   margin-right: 16px;   width: 60%;   border-radius: 6px;   border: 1px solid rgb(153, 217, 234);   font-size: 0.9rem; }<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0447\u0430\u0442\u0430:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/8d8\/db3\/108\/8d8db31081af9a5a68e7b071b3b7b529.jpeg\" alt=\"The finished chat page\" title=\"\u0413\u043e\u0442\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0447\u0430\u0442\u0430\" width=\"1216\" height=\"678\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8d8\/db3\/108\/8d8db31081af9a5a68e7b071b3b7b529.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0413\u043e\u0442\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0447\u0430\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u0415\u0441\u043b\u0438 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u043a\u043e\u0434 \u0438 \u043b\u043e\u0433\u0438\u043a\u0443 \u044d\u0442\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432 \u043e\u0434\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435, \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0443\u0442\u0430\u0442\u044c \u0438 \u0443\u0441\u043b\u043e\u0436\u043d\u0438\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0442\u0435\u043c, \u0447\u0442\u043e \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c React, \u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u043c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043d\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/681\/c0e\/6fa\/681c0e6faada8f1c9a95de5ea805fc82.png\" alt=\"The chat page split into three components\" title=\"\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0447\u0430\u0442\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0442\u0440\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432\" width=\"1232\" height=\"719\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/681\/c0e\/6fa\/681c0e6faada8f1c9a95de5ea805fc82.png\"\/><\/p>\n<div><figcaption>\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0447\u0430\u0442\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0442\u0440\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432<\/figcaption><\/div>\n<\/figure>\n<h3>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0447\u0430\u0442\u0430:<\/h3>\n<p><strong>A:<\/strong>\u00a0\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u043d\u0430\u0442\u044b, \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u044d\u0442\u043e\u0439 \u043a\u043e\u043c\u043d\u0430\u0442\u0435 \u0438 \u043a\u043d\u043e\u043f\u043a\u0443 &#171;Leave&#187;, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u0437 \u043a\u043e\u043c\u043d\u0430\u0442\u044b.<\/p>\n<p><strong>B:<\/strong>\u00a0\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u041f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u0438\u0437 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u0443\u0434\u0443\u0442 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u044b \u0438 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 100 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0432 \u044d\u0442\u043e\u0439 \u043a\u043e\u043c\u043d\u0430\u0442\u0435.<\/p>\n<p><strong>C:<\/strong>\u00a0\u0412\u0432\u043e\u0434 \u0438 \u043a\u043d\u043e\u043f\u043a\u0430 \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 B, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.<\/p>\n<p><a class=\"anchor\" name=\"id8\" id=\"id8\"><\/a><\/p>\n<h3>\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 (B)<\/h3>\n<p>\u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 src\/pages\/chat\/messages.js \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0432 \u043d\u0435\u0433\u043e \u043a\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/pages\/chat\/messages.js  import styles from '.\/styles.module.css'; import { useState, useEffect } from 'react';  const Messages = ({ socket }) => {   const [messagesRecieved, setMessagesReceived] = useState([]);    \/\/ Runs whenever a socket event is recieved from the server   useEffect(() => {     socket.on('receive_message', (data) => {       console.log(data);       setMessagesReceived((state) => [         ...state,         {           message: data.message,           username: data.username,           __createdtime__: data.__createdtime__,         },       ]);     });  \/\/ Remove event listener on component unmount     return () => socket.off('receive_message');   }, [socket]);    \/\/ dd\/mm\/yyyy, hh:mm:ss   function formatDateFromTimestamp(timestamp) {     const date = new Date(timestamp);     return date.toLocaleString();   }    return (     &lt;div className={styles.messagesColumn}>       {messagesRecieved.map((msg, i) => (         &lt;div className={styles.message} key={i}>           &lt;div style={{ display: 'flex', justifyContent: 'space-between' }}>             &lt;span className={styles.msgMeta}>{msg.username}&lt;\/span>             &lt;span className={styles.msgMeta}>               {formatDateFromTimestamp(msg.__createdtime__)}             &lt;\/span>           &lt;\/div>           &lt;p className={styles.msgText}>{msg.message}&lt;\/p>           &lt;br \/>         &lt;\/div>       ))}     &lt;\/div>   ); };  export default Messages;<\/code><\/pre>\n<p>\u0412\u044b\u0448\u0435 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0445\u0443\u043a\u00a0<code>useEffect<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043e\u0442 \u0441\u043e\u043a\u0435\u0442\u0430. \u0417\u0430\u0442\u0435\u043c \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u00a0<code>receive_message<\/code>. \u041e\u0442\u0442\u0443\u0434\u0430 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u00a0<code>messagesReceived<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u2014 \u043e\u043d\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044f \u0438 \u0434\u0430\u0442\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 messages \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 Chat, \u0430 \u0437\u0430\u0442\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u0434\u043b\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b Chat \u0432 App.js:<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/pages\/chat\/index.js  import styles from '.\/styles.module.css'; import MessagesReceived from '.\/messages';  const Chat = ({ socket }) => {   return (     &lt;div className={styles.chatContainer}>       &lt;div>         &lt;MessagesReceived socket={socket} \/>       &lt;\/div>     &lt;\/div>   ); };  export default Chat;<\/code><\/pre>\n<pre><code class=\"javascript\">\/\/ client\/src\/App.js  import '.\/App.css'; import { useState } from 'react'; import Home from '.\/pages\/home'; import Chat from '.\/pages\/chat'; import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import io from 'socket.io-client';  const socket = io.connect('http:\/\/localhost:4000');  function App() {   const [username, setUsername] = useState('');   const [room, setRoom] = useState('');    return (     &lt;Router>       &lt;div className='App'>         &lt;Routes>           &lt;Route             path='\/'             element={               &lt;Home                 username={username}                 setUsername={setUsername}                 room={room}                 setRoom={setRoom}                 socket={socket}               \/>             }           \/>           {\/* Add this *\/}           &lt;Route             path='\/chat'             element={&lt;Chat username={username} room={room} socket={socket} \/>}           \/>         &lt;\/Routes>       &lt;\/div>     &lt;\/Router>   ); }  export default App;<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c. \u0417\u0430\u0439\u0434\u0438\u0442\u0435 \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0438 \u0432\u043e\u0439\u0434\u0438\u0442\u0435 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/f20\/733\/0f8\/f207330f8721e30bfd21fe1d6ff6e970.jpeg\" alt=\"Joining a room as Dan\" title=\"\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0414\u044d\u043d\u0430\" width=\"661\" height=\"538\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f20\/733\/0f8\/f207330f8721e30bfd21fe1d6ff6e970.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0412\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0414\u044d\u043d\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u041c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043f\u0430\u0441\u0442\u044c \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0447\u0430\u0442\u0430 \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 ChatBot:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/d54\/aad\/e98\/d54aade984384b7303eb4325a60fa375.jpeg\" alt=\"Welcome message received from ChatBot\" title=\"\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 ChatBot\" width=\"571\" height=\"357\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d54\/aad\/e98\/d54aade984384b7303eb4325a60fa375.jpeg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 ChatBot<\/figcaption><\/div>\n<\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u0443\u0442 \u0432\u0438\u0434\u0435\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u0421\u0443\u043f\u0435\u0440!<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435: \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e\u0433\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439.<\/p>\n<p><a class=\"anchor\" name=\"id9\" id=\"id9\"><\/a><\/p>\n<h2>\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0445\u0435\u043c\u0443 \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0432 HarperDB<\/h2>\n<p>\u0412\u0435\u0440\u043d\u0438\u0442\u0435\u0441\u044c \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u044c HarperDB \u0438 \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 &#171;browse&#187;. \u0417\u0430\u0442\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u0443\u044e \u0441\u0445\u0435\u043c\u0443 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c &#171;realtime_chat_app&#187;. \u0421\u0445\u0435\u043c\u0430 \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0433\u0440\u0443\u043f\u043f\u0430 \u0442\u0430\u0431\u043b\u0438\u0446.<\/p>\n<p>\u0412 \u0440\u0430\u043c\u043a\u0430\u0445 \u044d\u0442\u043e\u0439 \u0441\u0445\u0435\u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c &#171;messages&#187; \u0441 \u0445\u044d\u0448-\u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c &#171;id&#187;.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/808\/a42\/db1\/808a42db17dd72fce5007599b3fb1263.png\" alt=\"Creating our schema and table in HarperDB\" title=\"\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0445\u0435\u043c\u044b \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0432 HarperDB\" width=\"591\" height=\"430\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/808\/a42\/db1\/808a42db17dd72fce5007599b3fb1263.png\"\/><\/p>\n<div><figcaption>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0445\u0435\u043c\u044b \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0432 HarperDB<\/figcaption><\/div>\n<\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043c\u0435\u0441\u0442\u043e \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 SendMessage.<\/p>\n<p><a class=\"anchor\" name=\"id10\" id=\"id10\"><\/a><\/p>\n<h2>\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Send Message (C)<\/h2>\n<p>\u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0444\u0430\u0439\u043b src\/pages\/chat\/send-message.js \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0432 \u043d\u0435\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/pages\/chat\/send-message.js  import styles from '.\/styles.module.css'; import React, { useState } from 'react';  const SendMessage = ({ socket, username, room }) => {   const [message, setMessage] = useState('');    const sendMessage = () => {     if (message !== '') {       const __createdtime__ = Date.now();       \/\/ Send message to server. We can't specify who we send the message to from the frontend. We can only send to server. Server can then send message to rest of users in room       socket.emit('send_message', { username, room, message, __createdtime__ });       setMessage('');     }   };    return (     &lt;div className={styles.sendMessageContainer}>       &lt;input         className={styles.messageInput}         placeholder='Message...'         onChange={(e) => setMessage(e.target.value)}         value={message}       \/>       &lt;button className='btn btn-primary' onClick={sendMessage}>         Send Message       &lt;\/button>     &lt;\/div>   ); };  export default SendMessage;<\/code><\/pre>\n<p>\u0412\u044b\u0448\u0435, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0443 &#171;Send Message&#187;, \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0441\u043e\u043a\u0435\u0442\u0430 send_message \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u041c\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u044d\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0432 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0435 \u0432\u0440\u0435\u043c\u044f.<\/p>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0439\u0442\u0435\u00a0<code>SendMessage<\/code>\u00a0\u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0447\u0430\u0442\u0430:<\/p>\n<pre><code class=\"javascript\">\/\/ src\/pages\/chat\/index.js  import styles from '.\/styles.module.css'; import MessagesReceived from '.\/messages'; import SendMessage from '.\/send-message';  const Chat = ({ username, room, socket }) => {   return (     &lt;div className={styles.chatContainer}>       &lt;div>         &lt;MessagesReceived socket={socket} \/>         &lt;SendMessage socket={socket} username={username} room={room} \/>       &lt;\/div>     &lt;\/div>   ); };  export default Chat;<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0447\u0430\u0442\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4b9\/d5a\/7aa\/4b9d5a7aa06d2692cdb105fa4df9f9a3.png\" alt=\"Chat page now has a message input where a message can be typed and sent\" title=\"\u041d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0447\u0430\u0442\u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u0432\u043e\u0434\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0431\u0440\u0430\u0442\u044c \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c\" width=\"521\" height=\"980\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4b9\/d5a\/7aa\/4b9d5a7aa06d2692cdb105fa4df9f9a3.png\"\/><\/p>\n<div><figcaption>\u041d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0447\u0430\u0442\u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u0432\u043e\u0434\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0431\u0440\u0430\u0442\u044c \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c<\/figcaption><\/div>\n<\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f HarperDB, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p><a class=\"anchor\" name=\"id11\" id=\"id11\"><\/a><\/p>\n<h2>\u041a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f HarperDB<\/h2>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 HarperDB, \u0432\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f URL-\u0430\u0434\u0440\u0435\u0441 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 HarperDB \u0438 \u043f\u0430\u0440\u043e\u043b\u044c API.<\/p>\n<p>\u041d\u0430 \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f HarperDB \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 \u0441\u0432\u043e\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440, \u0437\u0430\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b &#171;config&#187;. \u0412\u044b \u043d\u0430\u0439\u0434\u0435\u0442\u0435 URL-\u0430\u0434\u0440\u0435\u0441 \u0432\u0430\u0448\u0435\u0433\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a API Auth \u2014 \u0442\u043e \u0435\u0441\u0442\u044c \u0432\u0430\u0448 \u043f\u0430\u0440\u043e\u043b\u044c &#171;super_user&#187;, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u043b\u044e\u0431\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0435\u0442\u0435 \u0432\u0438\u0434\u0435\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/54d\/edd\/c94\/54deddc941124549835a5d7cee00aa6b.png\" alt=\"HarperDB instance URL and API auth header\" title=\"URL-\u0430\u0434\u0440\u0435\u0441 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 HarperDB \u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a API auth\" width=\"943\" height=\"410\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/54d\/edd\/c94\/54deddc941124549835a5d7cee00aa6b.png\"\/><\/p>\n<div><figcaption>URL-\u0430\u0434\u0440\u0435\u0441 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 HarperDB \u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a API auth<\/figcaption><\/div>\n<\/figure>\n<p>\u0425\u0440\u0430\u043d\u0438\u0442\u044c \u044d\u0442\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0435\u043c \u0432 \u0444\u0430\u0439\u043b\u0435\u00a0<code>.env<\/code>. \u0412\u043d\u0438\u043c\u0430\u043d\u0438\u0435: \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u0444\u0430\u0439\u043b\u00a0<code>.env<\/code>\u00a0\u043d\u0430 GitHub! \u042d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0432\u0438\u0434\u0435\u043d \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e. \u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0441\u0435\u0440\u0432\u0435\u0440 \u0437\u0430 \u043a\u0443\u043b\u0438\u0441\u0430\u043c\u0438.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0444\u0430\u0439\u043b\u044b \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0432 \u043d\u0438\u0445 URL-\u0430\u0434\u0440\u0435\u0441 \u0438 \u043f\u0430\u0440\u043e\u043b\u044c HarperDB:<\/p>\n<pre><code class=\"javascript\">\/\/ server\/.env HARPERDB_URL=\"&lt;your url goes here>\" HARPERDB_PW=\"Basic &lt;your password here>\"<\/code><\/pre>\n<p>\u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b .gitignore, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u044e .env \u043d\u0430 GitHub, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0430\u043f\u043a\u0443 node_modules:<\/p>\n<pre><code>\/\/ server\/.gitignore .env node_modules<\/code><\/pre>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/em>: \u0443\u043c\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 Git \u0438 GitHub \u2014 \u044d\u0442\u043e 100% \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432. \u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 \u043c\u043e\u0435\u0439\u00a0<a href=\"https:\/\/www.doabledanny.com\/git-workflows\"><u>\u0441\u0442\u0430\u0442\u044c\u0435\u0439<\/u><\/a>\u00a0\u043e \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430\u0445 Git, \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0443\u043b\u0443\u0447\u0448\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0432\u044b\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 Git. \u0410 \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0438\u0441\u043a\u0430\u0442\u044c \u043e\u0434\u043d\u0438 \u0438 \u0442\u0435 \u0436\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b Git, \u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u043e\u0438\u0441\u043a\u0430, \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\/\u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u2014 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043c\u043e\u044e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u0443\u044e\u00a0<a href=\"https:\/\/doabledanny.gumroad.com\/l\/git-commands-cheat-sheet-pdf\"><u>\u0448\u043f\u0430\u0440\u0433\u0430\u043b\u043a\u0443<\/u><\/a>\u00a0\u043f\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u043c Git \u0432 PDF \u0438\u00a0<a href=\"https:\/\/doabledanny.gumroad.com\/l\/git-cheat-sheet-poster\"><u>\u043f\u043b\u0430\u043a\u0430\u0442<\/u><\/a>\u00a0\u0441\u043e \u0448\u043f\u0430\u0440\u0433\u0430\u043b\u043a\u043e\u0439 \u043f\u043e Git.<\/p>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0432 \u0432\u0435\u0440\u0445\u043d\u044e\u044e \u0447\u0430\u0441\u0442\u044c \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430:<\/p>\n<pre><code class=\"javascript\">\/\/ server\/index.js  require('dotenv').config(); console.log(process.env.HARPERDB_URL); \/\/ remove this after you've confirmed it working const express = require('express'); \/\/ ...<\/code><\/pre>\n<p><a class=\"anchor\" name=\"id12\" id=\"id12\"><\/a><\/p>\n<h2>\u041a\u0430\u043a \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Socket.io<\/h2>\n<p>\u041d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u043b\u0443\u0448\u0430\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u00a0<code>send_message<\/code>, \u0430 \u0437\u0430\u0442\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0435:<\/p>\n<pre><code class=\"javascript\">\/\/ server\/index.js  const express = require('express'); \/\/ ... const harperSaveMessage = require('.\/services\/harper-save-message'); \/\/ Add this  \/\/ ...  \/\/ Listen for when the client connects via socket.io-client io.on('connection', (socket) => {        \/\/ ...    \/\/ Add this   socket.on('send_message', (data) => {     const { message, username, room, __createdtime__ } = data;     io.in(room).emit('receive_message', data); \/\/ Send to all users in room, including sender     harperSaveMessage(message, username, room, __createdtime__) \/\/ Save message in db       .then((response) => console.log(response))       .catch((err) => console.log(err));   }); });  server.listen(4000, () => 'Server is running on port 3000');<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e\u00a0<code>harperSaveMessage<\/code>. \u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 server\/services\/harper-save-message.js \u0438 \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0432 \u043d\u0435\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434:<\/p>\n<pre><code class=\"javascript\">\/\/ server\/services\/harper-save-message.js  var axios = require('axios');  function harperSaveMessage(message, username, room) {   const dbUrl = process.env.HARPERDB_URL;   const dbPw = process.env.HARPERDB_PW;   if (!dbUrl || !dbPw) return null;    var data = JSON.stringify({     operation: 'insert',     schema: 'realtime_chat_app',     table: 'messages',     records: [       {         message,         username,         room,       },     ],   });    var config = {     method: 'post',     url: dbUrl,     headers: {       'Content-Type': 'application\/json',       Authorization: dbPw,     },     data: data,   };    return new Promise((resolve, reject) => {     axios(config)       .then(function (response) {         resolve(JSON.stringify(response.data));       })       .catch(function (error) {         reject(error);       });   }); }  module.exports = harperSaveMessage;<\/code><\/pre>\n<p>\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043d\u044f\u0442\u044c \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0432\u0440\u0435\u043c\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043e\u0431\u0435\u0449\u0430\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e, \u0435\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u043e, \u0438\u043b\u0438 \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u043e, \u0435\u0441\u043b\u0438 \u043d\u0435\u0442.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043e\u0442\u043a\u0443\u0434\u0430 \u044f \u0432\u0437\u044f\u043b \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0432\u044b\u0448\u0435 \u043a\u043e\u0434, HarperDB \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u0434\u0435\u043b \u00ab<a href=\"https:\/\/studio.harperdb.io\/resources\/examples\/QuickStart%20Examples\/Create%20dev%20Schema\"><u>\u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043a\u043e\u0434\u0430<\/u><\/a>\u00bb \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0435\u0442 \u0436\u0438\u0437\u043d\u044c:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7af\/705\/c99\/7af705c995fc6e07e02cc92a5ff2a02d.png\" alt=\"HarperDB code examples\" title=\"\u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043a\u043e\u0434\u0430 HarperDB\u00a0\" width=\"1113\" height=\"713\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7af\/705\/c99\/7af705c995fc6e07e02cc92a5ff2a02d.png\"\/><\/p>\n<div><figcaption>\u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043a\u043e\u0434\u0430 HarperDB\u00a0<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u0440\u0435\u043c\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c! \u0412\u043e\u0439\u0434\u0438\u0442\u0435 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u044c\u0442\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435. \u0417\u0430\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 HarperDB \u0438 \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 &#171;browse&#187;, \u0437\u0430\u0442\u0435\u043c \u0449\u0435\u043b\u043a\u043d\u0438\u0442\u0435 \u043f\u043e \u0442\u0430\u0431\u043b\u0438\u0446\u0435 &#171;messages&#187;. \u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0441\u0432\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/469\/e2a\/ecd\/469e2aecd949ef46c1e90cbd0f22d7ec.png\" alt=\"Our first messages in the database\" title=\"\u041d\u0430\u0448\u0438 \u043f\u0435\u0440\u0432\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445\" width=\"937\" height=\"383\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/469\/e2a\/ecd\/469e2aecd949ef46c1e90cbd0f22d7ec.png\"\/><\/p>\n<div><figcaption>\u041d\u0430\u0448\u0438 \u043f\u0435\u0440\u0432\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0440\u0443\u0442\u043e. \u0418 \u0447\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435? \u0411\u044b\u043b\u043e \u0431\u044b \u0437\u0434\u043e\u0440\u043e\u0432\u043e, \u0435\u0441\u043b\u0438 \u0431\u044b \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 100 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0435, \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u043b\u0438\u0441\u044c, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u0442\u0441\u044f \u043a \u043a\u043e\u043c\u043d\u0430\u0442\u0435.<\/p>\n<p><a class=\"anchor\" name=\"id13\" id=\"id13\"><\/a><\/p>\n<h2>\u041a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438\u0437 HarperDB<\/h2>\n<p>\u041d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 100 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u043a\u043e\u043c\u043d\u0430\u0442\u0435 (\u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e HarperDB \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u044b):<\/p>\n<pre><code class=\"javascript\">\/\/ server\/services\/harper-get-messages.js  let axios = require('axios');  function harperGetMessages(room) {   const dbUrl = process.env.HARPERDB_URL;   const dbPw = process.env.HARPERDB_PW;   if (!dbUrl || !dbPw) return null;    let data = JSON.stringify({     operation: 'sql',     sql: `SELECT * FROM realtime_chat_app.messages WHERE room = '${room}' LIMIT 100`,   });    let config = {     method: 'post',     url: dbUrl,     headers: {       'Content-Type': 'application\/json',       Authorization: dbPw,     },     data: data,   };    return new Promise((resolve, reject) => {     axios(config)       .then(function (response) {         resolve(JSON.stringify(response.data));       })       .catch(function (error) {         reject(error);       });   }); }  module.exports = harperGetMessages;<\/code><\/pre>\n<p>\u041c\u044b \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u0442\u0441\u044f \u043a \u043a\u043e\u043c\u043d\u0430\u0442\u0435:<\/p>\n<pre><code class=\"javascript\">\/\/ server\/index.js  \/\/ ... const harperSaveMessage = require('.\/services\/harper-save-message'); const harperGetMessages = require('.\/services\/harper-get-messages'); \/\/ Add this  \/\/ ...  \/\/ Listen for when the client connects via socket.io-client io.on('connection', (socket) => {   console.log(`User connected ${socket.id}`);    \/\/ Add a user to a room   socket.on('join_room', (data) => {            \/\/ ...      \/\/ Add this     \/\/ Get last 100 messages sent in the chat room     harperGetMessages(room)       .then((last100Messages) => {         \/\/ console.log('latest messages', last100Messages);         socket.emit('last_100_messages', last100Messages);       })       .catch((err) => console.log(err));   });   \/\/ ...<\/code><\/pre>\n<p>\u0412\u044b\u0448\u0435, \u0435\u0441\u043b\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b, \u043c\u044b \u0432\u044b\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <a href=\"http:\/\/Socket.io\">Socket.io<\/a> \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c\u00a0<code>last_100_messages<\/code>. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u043b\u0443\u0448\u0430\u0442\u044c \u044d\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435.<\/p>\n<p><a class=\"anchor\" name=\"id14\" id=\"id14\"><\/a><\/p>\n<h2>\u041a\u0430\u043a \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 100 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435<\/h2>\n<p>\u041d\u0438\u0436\u0435 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0445\u0443\u043a\u00a0<code>useEffect<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f <a href=\"http:\/\/Socket.io\">Socket.io<\/a> \u0434\u043b\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u00a0<code>last_100_messages<\/code>. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u0434\u0430\u0442, \u0441\u0430\u043c\u044b\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0432\u043d\u0438\u0437\u0443, \u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u00a0<code>messagesReceived<\/code>\u00a0\u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f.<\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u00a0<code>messagesReceived<\/code>\u00a0\u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f\u00a0<code>useEffect<\/code>\u00a0\u0434\u043b\u044f \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u00a0<code>messageColumn<\/code>\u0434\u043e \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u042d\u0442\u043e \u0443\u043b\u0443\u0447\u0448\u0430\u0435\u0442 UX \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/pages\/chat\/messages.js  import styles from '.\/styles.module.css'; import { useState, useEffect, useRef } from 'react';  const Messages = ({ socket }) => {   const [messagesRecieved, setMessagesReceived] = useState([]);    const messagesColumnRef = useRef(null); \/\/ Add this    \/\/ Runs whenever a socket event is recieved from the server   useEffect(() => {     socket.on('receive_message', (data) => {       console.log(data);       setMessagesReceived((state) => [         ...state,         {           message: data.message,           username: data.username,           __createdtime__: data.__createdtime__,         },       ]);     });      \/\/ Remove event listener on component unmount     return () => socket.off('receive_message');   }, [socket]);    \/\/ Add this   useEffect(() => {     \/\/ Last 100 messages sent in the chat room (fetched from the db in backend)     socket.on('last_100_messages', (last100Messages) => {       console.log('Last 100 messages:', JSON.parse(last100Messages));       last100Messages = JSON.parse(last100Messages);       \/\/ Sort these messages by __createdtime__       last100Messages = sortMessagesByDate(last100Messages);       setMessagesReceived((state) => [...last100Messages, ...state]);     });      return () => socket.off('last_100_messages');   }, [socket]);    \/\/ Add this   \/\/ Scroll to the most recent message   useEffect(() => {     messagesColumnRef.current.scrollTop =       messagesColumnRef.current.scrollHeight;   }, [messagesRecieved]);    \/\/ Add this   function sortMessagesByDate(messages) {     return messages.sort(       (a, b) => parseInt(a.__createdtime__) - parseInt(b.__createdtime__)     );   }    \/\/ dd\/mm\/yyyy, hh:mm:ss   function formatDateFromTimestamp(timestamp) {     const date = new Date(timestamp);     return date.toLocaleString();   }    return (     \/\/ Add ref to this div     &lt;div className={styles.messagesColumn} ref={messagesColumnRef}>       {messagesRecieved.map((msg, i) => (         &lt;div className={styles.message} key={i}>           &lt;div style={{ display: 'flex', justifyContent: 'space-between' }}>             &lt;span className={styles.msgMeta}>{msg.username}&lt;\/span>             &lt;span className={styles.msgMeta}>               {formatDateFromTimestamp(msg.__createdtime__)}             &lt;\/span>           &lt;\/div>           &lt;p className={styles.msgText}>{msg.message}&lt;\/p>           &lt;br \/>         &lt;\/div>       ))}     &lt;\/div>   ); };  export default Messages;<\/code><\/pre>\n<p><a class=\"anchor\" name=\"id15\" id=\"id15\"><\/a><\/p>\n<h2>\u041a\u0430\u043a \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u043a\u043e\u043c\u043d\u0430\u0442\u0443 \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 (A)<\/h2>\n<p>\u041c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b B \u0438 C, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c A.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a80\/367\/31c\/a8036731cd4a2b195a62a597b2709a90.png\" alt=\"The chat page split into three components\" title=\"\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0447\u0430\u0442\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0442\u0440\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432\" width=\"1232\" height=\"719\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a80\/367\/31c\/a8036731cd4a2b195a62a597b2709a90.png\"\/><\/p>\n<div><figcaption>\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0447\u0430\u0442\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0442\u0440\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u0442\u0441\u044f \u043a \u043a\u043e\u043c\u043d\u0430\u0442\u0435, \u043c\u044b \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u00a0<code>chatroom_users<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432 \u043a\u043e\u043c\u043d\u0430\u0442\u0435 \u0432\u0441\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0432 \u044d\u0442\u043e\u0439 \u043a\u043e\u043c\u043d\u0430\u0442\u0435. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0441\u043b\u0443\u0448\u0430\u0435\u043c \u044d\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c\u00a0<code>RoomAndUsers<\/code>.<\/p>\n<p>\u041d\u0438\u0436\u0435 \u0442\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u043a\u043d\u043e\u043f\u043a\u0430 &#171;Leave&#187;, \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u00a0<code>leave_room<\/code>. \u0417\u0430\u0442\u0435\u043c \u043e\u043d\u0430 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443.<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/pages\/chat\/room-and-users.js  import styles from '.\/styles.module.css'; import { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom';  const RoomAndUsers = ({ socket, username, room }) => {   const [roomUsers, setRoomUsers] = useState([]);    const navigate = useNavigate();    useEffect(() => {     socket.on('chatroom_users', (data) => {       console.log(data);       setRoomUsers(data);     });      return () => socket.off('chatroom_users');   }, [socket]);    const leaveRoom = () => {     const __createdtime__ = Date.now();     socket.emit('leave_room', { username, room, __createdtime__ });     \/\/ Redirect to home page     navigate('\/', { replace: true });   };    return (     &lt;div className={styles.roomAndUsersColumn}>       &lt;h2 className={styles.roomTitle}>{room}&lt;\/h2>        &lt;div>         {roomUsers.length > 0 &amp;&amp; &lt;h5 className={styles.usersTitle}>Users:&lt;\/h5>}         &lt;ul className={styles.usersList}>           {roomUsers.map((user) => (             &lt;li               style={{                 fontWeight: `${user.username === username ? 'bold' : 'normal'}`,               }}               key={user.id}             >               {user.username}             &lt;\/li>           ))}         &lt;\/ul>       &lt;\/div>        &lt;button className='btn btn-outline' onClick={leaveRoom}>         Leave       &lt;\/button>     &lt;\/div>   ); };  export default RoomAndUsers;<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u044d\u0442\u043e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0447\u0430\u0442\u0430:<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/pages\/chat\/index.js  import styles from '.\/styles.module.css'; import RoomAndUsersColumn from '.\/room-and-users'; \/\/ Add this import SendMessage from '.\/send-message'; import MessagesReceived from '.\/messages';  const Chat = ({ username, room, socket }) => {   return (     &lt;div className={styles.chatContainer}>       {\/* Add this *\/}       &lt;RoomAndUsersColumn socket={socket} username={username} room={room} \/>        &lt;div>         &lt;MessagesReceived socket={socket} \/>         &lt;SendMessage socket={socket} username={username} room={room} \/>       &lt;\/div>     &lt;\/div>   ); };  export default Chat;<\/code><\/pre>\n<p><a class=\"anchor\" name=\"id16\" id=\"id16\"><\/a><\/p>\n<h2>\u041a\u0430\u043a \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u0437 \u043a\u043e\u043c\u043d\u0430\u0442\u044b Socket.io<\/h2>\n<p><a href=\"http:\/\/Socket.io\">Socket.io<\/a> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u00a0<code>leave()<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u0437 \u043a\u043e\u043c\u043d\u0430\u0442\u044b <a href=\"http:\/\/Socket.io\">Socket.io<\/a>. \u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u0445\u0440\u0430\u043d\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u0445 \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443\u0434\u0430\u043b\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0430:<\/p>\n<pre><code class=\"javascript\">\/\/ server\/index.js  const leaveRoom = require('.\/utils\/leave-room'); \/\/ Add this  \/\/ ...  \/\/ Listen for when the client connects via socket.io-client io.on('connection', (socket) => {        \/\/ ...    \/\/ Add this   socket.on('leave_room', (data) => {     const { username, room } = data;     socket.leave(room);     const __createdtime__ = Date.now();     \/\/ Remove user from memory     allUsers = leaveRoom(socket.id, allUsers);     socket.to(room).emit('chatroom_users', allUsers);     socket.to(room).emit('receive_message', {       username: CHAT_BOT,       message: `${username} has left the chat`,       __createdtime__,     });     console.log(`${username} has left the chat`);   }); });  server.listen(4000, () => 'Server is running on port 3000');<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e\u00a0<code>leaveRoom()<\/code>:<\/p>\n<pre><code class=\"javascript\">\/\/ server\/utils\/leave-room.js  function leaveRoom(userID, chatRoomUsers) {   return chatRoomUsers.filter((user) => user.id != userID); }  module.exports = leaveRoom;<\/code><\/pre>\n<p>\u0417\u0430\u0447\u0435\u043c \u043f\u043e\u043c\u0435\u0449\u0430\u0442\u044c \u044d\u0442\u0443 \u043a\u043e\u0440\u043e\u0442\u043a\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443\u00a0<code>utils<\/code>, \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u0435 \u0432\u044b? \u041f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0435 \u043f\u043e\u0437\u0436\u0435, \u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c\u0441\u044f \u043c\u044b \u043d\u0435 \u0445\u043e\u0442\u0438\u043c (\u0441\u043b\u0435\u0434\u0443\u044f \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Don%27t_repeat_yourself\"><u>DRY<\/u><\/a>).<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c: \u043e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u0434\u0432\u0430 \u043e\u043a\u043d\u0430 \u0440\u044f\u0434\u043e\u043c \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c \u0438 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u0435\u0441\u044c \u043a \u0447\u0430\u0442\u0443 \u0432 \u043e\u0431\u043e\u0438\u0445:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/65d\/d3c\/57b\/65dd3c57bf368a03667868c76e6a8735.png\" alt=\"Two windows chatting in realtime.\" title=\"\u0414\u0432\u0430 \u043e\u043a\u043d\u0430 \u0441 \u0447\u0430\u0442\u043e\u043c \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438\" width=\"1441\" height=\"954\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/65d\/d3c\/57b\/65dd3c57bf368a03667868c76e6a8735.png\"\/><\/p>\n<div><figcaption>\u0414\u0432\u0430 \u043e\u043a\u043d\u0430 \u0441 \u0447\u0430\u0442\u043e\u043c \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u0417\u0430\u0442\u0435\u043c \u043d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 &#171;Leave&#187; \u0432 \u043e\u043a\u043d\u0435 2:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/132\/e89\/870\/132e89870219f97eb05d37719fd7604b.png\" alt=\"The user is removed from the chat when they click the Leave button\" title=\"\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0437 \u0447\u0430\u0442\u0430, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0443 &quot;\u041f\u043e\u043a\u0438\u043d\u0443\u0442\u044c&quot;.\" width=\"1341\" height=\"952\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/132\/e89\/870\/132e89870219f97eb05d37719fd7604b.png\"\/><\/p>\n<div><figcaption>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0437 \u0447\u0430\u0442\u0430, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0443 &#171;\u041f\u043e\u043a\u0438\u043d\u0443\u0442\u044c&#187;.<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043a\u0438\u0434\u0430\u0435\u0442 \u0447\u0430\u0442, \u0430 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e \u0435\u0433\u043e \u0443\u0445\u043e\u0434\u0435. \u041e\u0442\u043b\u0438\u0447\u043d\u043e!<\/p>\n<p><a class=\"anchor\" name=\"id17\" id=\"id17\"><\/a><\/p>\n<h2>\u041a\u0430\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f disconnect<\/h2>\n<p>\u0427\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u0447\u0435\u043c\u0443-\u0442\u043e \u043f\u043e\u0442\u0435\u0440\u044f\u043b \u0441\u0432\u044f\u0437\u044c \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0443 \u043d\u0435\u0433\u043e \u043f\u0440\u043e\u043f\u0430\u043b \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442? Socket.io \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f (disconnect event listener) \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0433\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440, \u0447\u0442\u043e\u0431\u044b \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u0437 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u0440\u0438 \u043f\u043e\u0442\u0435\u0440\u0438 \u0441\u0432\u044f\u0437\u0438:<\/p>\n<pre><code class=\"javascript\">\/\/ server\/index.js  \/\/ ...  \/\/ Listen for when the client connects via socket.io-client io.on('connection', (socket) => {        \/\/ ...        \/\/ Add this   socket.on('disconnect', () => {     console.log('User disconnected from the chat');     const user = allUsers.find((user) => user.id == socket.id);     if (user?.username) {       allUsers = leaveRoom(socket.id, allUsers);       socket.to(chatRoom).emit('chatroom_users', allUsers);       socket.to(chatRoom).emit('receive_message', {         message: `${user.username} has disconnected from the chat.`,       });     }   }); });  server.listen(4000, () => 'Server is running on port 3000');<\/code><\/pre>\n<p>\u0412\u0443\u0430\u043b\u044f, \u0432\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u043f\u043e\u043b\u043d\u043e\u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0447\u0430\u0442\u0430 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u043e\u043c \u043d\u0430 React, \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e \u043d\u0430 Node\/Express \u0438 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 HarperDB. \u0425\u043e\u0440\u043e\u0448\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430!<\/p>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437 \u044f \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u044e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c\u00a0<a href=\"https:\/\/harperdb.io\/docs\/custom-functions\/\"><u>\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/u><\/a>\u00a0HarperDB, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u0435\u0447\u043d\u044b\u0435 \u0442\u043e\u0447\u043a\u0438 API \u0432 HarperDB. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0432\u0441\u0435 \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435! \u041f\u0440\u0438\u043c\u0435\u0440 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a HarperDB \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0435\u043a, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u00a0<a href=\"https:\/\/harperdb.io\/blog\/mean-stack-alternative\/\"><u>\u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/u><\/a>.<\/p>\n<h4>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u043e\u0449\u0430\u043d\u0438\u0435<\/h4>\n<p>\u0415\u0441\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0447\u0430\u0442\u0430, \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u043a\u043e\u043c\u043d\u0430\u0442\u0430 \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u0442\u0435\u0440\u044f\u043d\u044b. \u0421\u043c\u043e\u0436\u0435\u0442\u0435 \u043b\u0438 \u0432\u044b \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u043f\u043e\u0442\u0435\u0440\u044e \u044d\u0442\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438? \u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430: \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c \u043c\u043e\u0436\u0435\u0442\u00a0<a href=\"https:\/\/www.w3schools.com\/html\/html5_webstorage.asp\"><u>\u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435<\/u><\/a>. \u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0439\u0442\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u043a \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<hr\/>\n<blockquote>\n<p>\u0412\u0441\u0435\u0445 \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0445 \u0432\u0435\u0431-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043f\u0440\u0438\u0433\u043b\u0430\u0448\u0430\u0435\u043c \u043d\u0430 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0435 \u0437\u0430\u043d\u044f\u0442\u0438\u044f, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445:<\/p>\n<ul>\n<li>\n<p>\u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c html \u0441\u0430\u0439\u0442 \u0437\u0430 \u0447\u0430\u0441 \u0432 \u0430\u043d\u0430\u043b\u043e\u0433\u0435 \u0431\u043b\u043e\u043a\u043d\u043e\u0442\u0430 (6 \u0434\u0435\u043a\u0430\u0431\u0440\u044f, <a href=\"https:\/\/otus.pw\/LRpI\/\">-> \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f<\/a>)<\/p>\n<\/li>\n<li>\n<p>\u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0435\u0433\u043e \u0434\u043e \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0433\u043e \u0447\u0430\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0441 \u0440\u0430\u0437\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043e\u0432 \u043c\u043e\u0433\u043b\u0438 \u043e\u0431\u0449\u0430\u0442\u044c\u0441\u044f \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c (21 \u0434\u0435\u043a\u0430\u0431\u0440\u044f, <a href=\"https:\/\/otus.pw\/CYDD\/\">-> \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f<\/a>).<\/p>\n<\/li>\n<\/ul>\n<\/blockquote>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/778594\/\"> https:\/\/habr.com\/ru\/articles\/778594\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041e\u0431\u044b\u0447\u043d\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u041d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Socket.io, \u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043c\u043e\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u0445, \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u0435\u0434\u0448\u0438\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438.<\/p>\n<p>\u041d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u0434\u0432\u0443\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446.<\/p>\n<p>\u0421\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0432\u0445\u043e\u0434\u0430 \u0432 \u0447\u0430\u0442:<\/p>\n<figure class=\"\">\n<div><figcaption>\u041a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f: \u0444\u043e\u0440\u043c\u0430 \u0441 \u0432\u0432\u043e\u0434\u043e\u043c \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u044b\u0431\u043e\u0440\u0430 \u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0438 \u043a\u043d\u043e\u043f\u043a\u0430 Join Room<\/figcaption><\/div>\n<\/figure>\n<p>\u0418 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0441\u0430\u043c\u043e\u0433\u043e \u0447\u0430\u0442\u0430:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0413\u043e\u0442\u043e\u0432\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0447\u0430\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u043e\u0442 \u0447\u0442\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p><strong>Frontend<\/strong>:\u00a0<a href=\"https:\/\/reactjs.org\/docs\/create-a-new-react-app.html\"><u>React<\/u><\/a>\u00a0(\u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a JavaScript \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439)<\/p>\n<\/li>\n<li>\n<p><strong>\u0411\u044d\u043a\u044d\u043d\u0434<\/strong>:\u00a0<a href=\"https:\/\/nodejs.org\/en\/\"><u>Node<\/u><\/a>\u00a0\u0438\u00a0<a href=\"https:\/\/expressjs.com\/\"><u>Express<\/u><\/a>\u00a0(Express \u2014 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a NodeJS, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043b\u0435\u0433\u043a\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c API \u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u044b)<\/p>\n<\/li>\n<li>\n<p><strong>\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445:<\/strong>\u00a0<a href=\"https:\/\/harperdb.io\/\"><u>HarperDB<\/u><\/a>\u00a0(\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e SQL \u0438\u043b\u0438 NoSQL. HarperDB \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 API, \u0447\u0442\u043e \u0438\u0437\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0441 \u043e\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0438\u0441\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0434\u043b\u044f \u0431\u044d\u043a\u0435\u043d\u0434\u0430)<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u044f \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/strong>:\u00a0<a href=\"https:\/\/socket.io\/docs\/v3\/\"><u>Socket.io<\/u><\/a>\u00a0(\u0441\u043c. \u043d\u0438\u0436\u0435).<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/DoableDanny\/Realtime-chat-app-with-rooms\"><u>\u0412\u043e\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434<\/u><\/a>\u00a0(\u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u043c\u0443 \u0437\u0432\u0435\u0437\u0434\u0443).<\/p>\n<h2>\u041e\u0433\u043b\u0430\u0432\u043b\u0435\u043d\u0438\u0435<\/h2>\n<ol>\n<li>\n<p><a href=\"#id1\">\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 Socket.io?<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id2\">\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id3\">\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 &#171;Join a room&#187;<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id4\">\u041a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id5\">\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0439 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0439 Socket.io \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id6\">\u041a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0432 Socket.io<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id7\">\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0447\u0430\u0442\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id8\">\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 (B)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id9\">\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0445\u0435\u043c\u0443 \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0432 HarperDB<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id10\">\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Send Message (C)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id11\">\u041a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f HarperDB<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id12\">\u041a\u0430\u043a \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0434\u0440\u0443\u0433 \u0434\u0440\u0443\u0433\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Socket.io<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id13\">\u041a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438\u0437 HarperDB<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id14\">\u041a\u0430\u043a \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 100 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id15\">\u041a\u0430\u043a \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u043a\u043e\u043c\u043d\u0430\u0442\u0443 \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 (A)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id16\">\u041a\u0430\u043a \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u0437 \u043a\u043e\u043c\u043d\u0430\u0442\u044b Socket.io<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"#id17\">\u041a\u0430\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f disconnect<\/a><\/p>\n<\/li>\n<\/ol>\n<hr\/>\n<p><a class=\"anchor\" name=\"id1\" id=\"id1\"><\/a><\/p>\n<h2>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 Socket.IO?<\/h2>\n<p>Socket.IO \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u044f.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0432\u044b \u0438\u0433\u0440\u0430\u0435\u0442\u0435 \u0432 \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0443\u044e \u0438\u0433\u0440\u0443, \u0441\u043e\u0431\u044b\u0442\u0438\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u0441\u0442\u0430\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u0432\u0430\u0448 \u00ab\u0434\u0440\u0443\u0433\u00bb \u0437\u0430\u0431\u044c\u0435\u0442 \u0432\u0430\u043c \u044d\u0444\u0444\u0435\u043a\u0442\u043d\u044b\u0439 \u0433\u043e\u043b.<\/p>\n<p>\u0421 Socket.IO \u0432\u044b \u0431\u044b \u043f\u043e\u0447\u0442\u0438 \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e \u0443\u0437\u043d\u0430\u043b\u0438 \u043e \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u043c \u0433\u043e\u043b\u0435.<\/p>\n<p>\u0411\u0435\u0437 Socket.IO \u043a\u043b\u0438\u0435\u043d\u0442\u0443, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e AJAX \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043b\u0438\u0435\u043d\u0442 \u043c\u043e\u0433 \u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c JavaScript, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043a\u0430\u0436\u0434\u044b\u0435 5 \u0441\u0435\u043a\u0443\u043d\u0434.<\/p>\n<p>\u0421 Socket.IO \u043a\u043b\u0438\u0435\u043d\u0442\u0443 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e AJAX \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u043b\u0438 \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043a\u043b\u0438\u0435\u043d\u0442\u0443, \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0435\u0435. \u042d\u0442\u043e \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u043b\u0443\u0447\u0448\u0435.\u00a0<\/p>\n<p>\u0418\u0442\u0430\u043a, Socket.IO \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043b\u0435\u0433\u043a\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u0447\u0430\u0442-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0438\u0433\u0440\u044b.<\/p>\n<p><a class=\"anchor\" name=\"id2\" id=\"id2\"><\/a><\/p>\n<h2>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h2>\n<h4>1.\u00a0\u041a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u0430\u043f\u043a\u0438<\/h4>\n<p>\u041d\u0430\u0447\u043d\u0438\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0432 \u0432\u0430\u0448\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u043c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 (\u0443 \u043c\u0435\u043d\u044f \u044d\u0442\u043e VS Code) \u0438 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0432 \u043a\u043e\u0440\u043d\u0435 \u0434\u0432\u0435 \u043f\u0430\u043f\u043a\u0438 \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f\u043c\u0438 client \u0438 server.<\/p>\n<figure class=\"\">\n<div><figcaption>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0430\u043f\u043e\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0447\u0430\u0442\u0430 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/figcaption><\/div>\n<\/figure>\n<p>\u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434 React-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432 \u043f\u0430\u043f\u043a\u0435 client, \u0430 \u0431\u044d\u043a\u0435\u043d\u0434 Node\/Express \u2014 \u0432 \u043f\u0430\u043f\u043a\u0435 server.<\/p>\n<h4>2. \u041a\u0430\u043a \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0430<\/h4>\n<p>\u041e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b \u0432 \u043a\u043e\u0440\u043d\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (\u0432 VS Code \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u043d\u0430\u0436\u0430\u0432 Ctrl+&#8217; \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u0439\u0434\u044f \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b -> \u043d\u043e\u0432\u044b\u0439 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b).<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c React \u0432 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0443\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e:<\/p>\n<pre><code>$ npx create-react-app client<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 React \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u043f\u0430\u043f\u043a\u0443 client \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p>\n<pre><code>$ cd client $ npm i react-router-dom socket.io-client<\/code><\/pre>\n<p>React-router-dom \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u044b \u043a \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c React \u2014 \u043f\u043e \u0441\u0443\u0442\u0438, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b.<\/p>\n<p>Socket.io-client \u2014 \u044d\u0442\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f socket.io, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u00ab\u0432\u044b\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u00bb \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440. \u041f\u043e\u043b\u0443\u0447\u0438\u0432 \u0438\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e socket.io \u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439, \u043a\u0430\u043a \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c, \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0438\u043c\u0441\u044f \u0432 \u0442\u043e\u0439 \u0436\u0435 \u043a\u043e\u043c\u043d\u0430\u0442\u0435, \u0447\u0442\u043e \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044c, \u0438\u043b\u0438 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043a socket room.<\/p>\n<p>\u0412\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u043d\u044f\u0442\u044c \u044d\u0442\u043e \u043f\u043e\u0437\u0436\u0435, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043d\u0430\u0447\u043d\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u0438 \u0438\u0434\u0435\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0434\u0430.<\/p>\n<h4>3. \u041a\u0430\u043a \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 React<\/h4>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0432\u0441\u0435 \u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u0443\u0442\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0438\u0437 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0430:<\/p>\n<pre><code>$ npm start<\/code><\/pre>\n<p>Webpack \u0441\u043e\u0431\u0435\u0440\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 React \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442 \u0435\u0433\u043e \u043d\u0430\u00a0<a href=\"http:\/\/localhost:3000\/\">http:\/\/localhost:3000<\/a>:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 react \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0435\u0433\u043e \u043d\u0430 localhost<\/figcaption><\/div>\n<\/figure>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 HarperDB \u2014 \u0435\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438.<\/p>\n<h3>\u041a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c HarperDB<\/h3>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430\u00a0<a href=\"https:\/\/studio.harperdb.io\/\"><u>\u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0432 HarperDB<\/u><\/a>.<\/p>\n<p>\u0417\u0430\u0442\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 HarperDB:<\/p>\n<figure class=\"\">\n<div><figcaption>\u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 HarperDB<\/figcaption><\/div>\n<\/figure>\n<p>\u0427\u0442\u043e\u0431\u044b \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043e\u0431\u043b\u0430\u043a\u0430:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0442\u0438\u043f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 HarperDB<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043e\u0431\u043b\u0430\u0447\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 (\u044f \u0432\u044b\u0431\u0440\u0430\u043b AWS):<\/p>\n<figure class=\"\">\n<div><figcaption>\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043e\u0431\u043b\u0430\u0447\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 HarperDB<\/figcaption><\/div>\n<\/figure>\n<p>\u0417\u0430\u0434\u0430\u0439\u0442\u0435 \u0438\u043c\u044f \u043e\u0431\u043b\u0430\u0447\u043d\u043e\u043c\u0443 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0443 \u0438 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0443\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430:<\/p>\n<figure class=\"\">\n<div><figcaption>\u0417\u0430\u0434\u0430\u0435\u043c \u0443\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 HarperDB<\/figcaption><\/div>\n<\/figure>\n<p>\u0423 HarperDB \u0449\u0435\u0434\u0440\u044b\u0439 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0435\u0433\u043e:<\/p>\n<figure class=\"\">\n<div><figcaption>\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u0438\u0441\u0442\u0438\u043a\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 HarperDB<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u0437\u0430\u0439\u043c\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0438\u043d\u0443\u0442, \u0442\u0430\u043a \u0447\u0442\u043e \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 React.<\/p>\n<figure class=\"\">\n<div><figcaption>HarperDB instance loading<\/figcaption><\/div>\n<\/figure>\n<p><a class=\"anchor\" name=\"id3\" id=\"id3\"><\/a><\/p>\n<h2>\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u201cJoin a Room\u201d<\/h2>\n<p>\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<figure class=\"\">\n<div><figcaption>\u041a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f: \u0444\u043e\u0440\u043c\u0430 \u0441 \u0432\u0432\u043e\u0434\u043e\u043c \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u044b\u0431\u043e\u0440\u0430 \u043a\u043e\u043c\u043d\u0430\u0442\u044b \u0438 \u043a\u043d\u043e\u043f\u043a\u0430 Join Room<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0432\u043e\u0434\u0438\u0442 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u043a\u043e\u043c\u043d\u0430\u0442\u0443 \u0447\u0430\u0442\u0430 \u0438\u0437 \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430 \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0443 &#171;Join Room&#187;. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0447\u0430\u0442\u0430.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u0443 \u0434\u043e\u043c\u0430\u0448\u043d\u044e\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443.<\/p>\n<h4>1. \u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c HTML-\u0444\u043e\u0440\u043c\u0443 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u0438\u043b\u0438<\/h4>\n<p>\u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 src\/pages\/home\/index.js.<\/p>\n<p>\u041c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0441\u0442\u0438\u043b\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0434\u0443\u043b\u0435\u0439 CSS, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b: src\/pages\/home\/styles.module.css.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0430\u043f\u043e\u043a \u0434\u043e\u043b\u0436\u043d\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<figure class=\"\">\n<div><figcaption>\u043f\u0430\u043f\u043a\u0430 pages \u0441 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c \u0434\u043e\u043c\u0430\u0448\u043d\u0435\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b<\/figcaption><\/div>\n<\/figure>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u0444\u043e\u0440\u043c\u0443 HTML:<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/pages\/home\/index.js  import styles from '.\/styles.module.css';  const Home = () => {   return (     &lt;div className={styles.container}>       &lt;div className={styles.formContainer}>         &lt;h1>{`&lt;>DevRooms&lt;\/>`}&lt;\/h1>         &lt;input className={styles.input} placeholder='Username...' \/>          &lt;select className={styles.input}>           &lt;option>-- Select Room --&lt;\/option>           &lt;option value='javascript'>JavaScript&lt;\/option>           &lt;option value='node'>Node&lt;\/option>           &lt;option value='express'>Express&lt;\/option>           &lt;option value='react'>React&lt;\/option>         &lt;\/select>          &lt;button className='btn btn-secondary'>Join Room&lt;\/button>       &lt;\/div>     &lt;\/div>   ); };  export default Home;<\/code><\/pre>\n<p>\u0412\u044b\u0448\u0435 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0432\u0432\u043e\u0434 \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0438\u043c\u0435\u043d\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 \u043e\u043f\u0446\u0438\u044f\u043c\u0438 \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u0447\u0430\u0442\u0430, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c\u0441\u044f.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u044d\u0442\u043e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432 App.js \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0430\u043a\u0435\u0442\u0430 react-router-dom. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u0448\u0430 \u0434\u043e\u043c\u0430\u0448\u043d\u044f\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0443\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e &#171;\/&#187;:<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/App.js  import '.\/App.css'; import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import Home from '.\/pages\/home';  function App() {   return (     &lt;Router>       &lt;div className='App'>         &lt;Routes>           &lt;Route path='\/' element={&lt;Home \/>} \/>         &lt;\/Routes>       &lt;\/div>     &lt;\/Router>   ); }  export default App;<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0441\u0442\u0438\u043b\u0435\u0439, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b\u043e \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e:<\/p>\n<pre><code class=\"css\">\/* client\/src\/App.css *\/  html * {   font-family: Arial;   box-sizing: border-box; } body {   margin: 0;   padding: 0;   overflow: hidden;   background: rgb(63, 73, 204); } ::-webkit-scrollbar {   width: 20px; } ::-webkit-scrollbar-track {   background-color: transparent; } ::-webkit-scrollbar-thumb {   background-color: #d6dee1;   border-radius: 20px;   border: 6px solid transparent;   background-clip: content-box; } ::-webkit-scrollbar-thumb:hover {   background-color: #a8bbbf; } .btn {   padding: 14px 14px;   border-radius: 6px;   font-weight: bold;   font-size: 1.1rem;   cursor: pointer;   border: none; } .btn-outline {   color: rgb(153, 217, 234);   border: 1px solid rgb(153, 217, 234);   background: rgb(63, 73, 204); } .btn-primary {   background: rgb(153, 217, 234);   color: rgb(0, 24, 111); } .btn-secondary {   background: rgb(0, 24, 111);   color: #fff; }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u0442\u0438\u043b\u0438, \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u043d\u044b\u0435 \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b:<\/p>\n<pre><code class=\"javascript\">\/* client\/src\/pages\/home\/styles.module.css *\/  .container {   height: 100vh;   width: 100%;   display: flex;   justify-content: center;   align-items: center;   background: rgb(63, 73, 204); } .formContainer {   width: 400px;   margin: 0 auto 0 auto;   padding: 32px;   background: lightblue;   border-radius: 6px;   display: flex;   flex-direction: column;   align-items: center;   gap: 28px; } .input {   width: 100%;   padding: 12px;   border-radius: 6px;   border: 1px solid rgb(63, 73, 204);   font-size: 0.9rem; } .input option {   margin-top: 20px; }<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0430\u043a\u0436\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 &#171;Join Room&#187; \u043f\u043e\u043b\u043d\u043e\u0440\u0430\u0437\u043c\u0435\u0440\u043d\u043e\u0439, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0441\u0442\u0438\u043b\u044f:<\/p>\n<pre><code class=\"javascript\">\/\/ client\/src\/pages\/home\/index.js  &lt;button className='btn btn-secondary' style={{ width: '100%' }}>Join Room&lt;\/button><\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0433\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0445\u043e\u0440\u043e\u0448\u043e:<\/p>\n<figure class=\"\">\n<div><figcaption>\u041f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u0442\u0438\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0434\u043e\u043c\u0430\u0448\u043d\u044f\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430<\/figcaption><\/div>\n<\/figure>\n<h4>2. \u041a\u0430\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432 \u0444\u043e\u0440\u043c\u0443 Join Room<\/h4>\n<p>\u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u0438 \u0441\u0442\u0438\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>\u0412\u043e\u0442 \u0447\u0442\u043e \u043c\u044b \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u043b\u043e, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0443 &#171;Join Room&#187;:<\/p>\n<ol>\n<li>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u044b \u043b\u0438 \u043f\u043e\u043b\u044f \u0441 \u0438\u043c\u0435\u043d\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u043a\u043e\u043c\u043d\u0430\u0442\u043e\u0439.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0434\u0430, \u0442\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0441\u043e\u043a\u0435\u0442\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0447\u0430\u0442\u0430 (\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u043e\u0437\u0436\u0435).<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439\u00a0<em>username<\/em>\u00a0\u0438\u00a0<em>room<\/em>. \u0422\u0430\u043a\u0436\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0441\u043e\u043a\u0435\u0442\u0430.<\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u0442\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 home, \u043d\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 Chat \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f \u043a\u00a0<em>username<\/em>,\u00a0<em>room<\/em>\u00a0\u0438\u00a0<em>socket<\/em>. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043f\u043e\u0434\u043d\u0438\u043c\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0432 App.js, \u0433\u0434\u0435 \u0437\u0430\u0442\u0435\u043c \u0441\u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u044d\u0442\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c \u0434\u043e\u043c\u0430\u0448\u043d\u0435\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0447\u0430\u0442\u0430.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c \u0441\u043e\u043a\u0435\u0442 \u0432 App.js \u0438 <\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-362080","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/362080","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=362080"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/362080\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=362080"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=362080"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=362080"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}