Простий додаток “Список справ” за допомогою веб-стеку MERN

Реалізація веб-рішення на основі стека MERN у хмарі AWS.

MERN веб-стек складається з таких компонентів:

  1. MongoDB: Документно-орієнтована No-SQL база даних, що використовується для зберігання даних додатка у вигляді документів.
  2. ExpressJS: Фреймворк для розробки веб-додатків на стороні сервера для Node.js.
  3. ReactJS: Фреймворк для фронтенду, розроблений компанією Facebook. Він базується на JavaScript, і використовується для створення компонентів інтерфейсу користувача (UI).
  4. Node.js: Оточення для виконання JavaScript. Використовується для виконання JavaScript на сервері замість браузера.

pic

Крок 0 — Підготовка передумов

Створіть екземпляр EC2.

pic

КРОК 1 — КОНФІГУРАЦІЯ БЕКЕНДУ

  • Підключіться до екземпляра EC2 через SSH

Оновіть та оновіть Ubuntu 20.04:

  • Sudo apt update && sudo apt upgrade

Отримайте місце розташування програмного забезпечення Node.js в репозиторіях Ubuntu

Встановіть 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

pic

Відкрийте групи безпеки EC2 і створіть вхідне правило для порту 5000

pic

Перевірте доступ до серверів за публічним IP або DNS з портом 5000

  • http://:5000

pic

Маршрути

Є три дії, які наш додаток To-Do повинен виконувати:

  1. Створити нове завдання
  2. Показати список усіх завдань
  3. Видалити завершене завдання

Кожне завдання буде пов'язане з певним кінцевим пунктом і використовуватиме різні стандартні методи 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

Ви повинні побачити 'База даних успішно підключена' — давайте протестуємо це

pic

Тестування бекенд коду без фронтенду за допомогою RESTful API

Ми протестуємо наш бекенд за допомогою RESTful API, використовуючи Postman.

Вам потрібно протестувати всі кінцеві точки API і переконатися, що вони працюють. Для тих кінцевих точок, що вимагають тіла запиту, ви повинні відправити JSON з необхідними полями, оскільки це те, що ми налаштували в нашому коді.

Тепер відкрийте Postman, створіть POST-запит до API

http://:5000/api/todos. Цей запит надсилає нове завдання до нашого списку To-Do, щоб додаток міг зберегти його в базі даних.

Тестуємо POST-запити.

pic

Тестуємо GET-запит

pic

Крок 2 — Створення фронтенду

Функціональність готова. Тепер створимо інтерфейс користувача для веб-клієнта, щоб взаємодіяти з API додатка.

Щоб почати роботу з фронтендом додатка To-Do, ми використаємо команду create-react-app для створення нашого додатка.

У тій самій кореневій директорії, де знаходиться наш бекенд-код, тобто в директорії Todo, виконайте:

  • npx create-react-app client

Це створить нову директорію з назвою client, куди ви додаватимете весь React код.

Запуск React додатка

Встановіть наступні залежності:

  1. Встановіть concurrently. Цей пакет використовується для запуску кількох команд одночасно в одному вікні термінала.
  2. Встановіть nodemon. Він використовується для запуску і моніторингу сервера. Якщо буде змінено код сервера, nodemon автоматично перезапустить його і завантажить нові зміни.

npm install concurrently --save-dev && npm install nodemon --save-dev

  1. Відкрийте файл 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

  1. Перейдіть у директорію ‘client’
  • cd client
  1. Відкрийте файл 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. Ви вже знаєте, як це зробити.

pic

Створення компонентів 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.

pic

— — — — — — — — — — — — — — — — —

Кінець

— — — — — — — — — — — — — — — — —

Ось мій репозиторій на Github: https://github.com/mutemip/mern-stack-project3

Перекладено з: Simple To-Do Application using MERN Web Stack

Leave a Reply

Your email address will not be published. Required fields are marked *