Реалізація веб-рішення на основі стека MERN у хмарі AWS.
MERN веб-стек складається з таких компонентів:
- MongoDB: Документно-орієнтована No-SQL база даних, що використовується для зберігання даних додатка у вигляді документів.
- ExpressJS: Фреймворк для розробки веб-додатків на стороні сервера для Node.js.
- ReactJS: Фреймворк для фронтенду, розроблений компанією Facebook. Він базується на JavaScript, і використовується для створення компонентів інтерфейсу користувача (UI).
- Node.js: Оточення для виконання JavaScript. Використовується для виконання JavaScript на сервері замість браузера.
Крок 0 — Підготовка передумов
Створіть екземпляр EC2.
КРОК 1 — КОНФІГУРАЦІЯ БЕКЕНДУ
- Підключіться до екземпляра EC2 через SSH
Оновіть та оновіть Ubuntu 20.04:
- Sudo apt update && sudo apt upgrade
Отримайте місце розташування програмного забезпечення Node.js в репозиторіях Ubuntu
- curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
Встановіть Node.js на сервері
- sudo apt-get install -y nodejs
Перевірте встановлення Node і NPM
- node -v && npm -v
Налаштування коду додатка
Створіть нову директорію для вашого проекту To-Do:
- mkdir Todo && cd Todo
Далі: запустіть npm init для ініціалізації проекту. Це створить новий файл під назвою package.json.
Встановіть ExpressJS
Щоб використовувати express, встановіть його за допомогою npm:
- npm install express
Тепер створіть файл
index.js
за допомогою команди:
- touch index.js
Запустіть ls, щоб переконатися, що файл index.js успішно створено
Встановіть модуль dotenv
- npm install dotenv
Відкрийте файл index.js за допомогою наступної команди:
- vi index.js
Вставте цей код:
const express = require('express');
require('dotenv').config();
const app = express();
const port = process.env.PORT || 5000;
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use((req, res, next) => {
res.send('Welcome to Express');
});
app.listen(port, () => {
console.log(`Server running on port ${port}`)
});
Порт 5000 вказано — він буде потрібен у браузері. Запуск:
- node index.js — має показати Server running on port 5000
Відкрийте групи безпеки EC2 і створіть вхідне правило для порту 5000
Перевірте доступ до серверів за публічним IP або DNS з портом 5000
- http://
:5000
Маршрути
Є три дії, які наш додаток To-Do повинен виконувати:
- Створити нове завдання
- Показати список усіх завдань
- Видалити завершене завдання
Кожне завдання буде пов'язане з певним кінцевим пунктом і використовуватиме різні стандартні методи HTTP запитів: POST, GET, DELETE.
Для кожного завдання нам потрібно створити маршрути, які визначатимуть різні кінцеві точки, на які буде залежати додаток To-Do. Отже, давайте створимо папку routes:
- mkdir routes && cd routes && touch api.js && nano api.js
Вставте цей код:
const express = require ('express');
const router = express.Router();
router.get('/todos', (req, res, next) => {
});
router.post('/todos', (req, res, next) => {
});
router.delete('/todos/:id', (req, res, next) => {
})
module.exports = router;
МОДЕЛІ
Оскільки додаток буде використовувати MongoDB, яка є NoSQL базою даних, нам потрібно створити модель.
Модель є основою для JavaScript-додатків і саме вона робить додатки інтерактивними.
Ми повинні визначити схему бази даних (план того, як будується база даних) — це корисно для визначення полів, що зберігаються в кожному документі MongoDB.
Для створення схеми та моделі встановіть mongoose, який є пакетом для Node.js, що полегшує роботу з MongoDB.
Поверніться в директорію Todo за допомогою cd .. і встановіть Mongoose
- npm install mongoose
Створіть директорію:
- mkdir models && cd models && touch todo.js && nano todo.js
Вставте цей код схеми:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// створити схему для todo
const TodoSchema = new Schema({
action: {
type: String,
required: [true, 'Поле тексту todo обов\'язкове']
}
})
// створити модель для todo
const Todo = mongoose.model('todo', TodoSchema);
module.exports = Todo;
Тепер потрібно оновити наші маршрути у файлі Api.js у директорії 'routes', щоб використати нову модель.
const express = require ('express');
const router = express.Router();
const Todo = require('../models/todo');
router.get('/todos', (req, res, next) => {
// це поверне всі дані, надаючи клієнту тільки поле id та action
Todo.find({}, 'action')
.then(data => res.json(data))
.catch(next)
});
router.post('/todos', (req, res, next) => {
if(req.body.action){
Todo.create(req.body)
.then(data => res.json(data))
.catch(next)
} else {
res.json({
error: "Поле вводу порожнє"
})
}
});
router.delete('/todos/:id', (req, res, next) => {
Todo.findOneAndDelete({"_id": req.params.id})
.then(data => res.json(data))
.catch(next)
})
module.exports = router;
MongoDB База даних
Ми використаємо mLab, який надає MongoDB як сервіс. Зареєструйтесь і виберіть AWS як постачальника хмарних послуг та виберіть регіон, що знаходиться поруч із вами.
Дозвольте доступ до бази даних звідусіль і змініть час для видалення запису з 6 годин на 1 тиждень.
У файлі Index.js ми вказали process.env для доступу до змінних середовища, створіть .env у директорії Todo і відредагуйте:
- touch .env && nano .env
Додайте цей рядок підключення до файлу .env:
DB='mongodb+srv://<username>:<password>@<cluster-url>/?retryWrites=true&w=majority'
Переконайтеся, що оновили
Тепер потрібно оновити index.js, щоб відобразити використання .env, щоб Node.js міг підключитися до бази даних.
Просто видаліть існуючий вміст у файлі та оновіть його повним кодом нижче.
nano index.js
Вставте це:
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const routes = require('./routes/api');
const path = require('path');
require('dotenv').config();
const app = express();
const port = process.env.PORT || 5000;
// підключення до бази даних
mongoose.connect(process.env.DB, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('База даних успішно підключена'))
.catch(err => console.log(err));
// оскільки обіцянки mongoose застаріли, ми заміняємо їх на обіцянки node
mongoose.Promise = global.Promise;
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(bodyParser.json());
app.use('/api', routes);
app.use((err, req, res, next) => {
console.log(err);
next();
});
app.listen(port, () => {
console.log(`Сервер працює на порту ${port}`)
});
Використання змінних середовища для зберігання інформації вважається більш безпечним і є кращою практикою для розділення конфігурації та конфіденційних даних від додатка, замість того, щоб записувати рядки підключення безпосередньо в файл додатка index.js.
Запустіть сервер за допомогою команди:
- node index.js
Ви повинні побачити 'База даних успішно підключена' — давайте протестуємо це
Тестування бекенд коду без фронтенду за допомогою RESTful API
Ми протестуємо наш бекенд за допомогою RESTful API, використовуючи Postman.
Вам потрібно протестувати всі кінцеві точки API і переконатися, що вони працюють. Для тих кінцевих точок, що вимагають тіла запиту, ви повинні відправити JSON з необхідними полями, оскільки це те, що ми налаштували в нашому коді.
Тепер відкрийте Postman, створіть POST-запит до API
http://
Тестуємо POST-запити.
Тестуємо GET-запит
Крок 2 — Створення фронтенду
Функціональність готова. Тепер створимо інтерфейс користувача для веб-клієнта, щоб взаємодіяти з API додатка.
Щоб почати роботу з фронтендом додатка To-Do, ми використаємо команду create-react-app для створення нашого додатка.
У тій самій кореневій директорії, де знаходиться наш бекенд-код, тобто в директорії Todo, виконайте:
- npx create-react-app client
Це створить нову директорію з назвою client, куди ви додаватимете весь React код.
Запуск React додатка
Встановіть наступні залежності:
- Встановіть concurrently. Цей пакет використовується для запуску кількох команд одночасно в одному вікні термінала.
- Встановіть nodemon. Він використовується для запуску і моніторингу сервера. Якщо буде змінено код сервера, nodemon автоматично перезапустить його і завантажить нові зміни.
npm install concurrently --save-dev && npm install nodemon --save-dev
- Відкрийте файл package.json у директорії Todo. Змініть виділену частину на скріншоті нижче і замініть її кодом:
"scripts": {
"start": "node index.js",
"start-watch": "nodemon index.js",
"dev": "concurrently \"npm run start-watch\" \"cd client && npm start\""
},
Налаштування Proxy в package.json
- Перейдіть у директорію ‘client’
- cd client
- Відкрийте файл package.json
vi package.json
Додайте пару ключ-значення в файл package.json
“proxy”: “http://localhost:5000
Основна мета додавання конфігурації proxy в пункті 3 вище — це зробити можливим доступ до додатка безпосередньо з браузера, просто викликаючи URL сервера, наприклад, http://localhost:5000, а не завжди вказуючи повний шлях, наприклад,
http://localhost:5000/api/todos
Запустіть:
npm run dev
Наш додаток має відкритися і почати працювати на localhost:3000
Важлива примітка: Для того, щоб мати змогу отримати доступ до додатка з Інтернету, потрібно відкрити TCP порт 3000 на EC2, додавши нове правило в Security Group. Ви вже знаєте, як це зробити.
Створення компонентів React
- cd client && cd src && mkdir components && cd components && touch Input.js ListTodo.js Todo.js
Nano Input.js
import React, { Component } from 'react';
import axios from 'axios';
class Input extends Component {
state = {
action: ""
}
addTodo = () => {
const task = {action: this.state.action}
if(task.action && task.action.length > 0){
axios.post('/api/todos', task)
.then(res => {
if(res.data){
this.props.getTodos();
this.setState({action: ""})
}
})
.catch(err => console.log(err))
} else {
console.log('input field required')
}
}
handleChange = (e) => {
this.setState({
action: e.target.value
})
}
render() {
let { action } = this.state;
return (
<div>
<input
type="text"
placeholder="add todo"
value={action}
onChange={this.handleChange}
/>
<button onClick={this.addTodo}>add todo</button>
</div>
)
}
}
export default Input;
Тепер перейдіть назад до директорії clients/ і встановіть axios.
npm install axios
Потім перейдіть до src/components та виконайте команду nano ListTodo.js і вставте наступне:
import React from 'react';
const ListTodo = ({ todos, deleteTodo }) => {
return (
<div>
{ todos && todos.length > 0 ? (
todos.map(todo => {
return (
<div key={todo._id}>
<button onClick={() => deleteTodo(todo._id)}>Delete</button>
{todo.action}
</div>
)
})
) : (
<p>No todo(s) left</p>
)}
</div>
)
}
export default ListTodo;
Тепер у Todo.js – код
Тепер App.js, App.css і index.css
Коли все успішно … ви повинні отримати інтерфейс користувача для нашого додатка, що працює на порту 3000.
— — — — — — — — — — — — — — — — —
Кінець
— — — — — — — — — — — — — — — — —
Ось мій репозиторій на Github: https://github.com/mutemip/mern-stack-project3
Перекладено з: Simple To-Do Application using MERN Web Stack