Давайте построим и развернем полностековое веб-приложение MERN

Я уверен, что когда вы только начнете изучать веб-разработку с использованием стека MERN, у вас возникнут вопросы типа «Как это — создавать приложение с полным стеком?». Что такое frontend и backend? Как их соединить? Есть ли здесь какая-то магия? и т.д. Поэтому я пишу это руководство, чтобы ответить на ваши вопросы и показать вам, как построить веб-приложение полного стека.

Примечание
Цель этого руководства — предоставить вам высокоуровневый обзор того, что такое создание приложения полного стека, а не подробное объяснение технологий стека MERN.

Давайте начнем

Необходимые условия

  • Базовое понимание технологий стека MERN.
  • Установленный NodeJs
  • Учетная запись MongoDB.

Проект

Чтобы не усложнять задачу и в то же время охватить больше концепций, мы создадим простой мини-проект. Мы создадим простое приложение для отслеживания продуктивности, в котором вы сможете записывать, какие действия вы выполнили в течение дня и за какое время. Таким образом, мы сможем увидеть, как мы тратим свое время. Также мы сможем увидеть все дела на главной странице.

  • Исходный код

Как это работает?

  • Вы вводите вид деятельности и количество времени, которое вы на него потратили.
  • Затем данные передаются на бэкенд NodeJs.
  • Эта информация будет храниться в базе данных MongoDB.
  • Все виды деятельности отображаются на главной странице.

Мы знаем, что нам нужно сделать; теперь давайте выясним, как это сделать.

Фронтенд/клиент

Что такое фронтенд/клиентское приложение?

Клиентское приложение относится к фронтенду — части приложения полного стека. Клиент посылает запросы на сервер и получает ответы. Этот запрос может быть отправкой клиентом информации на сервер или запросом на получение информации. Клиент — это видимая часть приложения полного стека.

Давайте начнем с создания клиента.

  • Создайте новую папку и обозначьте ее «productivity-app».
  • Создайте react-приложение под названием «client» с помощью create-react-app.

    npx create-react-app client
    
  • Запустите ваш редактор кодирования/IDE и откройте проект.

  • Вот как будет выглядеть структура ваших папок.

    .
    ├── README.md
    ├── package-lock.json
    ├── package.json
    ├── public
    │   ├── favicon.ico
    │   ├── index.html
    │   ├── logo192.png
    │   ├── logo512.png
    │   ├── manifest.json
    │   └── robots.txt
    └── src
        ├── App.css
        ├── App.js
        ├── App.test.js
        ├── index.css
        ├── index.js
        ├── logo.svg
        ├── reportWebVitals.js
        └── setupTests.js
    
  • На данный момент нас интересуют только файлы App.js и App.css.

  • Удалите весь существующий код из файлов App.js и App.css.
    Давайте создадим компонент react.

  • Добавьте компонент App в файл App.js.

    import "./App.css";
    
    const App = () => {
        return <div>My App</div>;
    }
    
    export default App;
    
  • Приведенный выше код создает и отображает компонент App.

  • Выполните следующую команду в терминале и перейдите по адресу http://localhost:3000.

    npm start
    

Спроектируйте приложение.

  • Мы хотим, чтобы пользователь вводил название занятия, а также время, которое оно заняло. Затем мы отобразим все виды деятельности на главной странице.
  • Скопируйте и вставьте этот HTML-код в компонент App.

    ...
    <div className="app">
      <header className="app-header">
        <h1>Productivity Tracker</h1>
        <form>
          <div>
            <label htmlFor="activity">Activity:</label>
            <input
              type="text"
              id="activity"
              name="activity"
              autoComplete="off"
            />
          </div>
          <div>
            <label htmlFor="time">Time Taken:</label>
            <input type="text" id="time" name="time" autoComplete="off" />
          </div>
          <button type="submit">Add</button>
        </form>
      </header>
      <main className="app-main">
        <h2>Today</h2>
        <ol>
            <li> Activity 1 - 3 hours</li>
            <li> Activity 2 - 10 min</li>
            <li> Activity 3 - 2 hours and 25 min</li>
        </ol>
      </main>
    </div>
    ...
    
  • Теперь наше приложение будет выглядеть следующим образом.

  • Теперь давайте добавим немного CSS. Скопируйте и вставьте код CSS из этого файла в файл App.css.

  • Теперь наше приложение выглядит следующим образом.

Добавьте логику.

  • В настоящее время действия жестко закодированы. Давайте сохраним и будем использовать действия в состоянии.

    ...
    const [activities, setActivities] = useState([]);
    ...
    
    ...
    <main className="app-main">
    <h2>Today</h2>
    
    {activities && activities.length > 0 ? (
      <ol>
        {activities.map((activity) => (
          <li key={activity._id}>
            {activity.name} - {activity.time}
          </li>
        ))}
      </ol>
    ) : (
      <p>No activities yet</p>
    )}
    </main>
    ...
    
  • Но где мы возьмем наши активности? Как мы добавим деятельность в список?

  • Для обработки всего этого необходим бэкенд.

Бэкэнд/сервер

Бэкенд-компонент приложения полного стека часто называют сервером. Работа сервера заключается в постоянном получении запросов, реализации бизнес-логики и возврате результатов.

База данных

Прежде чем создавать сервер, давайте сначала создадим базу данных. Чтобы записывать и добавлять наши действия, нам нужна база данных. Мы можем использовать облачную базу данных вместо хостинга базы данных. MongoDB предлагает бесплатную облачную базу данных (атлас), которую можно использовать для небольших проектов/хобби.

  • Войдите в свою учетную запись MongoDB.
  • Создайте проект.

  • Затем перейдите в раздел «Browse collections» и создайте базу данных. Для названия коллекции напишите «activities».

  • Нажмите на «Обзор», а затем во вкладке обзора нажмите на «CONNECT» -> «Подключить ваше приложение». Скопируйте строку подключения. Ваша строка подключения должна выглядеть следующим образом.

    mongodb+srv://<username>:<password>@<clusterUrl>/<databaseName>?retryWrites=true&w=majority
    
  • Сохраните эту строку в безопасном месте.

Сервер

Теперь у нас есть база данных. Теперь давайте создадим логику нашего приложения и подключим ее к базе данных.

  • Создайте папку под названием «Server» в папке вашего проекта.
  • В терминале откройте папку и введите npm init. Заполните все данные.
  • Установите следующие пакеты.

    npm i express mongoose dotenv
    
    • express: Используется для создания сервера.
    • mongoose: Используется для работы с базой данных MongoDB
    • dotenv: Используется для загрузки переменных окружения.
  • Создайте файл .env и сохраните вашу строку подключения в переменной под названием «MONGODB URI».

    MONGODB_URI=yourconnectionstring
    
  • Создайте файл server.js и вставьте этот код.

    const express = require("express");
    const mongoose = require("mongoose");
    
    const app = express();
    
    /* Loading the environment variables from the .env file. */
    require("dotenv").config();
    
    const PORT = process.env.PORT || 5000;
    const MONGODB_URI = process.env.MONGODB_URI || "mongodb://localhost/todoapiDB";
    
        /* Telling the application to use the express.json() middleware. This middleware will parse the body of
    any request that has a Content-Type of application/json. */
    app.use(express.json());
    
    /* This is a route handler. It is listening for a GET request to the root route of the application.
    When it receives a request, it will send back a response with the string "Hello World!". */
    app.get("/", (req, res) => {
      res.send("Hello World!");
    });
    
    /* Connecting to the database and then starting the server. */
    mongoose
      .connect(MONGODB_URI, { useNewUrlParser: true })
      .then(() => {
        app.listen(PORT, console.log("Server stated on port 5000"));
      })
      .catch((err) => {
        console.log(err);
      });
    
    
  • Выполните приведенную ниже команду и перейдите на сайт http://localhost:5000 в вашем браузере. Вы увидите что-то вроде этого. (Убедитесь, что у вас глобально установлен nodemon).

    npm run dev
    

Это означает, что сервер успешно запущен.

  • Создайте модель схемы для хранения активности.

    • Создайте папку под названием «models» и в ней создайте файл activity.model.js. Скопируйте и вставьте приведенный ниже код.
    const mongoose = require("mongoose");
    
    const Schema = mongoose.Schema;
    
    /* Creating a new schema for the activity model. */
    const activitySchema = new Schema({
      name: {
        type: String,
        required: true,
      },
      time: {
        type: String,
        required: true,
      },
    });
    
    module.exports = mongoose.model("Activity", activitySchema);
    
  • Реализуйте логику приложения в контроллерах.

    • Создайте папку «controllers» и в ней создайте файл activity.controller.js.
    • Нам нужно реализовать две вещи — 1) Получить все активности для показа на главной странице и 2) Добавить активность.
    const Activity = require("../models/activity.model");
    
    /**
     * It's an async function that uses the Activity model to find all activities and then returns a status of 200 with the activities in the response body.
     */
    const getActivities = async (req, res) => {
      try {
        const activities = await Activity.find();
        res.status(200).json(activities);
      } catch (err) {
        res.status(500).json({ message: err.message });
      }
    };
    
    /**
     * It creates a new activity and saves it to the database.
     */
    const addActivity = async (req, res) => {
      const activity = new Activity(req.body);
    
      try {
        const newActivity = await activity.save();
        res.status(201).json(newActivity);
      } catch (err) {
        res.status(400).json({ message: err.message });
      }
    };
    
    module.exports = {
      getActivities,
      addActivity,
    };
    
    
  • Зарегистрируйте маршруты для обработки запросов.

    • Создайте папку «routes» и в ней создайте файл activity.route.js. Скопируйте и вставьте приведенный ниже код.
    const express = require("express");
    
    const {
      getActivities,
      addActivity,
    } = require("../controllers/activity.controller");
    
    const router = express.Router();
    
    /* Creating a route for the get request. */
    router.get("/activities", getActivities);
    /* Creating a route for the post request. */
    router.post("/activity", addActivity);
    
    module.exports = router;
    
  • Окончательная структура папки будет выглядеть следующим образом.

    .
    ├── controllers
    │   └── activity.controller.js
    ├── models
    │   └── activity.model.js
    ├── routes
    │   └── activity.route.js
    ├── package-lock.json
    ├── package.json
    └── server.js
    
  • Используйте вышеуказанные маршруты в приложении.

    • Откройте файл server.js и используйте зарегистрированные маршруты.
    ...
    const ActivityRouter = require("./routes/activity.route");
    ...
    
    ...
    /* Telling the application to use the ActivityRouter for any requests that start with "/api". */
    app.use("/api", ActivityRouter);
    ...
    
  • Теперь наш бэкенд полностью готов к работе; мы можем добавлять и получать данные. Давайте рассмотрим, как подключить бэкэнд к фронтэнду.

Подключение клиента и сервера

Подключить клиента и сервер несложно. Это так же просто, как добавить URL.

  • Перейдите в папку клиента и создайте файл .env.local. Вставьте URL-адрес бэкенда в переменную.

    REACT_APP_BACKEND_URL=http://localhost:5000/api
    
  • Перейдите в папку клиента и откройте App.js. Когда пользователь нажмет кнопку Add, мы должны сделать POST-запрос к серверу через маршрут /api/activity.

    • Создайте функцию handleSubmit() и добавьте атрибут onSubmit к элементу формы.
    • В этой функции мы должны отправить запрос на сервер, передав в теле имя активности и время.

      ...
      const addActivity = async (event) => {
      event.preventDefault();
      
      const newActivity = {
        name: event.target.activity.value,
        time: event.target.time.value,
      };
      
      await fetch(`${process.env.REACT_APP_BACKEND_URL}/activity`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(newActivity),
      });
      
      event.target.activity.value = ""; // sets input empty after clicking submit
      event.target.time.value = ""; // sets input empty after clicking submit
      window.location.reload(); // reloads the window after sending request
      };
      ...
      
      ...
       <form onSubmit={addActivity}>
      ...
      
  • Введите имя активности и время, затем отправьте запрос. (Убедитесь, что сервер также запущен.)

  • В консоли браузера появится сообщение об ошибке.

  • Доступ к серверу запрещен политикой CORS (Cross-Origin Resource Sharing), что означает, что ваш сервер не разрешает доступ к своим ресурсам. Мы можем избежать этой проблемы, используя пакет cors npm.

    • Откройте папку сервера и установите пакет cors.
    npm i cors
    
    • Затем используйте этот пакет в server.js.
    ...
    const cors = require("cors");
    ...
    
    ...
    /* Allowing the frontend to access the backend. */
    app.use(cors());
    ...
    
    • Перезапустите сервер.
  • Попробуйте добавить активность. На этот раз все сработает.

  • Вы можете видеть данные, которые были добавлены в базу данных.

  • Теперь мы должны отобразить список недавно добавленных активностей.

    • Мы должны отображать активности сразу после рендеринга компонента. Мы можем сделать это с помощью хука useEffect(). Получите данные с сервера и сохраните их в состоянии.
    ...
     /* Fetching the data from the backend and setting the state of activities to the data. */
      useEffect(() => {
        const fetchData = async () => {
          const result = await fetch(
            `${process.env.REACT_APP_BACKEND_URL}/activities`
          );
          const data = await result.json();
          setActivities(data);
        };
        fetchData();
      }, []);
    ...
    
    • Теперь вы можете увидеть все активности на главной странице.

Размещение полнофункционального приложения на хостинге

Перед хостингом мы должны сохранить секреты и избежать фиксации ненужных файлов/папок.

  • Откройте папку сервера.
  • Инициализируйте git, создайте файл .gitignore и вставьте в него следующее.
node_modules
.env
Войти в полноэкранный режим Выйти из полноэкранного режима

Бэкенд

Для бэкенда будет использоваться Heroku.

  • Создайте репозиторий GitHub для серверного приложения и разместите в нем код сервера.
  • Войдите в Heroku.
  • Выберите «New» -> «Create new app».
  • Дайте приложению имя, выберите регион, а затем нажмите «Создать приложение».
  • Перейдите в «Настройки» -> «Конфигурационные параметры» -> «Раскрыть конфигурационные параметры» -> «Добавить переменные среды».
  • Перейдите в раздел «Обзор» и выберите GitHub в качестве механизма развертывания. Если вы еще этого не сделали, зарегистрируйтесь на GitHub.
  • Выберите свой репозиторий.
  • Выберите «Enable Automatic Deploys», если вы хотите создавать развертывание каждый раз, когда вы фиксируете репозиторий. Наконец, нажмите «Deploy Branch».
  • Запишите URL-адрес развернутого сайта.

Фронтенд

Netlify будет размещать нашу клиентскую/фронтенд часть.

  • Создайте репозиторий GitHub для клиентского приложения и разместите в нем код клиента.
  • Войдите в Netlify.
  • Выберите «Добавить сайт».
  • Выберите «GitHub».

  • Дайте разрешение GitHub.
  • Выберите свой репозиторий.

  • В «Основных настройках сборки»,

    • Для базового каталога — Оставьте пустым.
    • Для команды сборки — npm run build.
    • Для каталога публикации — «build».
  • Выберите «Show advanced» -> «New variable» В поле key введите REACT_APP_BACKEND_URL и скопированный ранее URL бэкенда в поле value. В конце URL-адреса поставьте /api.

  • Выберите «Развернуть сайт».

  • Вот и все! Откройте URL в браузере и получайте удовольствие 🎉🎉🎉.


Добавьте свои собственные функции и поделитесь URL в комментариях.


Читайте также:

  • Поток построения полностекевого веб-приложения
  • Различные способы соединения react frontend и node backend

Надеюсь, это дало вам представление о том, как разработать полнофункциональное MERN-приложение. Следите за мной, чтобы узнать больше 🚀🚀🚀.

Не забудьте подписаться на мою рассылку.

Спасибо!

Оцените статью
devanswers.ru
Добавить комментарий