Створення застосунків для сумісного використання за допомогою PubNub, React.js і ES6
Ukrainian (українська мова) translation by Nadia Gonzales (you can also view the original English article)
В моїх попередніх посібниках я показала, як створювати прототип приладів, що відповідають концепції IoT (* Internet of Things – Інтернет речей; концепція мережі, що складається із взаємозв'язаних фізичних пристроїв, які мають вбудовані датчики, а також програмне забезпечення, що дозволяє здійснювати передачу і обмін даними між фізичним світом і комп'ютерними системами, за допомогою використання стандартних протоколів зв'язку. Тут і надалі примітка перекладача.), і зробила візуалізацію даних, отриманих від датчиків обладнання, за допомогою Мережі потоку даних (* DSN – Data Stream Network) PubNub (* швидко працююча система обміну повідомленнями між будь-якими пристроями та платформами). У цбому посібнику я збираюся показати, як використовівати PubNub для створення веб-застосувань для сумісного використання, що працює в режим реального часу, за допомогою React.js, що дозволяє вам дуже ефективно маніпулювати DOM (* Об'єктна модель документа), і наступного покоління JavaScript, ES6 (специфікація ECMAScript 6).



Онлайн демоверсія: Записки-наклейки для сумісного використання
Я створила дві версії того ж самого додатка Stickie Note (* для створення стікерів для заміток): у першій, що розташована на CodePen, використовуються версії React (* React.js; бібліотека JavaScript для створення користувальницьких інтерфейсів) з CDN (* content delivery network – мережа доставки (розповсюдження) контенту), а друга розташована на GitHub, і в ній для підключення React використовується пакетний менеджер. У цьому посібнику я використовую «легкий» варіант останньої версії. Ми пройдемося по процесу створення додатка, використовуючи всі фішки: npm, webpack, Babel (* компілятор для JavaScript, а точніше транcпілятор) для JSX (* розширення синтаксису для JavaScript) та ES6!
Попередні підготування
Для цього посібника вам будуть необхідні:
- базове розуміння React
- практичні знання пакетного менеджера npm для завантаження, встановлення та керування залежностями
- практичні знання збирача пакетів webpack (* збирач пакетів для JavaScript з відкритим початковим кодом), за допомогою якого робиться укомплектування ресурсів JavaScript та інших ресурсів для браузера (він рацює подібно до grunt или gulp)
- встановлені на вашому комп'ютері Node і npm
У цьому посібнику не даються початкові знання по React. Проте ви можете дізнатися про React більше з інших чудових посібників на Envato Tuts+.
Що ми збираємося створювати
Зараз ми збираємося створити простий веб-додаток за допомогою PubNub. PubNub – мережа потоку даних (* DSN – Data Stream Network), що надає глобальну інфраструктуру (* основоположна сукупність компонентів, об'єднана в систему) за допомогою якої можна доволі просто створювати та масштабувати застосунки, що працюють у режимі реального часу, та пристрої IoT. У цьому посібнику ми створимо «стікери для заміток» сумісного використання. Ось як виглядає послідовність взаємодії користувача із застосуванням.
- Користувач входить до застосування.
- Тільки-но користувач вводить ім'я, застосування отримує останні 50 заміток, якщо вони є.
- Користувач набирає повідомлення на стікері та натискає клавішу вводу для відправлення.
- Нова замітка з'являється разом із іншими на сторнці вашого браузера, а також на сторінках інших браузерів усіх користувачів, що знаходяться в той момент онлайн.
Тепер давайте почнемо!
Встановлення пакетів
В папці вашого додатка виконайте npm init
для налаштування вашого файлу package.json, і потім встановіть ці модулі.
Встановіть збирач пакетів webpack, що компілює, об'єднує, здійснює мініфікацію та стиснення статичних ресурсів для клієнтської частни додатка.
$ npm install webpack --save-dev
Встановіть webpack-dev-server для запуску локального сервера:$ npm install webpack-dev-server --save-dev
Встановіть React, React DOM і розширення CSS для реалізації анімації: $ npm install react react-dom react-addons-css-transition-group --save
Встановіть Babel для використання JSX і ES6. Ми збираємося писати код ES6 (ES 2015) за допомогою Babel: $ sudo npm install babel-loader babel-core babel-preset-es2015 babel-preset-react --save
Встановіть PubNub для забезпечення комунікації в режимі реального часу: $ npm install pubnub --save
Налаштоваємо структуру додатка та веб-сервера
Створіть структуру додатка подібною до наступної:
1 |
├── /app |
2 |
│ ├── app.jsx |
3 |
│ ├── stickie.jsx |
4 |
│ ├── stickieList.jsx |
5 |
├── /dist |
6 |
├── /css |
7 |
├── /images |
8 |
├── /node_modules |
9 |
├── index.html |
10 |
├── package.json |
11 |
└── webpack.config.js |
Та налаштуйте webpack.config.js:
1 |
var webpack = require('webpack'); |
2 |
module.exports = { |
3 |
entry: './app/app.jsx', |
4 |
output: {path: './dist', filename: 'bundle.js'}, |
5 |
watch: true, |
6 |
module: {...} |
7 |
}
|
Ознайомтеся з повним конфігураційним файлом у репозиторії GitHub.
Власне, ми визначаємо точку входу додатка (файл вищого рівня) та розташування для файлу вихідних даних, де усі ваші файли js (и .jsx) будуть об'єднані в один після виконання команди webpack. Також за допомогою визначення watch: true
ви гарантуєте, що webpack буде відслідковувати зміни ваших файлів та відтворить результівний файл автоматично.
Створення файлу index.html
Підключіть скрипт bundle.js до вашого файлу index.html:
1 |
<!DOCTYPE html>
|
2 |
<html>
|
3 |
<head>
|
4 |
<meta charset="utf-8"> |
5 |
<title>Collaborative Stickies</title> |
6 |
<link rel="stylesheet" href="css/style.css" /> |
7 |
</head>
|
8 |
<body>
|
9 |
<section id="container"></section> |
10 |
<script src="dist/bundle.js"></script> |
11 |
</body>
|
12 |
</html>
|
Також зверніть увагу на елемент із id=”container”
в тілі. Саме тут буде розташовуватися ваш додаток React.
Запуск Webpack Dev Server
Ви можете запустити ваш сервер для розробки за допомогою команди: $ ./node_modules/.bin/webpack-dev-server
Або ви можете налаштувати його запуск у вашому package.json за допомогою рядка:
1 |
"scripts": { |
2 |
"start": "webpack-dev-server" |
3 |
},
|
таким чином, що ви зможете запустити сервер за допомогою команди npm start
Перейдіть у вашому браузері на сторінку http://localhost:8080/webpack-dev-server/, і ви повинні будете там побачити ваш запущений додаток (поки що тільки порожня сторінка HTML).
Створення компонентів React за допомогою ES6
Відкрийте новий файл app.jsx в папці app, який ви вказали в якості точки входу додатка у вашому webpack.config.js. Як ви могли помітити по розширенню імені файлу, ми збираємося використовувати JSX.
Для початку імпортуйте модулі та файли, що необхідні для app.jsx:
1 |
import React from 'react'; |
2 |
import ReactDOM from 'react-dom'; |
3 |
import StickieList from './stickieList'; |
4 |
import 'pubnub'; |
Оператор import, що з'явився в ES6, використовується для імпорту функцій, об'єктів чи примітивів, що були експортовані із зовнішнього модуля або скрипта.
Далі визначаємо клас CollabStickies
, що поширює клас React.Component
за допомогою об'явлення класу згідно зі стандартом ES6. Це – еквівалент для React.createClass
згідно зі стандартом ES5:
1 |
class CollabStickies extends React.Component { |
2 |
constructor(props) { |
3 |
super(props); |
4 |
this.state = { |
5 |
stickieList: [] |
6 |
}
|
7 |
}
|
8 |
|
9 |
componentWillMount() { |
10 |
… // will explain later |
11 |
}
|
12 |
...
|
13 |
render() { |
14 |
return ( |
15 |
<div> |
16 |
<StickieWritable username={this.props.username} color={this.props.color} /> |
17 |
<StickieList stickieList={this.state.stickieList} /> |
18 |
</div> |
19 |
);
|
20 |
}
|
21 |
}
|
У конструкторі ви встановлюєте початковий стан цих мінливих даних – масиву stickieList.
Ми будемо оновлювати масив кожного разу при отриманні нової замітки за допомогою this.setState().
В функції render використовуємо JSX для визначення шаблоноподібних елементів віртуального DOM. В нашому випадку підключаються компоненти StickieWritable
і StickieList.
Ви можете передавати мінливі props (* реквізити) та states (* стани) компонентам для використання. Ми визначимо їх пізніше.
При створенні додатка Babel здійсне транспіляцію всього коду на ES6 та коду на JSX до ES5, який браузери можуть добре виконати.
Рендеринг вузла DOM разом із прив'язаними даними
За допомогою ReactDOM.render(),
що поставляється разом із пакетом react-dom
, виконайте відтворення компонента CollabStickies
у вузлі DOM у вашому HTML.
1 |
ReactDOM.render( |
2 |
<CollabStickies username={username} color={color} />, |
3 |
document.getElementById('container') |
4 |
);
|
Тут ви помітили props
username і color. Ці дані використовуються для компонента CollabStickies
та пердаються його дочірнім компонентам.
Значення повинні бути отримані після входу користувача; проте, для спрощення додатка для нашого прикладу давайте використовувати просто window.prompt()
для отримання username і потім задамо випадковий колір, коли додаток завантажено.
1 |
var username = window.prompt('Your name'); |
2 |
|
3 |
const colors = ['yellow', 'pink', 'green', 'blue', 'purple']; |
4 |
var color = colors[~~(Math.random() * colors.length)]; |



Хоча я використовую вбудоване до браузера вікно підказки, у дійсності я раджу створити інший компонент UI для реалізації можливості входу чи використовувати сторонні компоненти вікна діалогу. Існує багато готових компонентів, наприклад: Elemental UI’s Modal і Material UI’s Dialog.
Використання для реалізації можливості співробітництва
Тепер ми збираємося використовувати PubNub для реалізації можливості сумісного використання.
PubNub – глобально розповсюджена мережа потоку даних, що дозволяє вам легко створювати додатки, що працюють в режимі реального часу. Головна можливість, яку надає PubNub, – відправлення та отримання даних між багатьма користувачами одночасно.
У нашому додатку кожний, хто «увійшов» до додатку, може залишити повідомлення на стікері та поділитися ним із іншими користувачами.



Для використання PubNub у вашому додатку впевніться, що модуль pubnub встановлено та імпортовано у верхній частині вашого додатка.Ініціалізація PubNub
Ініціалізація PubNub
Для початку вам необхідно ініціалізувати PubNub для створення зразка її об'єкту. Вам необхідні ваші ключі API для нінціалізації, так що, будь ласка, зареєструйтесь у PubNub для їх отримання.
1 |
const publish_key = 'pub-c-1d17120...'; // your pub key |
2 |
const subscribe_key = 'sub-c-85bdc...'; // your sub key |
3 |
|
4 |
const pubnub = require('pubnub').init({ |
5 |
publish_key : publish_key, |
6 |
subscribe_key : subscribe_key, |
7 |
ssl: true, |
8 |
uuid: username |
9 |
});
|
10 |
|
11 |
const channel = 'stickie-notes'; |
Тут ви присвоюєте username, отриманий після процесу «входу» як uuid
(унікальний ідентифікатор). (У нашому прикладі ми використовуємо у якості uuid будь-який рядок, введений користувачем, але в реальності вам необхідна буде професійна система для «входу», щоб кожний uuid був у дійсності унікальним, без повторень!)
Також зверніть увагу, що я використовую об'явлення констант у стилі ES6 за допомогою const
замість var
для цих глобальних значень констант. У ES6 const
діє в якості змінної тільки для зчитування та представляє собою постійне посилання на значення. Далі ви побачите також недавно представлену let
– локальну змінну з блочною областю видимості.
Підписка на повідомлення
Для створення додатка для обміну записками ми збираємося використовувати метод publish()
PubNub для відправлення ваших повідомлень кому завгодно, тоді як subscribe()
дозволяє іншим користувачам отримувати всі записки. Метод subscribe()
викливається кожного разу, коли будь-хто публікує нову записку.
У вашому додатку React давайте викличемо subscribe()
усередині componentWillMount()
, що викликається одразу ж до того, як відбудеться початковий рендеринг у життєвому циклі застосунку.
1 |
componentWillMount() { |
2 |
pubnub.subscribe({ |
3 |
channel: channel, |
4 |
restore: true, |
5 |
connect: () => this.connect(), |
6 |
message: (m) => this.success(m) |
7 |
});
|
8 |
}
|
Метод subscribe працює асинхронно, і коли кожну операцію вдало закінчено, відбувається виклик функції зворотного виклику message
. У ній давайте оновимо список записів, задавши стан масиву stickieList
, що було визначено в конструкторі на початку.
В React при зміні ваших даних за допомогою setState
автоматично відбувається оновлення представлення.
1 |
success(m) { |
2 |
let newList = [m].concat(this.state.stickieList); |
3 |
this.setState({stickieList: newList}); |
4 |
}
|
Ми створимо представлення (компонент UI ) пізніше.
У функціях зворотного виклику ви, ймовірно, помітили синтаксис зі стрілками, що виглядає доволі смішно, – =>.
Це стрілочні функції, синтаксис яких коротше, ніж вираз для функцій ES5. Також цей вираз лексично пов'язує значення this
. Знов-таки, за допомогою Babel ми можемо використовувати всі можливості ES6!
Також ми використовуємо необов'язкову функцію зворотного виклику connect
для методу subscribe для отримання “history” (* історії). Завдяки їй ми отримаємо попередні дані, коли з'єднання з PubNub встановлюється в перший раз.
1 |
connect() { |
2 |
pubnub.history({ |
3 |
channel: channel, |
4 |
count: 50, |
5 |
callback: (m) => { |
6 |
m[0].reverse(); |
7 |
for (var v of m[0]) { |
8 |
let newList = this.state.stickieList.concat(v); |
9 |
this.setState({stickieList: newList}); |
10 |
}
|
11 |
}
|
12 |
});
|
13 |
}
|
history()
– це частина можливості Storage and Playback, яку надає PubNub (* сховище и відтворення), і в нашому випадку відбувається отримання останніх 50 повідомлень із PubNub. В функції зворотного виклику success
оновіть представлення, задавши стан масиву stickieList
тут також.
Публікація повідомлень
Давайте створимо клас StickieWritable
. Це – компонент записок-наклейок, до якого вводяться користувацькі дані.
Його рендерінг відбувається наступним чином:
1 |
render() { |
2 |
return ( |
3 |
<div className={'stickie-note writable ' + this.props.color}> |
4 |
<textarea type='text' placeholder='Your new note...' onKeyUp={this.handleTextChange.bind(this)} /> |
5 |
</div> |
6 |
);
|
7 |
}
|
У текстовому полі
прослуховуємо подію onKeyUp
і кожного разу при його виникненні викливаємо функцію handleTextChange
для перевірки, чи була нажата клавіша return/enter (* клавіша повернення каретки/ клавіша вводу). Зверніть увагу, що я прив'язую this при виклику функції. На відміну від React.createClass(),
що є методом React стандарту ES5 для створення класу, клас ES6 не додає
автоматично методи до зразка об'єкта, так що вам необхідно прив'язувати
їх самостійно. (Існує декілька різних способів реалізувати теж саме)
В функції handleTextChange
опублікуйте текст ті дані користувача в PubNub:
1 |
var data = { |
2 |
username: this.props.username, |
3 |
color: this.props.color, |
4 |
text: e.target.value, |
5 |
timestamp: Date.now() |
6 |
};
|
7 |
|
8 |
pubnub.publish({ |
9 |
channel: channel, |
10 |
message: data, |
11 |
callback: e.target.value = '' // resetting the text field |
12 |
});
|
Тепер при набиранні користувачем якого-небудь тексту на стикері та натисканні return повідомлення буде надіслано до PubNub, і всі інші користувачі отримають повідомлення одночасно (протягом ¼ секунди!).
Створення компонентів UI
UI додатка складається з декількох компонентів UI, що виглядають наступним чином:



1. CollabStickies (* стикери для сумісного використання)
2. StickieWritable (* стикер для створення нової нотатки)
3. Stickie (* стикер)
4.StickieList (* список стикерів)
З компонентами 1 і 2 ми вже ознайомилися, так що давайте створимо 3-й компонент – індивідуальний стикер.
Створіть новий файл stickie.jsx для рендерінгу UI за допомогою JSX. На відміну від компонента StickieWritable
, це – компонент UI тільки для зчитування без функціональності UX (* досвід взаємодії). У нього є тільки функція render()
для прорисовування стикера разом із текстом, використовуючи дані prop.
Власне, при кожному отриманні користувачем повідомлення від іншого користувача повідомлення відображується на новому стикері.
1 |
import React from 'react'; |
2 |
import ReactDOM from 'react-dom'; |
3 |
|
4 |
export default class Stickie extends React.Component { |
5 |
render() { |
6 |
return ( |
7 |
<div className={'stickie-note ' + this.props.color} > |
8 |
<p className='note'>{this.props.text}</p> |
9 |
<p className='username'>{this.props.username}</p> |
10 |
</div> |
11 |
);
|
12 |
}
|
13 |
}
|
Далі ми будемо створювати інший компонент UI – stickieList.jsx, що є контейнером для 3-го компонента та містить групу стикерів.
Анімування компонентів
Імпортуйте Stickie.jsx і всі залежності до StickieList.jsx. Тут я використовую додаток ReactCSSTransitionGroup
та користувальницький шрифт для веб.
1 |
import React from 'react'; |
2 |
import ReactDOM from 'react-dom'; |
3 |
import ReactCSSTransitionGroup from 'react/lib/ReactCSSTransitionGroup'; |
4 |
import Stickie from './stickie'; |
5 |
import webfontloader from 'webfontloader' |
Ви можете встановити завантажник шрифту для Веб за допомогою npm:$ npm install webfontloader
Потім ви можете завантажити будь-який користувальницький шрифт на свій вибір. Ви можете поглянути на початковий код, щоб подивитися, як імпортується користувальницький шрифт Google.
В render()
використовуємо стрілкову функцію ES6 та map()
для ітерації по масиву та використовуємо stickieList
для рендерингу кожного компонента Stickie, що тільки-но створили:
1 |
export default class StickieList extends React.Component { |
2 |
render() { |
3 |
let items = (this.props.stickieList || []).map((item) => |
4 |
<li key={item.username + '-' + item.timestamp} > |
5 |
<div className="stickieWrapper"> |
6 |
<Stickie text={item.text} color={item.color} username={item.username}/> |
7 |
</div> |
8 |
</li>); |
9 |
|
10 |
return ( |
11 |
<ReactCSSTransitionGroup transitionName='animation' transitionEnterTimeout={500} transitionLeaveTimeout={500} component='ul' id="stickiesList"> |
12 |
{items} |
13 |
</ReactCSSTransitionGroup> |
14 |
)
|
15 |
}
|
16 |
}
|
Створити анімацію певних компонентів можна за допомогою <ReactCSSTransitionGroup>.
Встановлюємо transitionName
, що вам необхідно використовувати у вашому CSS для визначення стилю анімування. Також зверніть увагу на атрибут key в <li>.
Вам необхідно використовувати унікальний ключ для анімування кожного компонента, коли ви використовуєте <ReactCSSTransitionGroup>.
React додає додаткові імена класів. Наприклад, коли transitionName
має значення ‘animation
’, то у вас також будуть ‘animation-enter
’, ‘animation-enter-active
’, ‘animation-leave
’ та ‘animation-leave-active
’.
Нижче наведено код для /css/style.css:
1 |
.animation-enter { |
2 |
opacity: 0.1; |
3 |
transform: scale(1.3); |
4 |
transition: all 1s ease-out; |
5 |
}
|
6 |
.animation-enter.animation-enter-active { |
7 |
opacity: 1; |
8 |
transform: scale(1); |
9 |
}
|
10 |
...
|
От ви і створили веб-додаток для сумісного використання, що працює в режимі реального часу, за допомогою React.js та PubNub! Сподіваюся, що вам сподобався посібник!



Ви можете ознайомитися з повним кодом, включаючи CSS, у цьому репозиторії GitHub. Хоча я використовувала у цьому посібнику «легку» версію – app-lite.jsx, ви можете поглянути на app.jsx, де показано більше можливостей.
Якщо ви зацікавлені у створенні більшої кількості додатків, що працюють в режимі реального часу, наприклад, додатки для чату, багатокористувацьких ігор, комерційних застосунків тощо, то відвідайте PubNub та ознайомтеся там з безліччю ресурсів!
Хочете познайомитися з React краще?
Ми маємо курс, присвячений спеціально розвитку ваших умінь роботи з React наскільки це можливо. У цьому курсі ви ознайомитесь із основами створення сучасних веб-додтків за допомогою React і Redux. Ви будете використовувати ці дві бібліотеки для створення повноцінного веб-додатка.
Ви почнете з простішої архітектури та поступово створите веб-додаток, додаючи можливість за можливістю. Ви вивчите базові концепції, такі як tooling, reducers и routing. Також ви вивчите деякі більш складні техніки: smart и dumb components, pure components та asynchronous actions. Наприкінці ви створите повноцінний додаток, де будуть карточки з текстом та малюнками для вивчення за допомогою повторення з інтервалами.
Цікаво? Зацініть!
Посилання
- PubNub: глобальна мережа потоку даних для мобільних додатків, веб-застосунків та додатків IoT.
- Посібник по SDK (* набір засобів для розроблення) на JavaScript для PubNub
- React: бібліотека JavaScript для створення користувальницьких інтерфейсів.
- ES6: специфікація мови ECMAScript 2015
- webpack: збирач пакетів