В этом руководстве вы узнаете, как создать и развернуть приложение для ведения заметок. С помощью этого приложения вы можете создать свою задачу, обновить ее и удалить задачу.

Я и мой друг Кушал изучили и создали это приложение.

Ниже приведены технологии, которые мы используем в этом руководстве

1) Mongo Atlas. MongoDB Atlas - это полностью управляемая облачная база данных, разработанная теми же людьми, которые создают MongoDB. Atlas берет на себя всю сложность развертывания, управления и восстановления ваших развертываний в выбранном вами провайдере облачных услуг (AWS, Azure и GCP).

2) Moongoose. Mongoose - это библиотека MongoDB и моделирования объектных данных (ODM) на основе узлов. Он отслеживает отношения данных, выполняет проверку схемы и преобразует объекты кода в представления MongoDB. 3) Express Js

4) Reactjs. React - это библиотека JavaScript для создания декларативных, эффективных и настраиваемых пользовательских интерфейсов.

5) ExpressJ - Express - это минималистичная и гибкая платформа для веб-приложений Node. js с открытым исходным кодом, предназначенная для разработки веб-сайтов, веб-приложений, & API намного проще.

6) Digital Ocean - это уникальный провайдер облачного хостинга, который предлагает услуги облачных вычислений для бизнес-структур, чтобы они могли масштабироваться за счет развертывания приложений DigitalOcean, которые работают параллельно на нескольких облачных серверах без ущерба для производительности!

Если вас больше интересует полный код, вы можете увидеть его по следующему URL-адресу

Https://github.com/karkranikhil/todo-app

URL развернутого приложения

Https://todo-app-v9tsq.ondigitalocean.app/

I) Настройка проекта

Для вас мы настроили базовый код, чтобы вы могли сразу перейти к созданию кода, а не к настройке проекта. В коде базового проекта мы уже упоминали пакеты, которые собираемся использовать в этом проекте, внутри package.json.
Сначала клонируйте проект из следующего

Https://github.com/karkranikhil/todo-app/tree/project-setup

Выполните следующие команды

git clone https://github.com/karkranikhil/todo-app/tree/project-setup
npm install
npm run client

Как только вы сможете запустить все команды, вы увидите, что новое окно браузера открыто, и вы сможете увидеть следующий результат.

Хорошо Готово, ваш проект успешно настроен !!

II) Давайте настроим экспресс-сервер

В папке server нашего проекта создайте новый файл index.js.

Добавьте в файл следующий код

// require express
const  express = require("express");
const path = require("path");
var cors = require('cors')

// create express app
const  app = express();

// use middleware on express app
app.use(cors());
app.use(express.urlencoded())
app.use(express.json())
// define port to run express app
const  port = process.env.PORT || 5000;

// Add endpoint
app.get('/', (req, res) => {
res.send("Welcome to our Todo App");
});
// Listen to server
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});

В приведенном выше коде мы импортируем необходимый пакет, например express, cors и path. Все эти пакеты уже установлены с помощью команды npm install. После этого мы создаем приложение Express. После создания нашего приложения мы упомянули несколько промежуточных программ, использующих метод app.use. Все запросы API проходят через промежуточное программное обеспечение. После этого мы определили порт, на котором будет работать наш сервер.

используя app.get, мы создаем наш первый API, который будет прослушивать метод GET и возвращать на экране сообщение «Добро пожаловать в наше приложение Todo».

В конце мы вызываем порт прослушивания app и передаем номер port (5000) и обратный вызов, который печатает msg на консоли после запуска нашего сервера.

Давайте запустим наш сервер, используя следующую команду

node server/index.js

После успешного запуска вашего сервера перейдите по следующему URL-адресу

Http: // localhost: 5000

вы увидите следующий результат

Итак, мы успешно создали наш первый экспресс API.

III) Настройка нашего MongoDB Atlas

Создайте учетную запись MongoDB Atlas

MongoDB Atlas - это платформа MongoDB Database-as-a-Service, что означает, что они настраивают и размещают базу данных для вас. Тогда ваша единственная ответственность будет заключаться в том, чтобы заполнить вашу базу данных тем, что имеет значение: данными.

  • Перейдите сюда, чтобы зарегистрировать новую учетную запись MongoDB Atlas.
  • Заполните регистрационную форму своими данными и нажмите Зарегистрироваться.

Создать новый кластер

  • На следующей странице введите название своей организации, название проекта, выберите JavaScript в качестве предпочтительного языка программирования и нажмите зеленую кнопку Продолжить.
  • Нажмите кнопку Создать кластер в разделе "Общие кластеры". Это должен быть единственный бесплатный вариант.
  • В раскрывающемся списке Поставщик облака и регион оставьте значение по умолчанию (обычно AWS).
  • В раскрывающемся списке Уровень кластера оставьте значение по умолчанию M0 Sandbox (Shared RAM, 512 MB Storage).
  • В раскрывающемся списке Имя кластера вы можете дать своему кластеру имя или оставить его по умолчанию Cluster 0.
  • Нажмите зеленую кнопку Создать кластер внизу экрана.
  • Теперь вы должны увидеть сообщение Your cluster is being created. New clusters take between 1-3 minutes to provision. Подождите, пока кластер не будет создан, прежде чем переходить к следующему шагу.

Создайте нового пользователя для базы данных

  • В левой части экрана нажмите Доступ к базе данных.
  • Нажмите зеленую кнопку Добавить нового пользователя базы данных.
  • В модальном окне введите новое имя пользователя и пароль.
  • В разделе Права пользователя базы данных оставьте вариант по умолчанию Чтение и запись в любую базу данных.
  • Нажмите кнопку Добавить пользователя, чтобы создать нового пользователя.

Разрешить доступ со всех IP-адресов

  • В левой части экрана нажмите Доступ к сети.
  • Нажмите зеленую кнопку Добавить IP-адрес.
  • В модальном окне нажмите кнопку РАЗРЕШИТЬ ДОСТУП ОТ ЛЮБОГО ОТДЕЛА. Вы должны увидеть 0.0.0.0/0 в поле записи списка доступа.
  • Нажмите зеленую кнопку Подтвердить.

Подключитесь к вашему кластеру

  • Нажмите зеленую кнопку Приступить к работе в левом нижнем углу экрана, и теперь вы увидите последний шаг: Подключитесь к кластеру, нажмите на него.
  • В левой части экрана нажмите Кластеры.
  • Нажмите кнопку Подключить для своего кластера.
  • В модальном всплывающем окне нажмите Подключить приложение.
  • Вы должны увидеть URI, который вы будете использовать для подключения к своей базе данных, примерно так: mongodb+srv://<username>:<password>@<cluster-name>.mongodb.net/<db-name>?retryWrites=true&w=majority.
  • Нажмите кнопку Копировать, чтобы скопировать свой URI в буфер обмена.

Обратите внимание, что поля <username>, <cluster-name> и <db-name> скопированного вами URI уже заполнены. Все, что вам нужно сделать, это заменить поле <password> тем, которое вы создали на предыдущем шаге.

IV. Подключение MongoDB к нашему экспресс-приложению

Под сервером в папке создайте новый файл с именем config.js и вставьте следующий код

// Export mongoose
const mongoose = require(“mongoose”);
//Assign MongoDB connection string to Uri and declare options settings
const uri = `mongodb+srv://${USERNAME}:${PASSWORD}@todocluster.4vnhp.mongodb.net/myFirstDatabase?retryWrites=true&w=majority`
// Declare a variable named option and assign optional settings
const options = {
useNewUrlParser: true,
useUnifiedTopology: true
};
// Connect MongoDB Atlas using mongoose connect method
mongoose.connect(uri, options).then(() => {
console.log(“Database connection established!”);
},err => {
{
console.log(“Error connecting Database instance due to:”, err);
}
});

В приведенном выше коде сначала мы импортируем библиотеку мангуста, а затем добавляем URL-адрес, который мы скопировали из нашего атласа MongoDB.

Примечание ** замените USERNAME и PASSWORD своими учетными данными

Monoogese предоставляет нам метод подключения, который помогает нам подключаться к нашей базе данных mongo. если возникает какая-либо ошибка, она печатается в консоли.

Нет, наша конфигурация готова, теперь мы должны вызвать это на нашем сервере index.js

Внутри index.js добавьте следующий жирным шрифтом код

app.use(cors());
app.use(express.urlencoded())
app.use(express.json())
// Import DB Connection
require(“./config.js”);

давайте снова запустим сервер с той же командой

node server/index.js

Вы увидите сообщение «Соединение с базой данных установлено!»

на консоли, как показано ниже

V. Создание API для нашей задачи создание, чтение, обновление, удаление

Давайте создадим несколько новых файлов controller.js, model.js, routes.js в папке сервера, как показано ниже.

Внутри Model.js файла добавьте следующий код.

// Import mongoose
const mongoose = require(“mongoose”);
// Declare schema and assign Schema class
const Schema = mongoose.Schema;
// Create Schema Instance and add schema propertise
const TodoSchema = new Schema({
text: {
type:String,
required:true
},
status:{
type:Boolean,
required:true
},
createdOn: {
type:Date,
default:Date.now
}
});
// create and export model
module.exports = mongoose.model(“todoModel”, TodoSchema);

В model.js мы создаем схему для нашей базы данных. Если мы посмотрим на приведенный выше код, мы используем три поля

а) текст - для хранения данных

б) статус - для хранения статуса

в) createdOn - для хранения даты создания задачи.

Внутри routes.js файла добавьте следующий код

// create App function
module.exports = function(app) {
var todoList = require(‘./controller’);
// todoList Routes
// get and post request for /todos endpoints
app
.route(“/todos”)
.get(todoList.listAllTodos)
.post(todoList.createNewTodo);
// put and delete request for /todos endpoints
app
.route(“/todo/:id”)
.put(todoList.updateTodo)
.delete(todoList.deleteTodo);
};

routes.js сообщает нам, какой метод вызывать внутри контроллера на основе метода и конечной точки.

Внутри controller.js файла добавьте следующий код

// import Todo Model
const Todo = require(“./model”);
// DEFINE CONTROLLER FUNCTIONS
// listAllTodos function — To list all todos
exports.listAllTodos = (req, res) => {
Todo.find({}, (err, todo) => {
if (err) {
 res.status(500).send(err);
}
 res.status(200).json(todo);
});
};
// createNewTodo function — To create new todo
exports.createNewTodo = (req, res) => {
let newTodo = new Todo (req.body);
newTodo.save((err, todo) => {
if (err) {
res.status(500).send(err);
}
res.status(201).json(todo);
});
};
// updateTodo function — To update todo status by id
exports.updateTodo = (req, res) => {
Todo.findOneAndUpdate({ _id:req.params.id }, req.body, { new:true }, (err, todo) => {
if (err) {
res.status(500).send(err);
}
res.status(200).json(todo);
});
};
// deleteTodo function — To delete todo by id
exports.deleteTodo = async ( req, res) => {
await Todo.deleteOne({ _id:req.params.id }, (err) => {
if (err) {
return res.status(404).send(err);
}
res.status(200).json({ message:”Todo successfully deleted”});
});
};

Внутри контроллера мы написали методы, которые вызываются на основе конечной точки API и метода, определенного в routes.js

В конце концов, мы должны подключить наш файл маршрута внутри index.js

Добавьте следующий выделенный код в index.js

// Import DB Connection
require(“./config.js”);
// Import API route
var routes = require(‘./routes’); //importing route
routes(app);

Пришло время протестировать наши API.

VI. Тестирование API с помощью почтальона

Перед тестированием давайте снова запустим сервер с помощью следующей команды

node server/index.js

Давайте откроем почтальон. Вы можете использовать и инструмент тестирования API

а) Тестирование базовой базовой конечной точки

http://localhost:5000

он вернет следующий результат

б) Добавление задачи в БД

Для добавления мы должны использовать следующий URL-адрес с методом POST

localhost:5000/todos

И как только он будет добавлен, вы увидите следующий результат

в) Обновление задачи в БД

Для обновления задачи нам нужен идентификатор задачи, которую мы хотим обновить, и в нашем случае мы будем использовать ранее созданный идентификатор задачи.
мы должны использовать следующий URL-адрес с методом PUT

localhost:5000/todo/60eecba5dd8f6b50db4deb52

И как только задача будет обновлена, вы увидите следующий результат

г) Получение задач из БД

Для получения задачи мы должны использовать следующий URL-адрес с методом GET

localhost:5000/todos

И как только задачи будут загружены, вы увидите следующий результат. Он вернет все задачи, доступные внутри БД

д) Удаление задачи из БД

Для удаления задачи нам нужен идентификатор задачи, которую мы хотим удалить, и в нашем случае мы будем использовать ранее созданный идентификатор задачи.
мы должны использовать следующий URL-адрес с методом DELETE

localhost:5000/todo/60eecba5dd8f6b50db4deb52

И как только задача будет удалена, вы увидите следующий результат.

Ура, все наши API работают !!

VII. Настройка пользовательского интерфейса и интеграция API

Откройте свой проект и создайте следующую папку и файлы

а) Создайте новую папку под названием api в папке src и добавьте в нее два файла httpClient.js and todoApi.js

б) Создайте новую папку под названием components в папке src и в ней создайте три новые папки Todo, TodoItem, and TodoList.

  • В папке Todo добавьте два файла Todo.css and Todo.js
  • В папке TodoItem добавьте два файла TodoItem.css and TodoItem.js
  • В папке TodoList добавьте два файла TodoList.css and TodoList.js

c) Создайте новую папку под названием redux в папке src и в ней создайте два новых файла actions.js and reducers.js

г) Добавьте store.js файл в папку src.

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

Давайте добавим следующий код в соответствующий файл

httpClient.js

Этот файл используется для вызова HTTP-запроса. Мы используем пакет axios для вызова API

import axios from ‘axios’
//Create a Http Client using Axios. Further modifications in this layer can be done later like Authorization.
const post = (url = ‘’, data = ‘’, config = {}) => {
return axios.post(url, data, config)
}
const get = (url) => {
return axios(url)
}
const put = (url = ‘’, data = ‘’, config = {}) => {
return axios.put(url, data, config)
}
//Cannot contain a delete method — Cause delete is a keyword.
const del = (url = ‘’, config = {}) => {
return axios.delete(url, config)
}
//Encapsulating in a JSON object
const HttpClient = {
post,
get,
put,
delete: del
}
export {HttpClient}

todoApi.js

Этот файл используется для вызова методов, определенных в httpClient.

мы настроили наш API и его путь для его вызова.

import {HttpClient} from ‘./httpClient’;
// This is the API. The backend root URL can be set from here.
console.log(process.env.REACT_APP_PROD_URL);
const port = process.env.PORT || 5000;
const API = process.env.REACT_APP_PROD_URL || ‘https://todo-app-v9tsq.ondigitalocean.app' || `http://localhost:${port}`
//Setting the todos URI
const TODO_API = `${API}/todos`
// The CRUD Operations of the Todo Resource.
//Create
const createTodo = todo => {
return HttpClient.post(TODO_API, todo)
}
//Read
const getTodos = () => {
return HttpClient.get(TODO_API)
}
//Update
const updateTodo = todo => {
return HttpClient.put(`${API}/todo/${todo._id}`, todo)
}
//Delete
const removeTodo = todo => {
return HttpClient.delete(`${API}/todo/${todo._id}`)
}
//Encapsulating in a JSON object
const TodoApi = {createTodo, getTodos, updateTodo, removeTodo}
export {TodoApi}

todoApi.js

Этот файл используется для вызова методов, определенных в httpClient.

мы настроили наш API и его путь для его вызова.

Мы использовали Redux для обучения, поэтому в этом проекте мы использовали redux

store.js

Этот файл используется для создания хранилища redux, которое является глобальным хранилищем.

import {createStore, combineReducers, applyMiddleware} from ‘redux’;
import thunkMiddleware from ‘redux-thunk’
import { createLogger } from ‘redux-logger’
import { todosReducer } from ‘./redux/reducers’;
const reducers = {
todosReducer,
};
const rootReducer = combineReducers(reducers);
// Create the redux logging middleware
const loggerMiddleware = createLogger()
export const configureStore= (preloadedState) => createStore(
rootReducer,
preloadedState,
applyMiddleware(
thunkMiddleware,
loggerMiddleware
)
);

actions.js

действие - это объект, содержащий полезную информацию. Они являются единственным источником информации для магазина Redux, который необходимо обновлять.

import { TodoApi } from ‘../api/todoApi’
//Create
export const CREATE_TODO = ‘CREATE_TODO’
export const CREATE_TODO_SUCCESS = ‘CREATE_TODO_SUCCESS’
export const CREATE_TODO_ERROR = ‘CREATE_TODO_ERROR’
//Read
export const GET_TODOS = ‘GET_TODOS’
export const GET_TODOS_SUCCESS = ‘GET_TODOS_SUCCESS’
export const GET_TODOS_ERROR = ‘GET_TODOS_ERROR’
//Update
export const UPDATE_TODO = ‘UPDATE_TODO’
export const UPDATE_TODO_SUCCESS = ‘UPDATE_ODO_SUCCESS’
export const UPDATE_TODO_ERROR = ‘UPDATE_TODO_ERROR’
//Remove
export const REMOVE_TODO = ‘REMOVE_TODO’;
export const REMOVE_TODO_SUCCESS = ‘REMOVE_TODO_SUCCESS’
export const REMOVE_TODO_ERROR = ‘REMOVE_TODO_ERROR’
//Create
//The dispatch and getstate function is provided by the Redux-Thunk middleware, we can dispatch actions with it.
export function CreateTodo(todo){
return (dispatch, getState) => {
return TodoApi.createTodo(todo).then(res => {
dispatch(CreateTodoSuccess(res.data))
})
}
}
export function CreateTodoSuccess(todo){
return {
type:CREATE_TODO_SUCCESS,
todo
}
}
//Read
export function GetTodos(){
return (dispatch, getState) => {
return TodoApi.getTodos().then(res => {
dispatch(GetTodoSuccess(res.data))
})
}
}
export function GetTodoSuccess(todos){
return {
type:GET_TODOS_SUCCESS,
todos
}
}
//Remove
export function RemoveTodo(todo) {
return (dispatch, getState) => {
TodoApi.removeTodo(todo).then(res => {
dispatch(RemoveTodoSuccess(todo))
})
}
}
export function RemoveTodoSuccess(todo) {
return {
type: REMOVE_TODO_SUCCESS,
todo,
_id: todo._id
}
}
//update
export function UpdateTodo(todo){
return (dispatch) => {
return TodoApi.updateTodo(todo).then(res => {
dispatch(UpdateTodoSuccess(res.data))
})
}
}
export function UpdateTodoSuccess(todo){
return {
type:UPDATE_TODO_SUCCESS,
todo
}
}

redurs.js

Редукторы обновляют магазин в зависимости от значения действия.

import * as TodoActions from “./actions”;
export const todosReducer = (state = [], action) => {
const { type } = action;
switch(type) {
// Create
case TodoActions.CREATE_TODO_SUCCESS: {
return [
…state,
action.todo
];
}
//Read
case TodoActions.GET_TODOS_SUCCESS: {
return action.todos || [];
}
//update
case TodoActions.UPDATE_TODO_SUCCESS: {
return state.map(item=>item._id === action.todo._id ? {…action.todo}:{…item})
}
//Remove
case TodoActions.REMOVE_TODO: {
return state.map(s => todo(s, action))
}
case TodoActions.REMOVE_TODO_SUCCESS: {
return state.filter(todo => todo._id !== action._id);
}
default:
return state;
}
}

Todo.js

import React from ‘react’;
import { connect } from ‘react-redux’;
import ‘./Todo.css’;
import { CreateTodo } from ‘../../redux/actions’;
const Todo = ({todoList, onCreatePressed}) => {
const [newText, setNewText] = React.useState(“”);
return (
<div className=”new-todo”>
<input
type=”text”
className=”new-todo-input”
placeholder=”Task title”
value={newText}
onChange={e => setNewText(e.target.value)}/>
<div className=”button-container”>
<button
onClick={()=> {
const isDuplicate = todoList.some(todo => todo.text === newText)
if (!isDuplicate){
onCreatePressed({“text”: newText, “status”: true});
setNewText(‘’);
}
}}
className=”add-button”> Create Task
</button>
</div>
</div>
);
}
const mapStateToProps = state => ({
todoList: state.todosReducer
});
const mapDispatchToProps = dispatch => ({
onCreatePressed: text => dispatch(CreateTodo(text)),
});
export default connect(mapStateToProps, mapDispatchToProps)(Todo);;

Todo.css

.new-todo {
border: 2px solid #cccccc;
margin: 0 auto;
display: flex;
align-items: center;
max-width: 700px;
}
.new-todo-input {
border: none;
background: #2b2e3e;
padding: 1rem;
border-radius: 5px;
color: #fff;
width: 100%;
flex: 1;
margin: 10px;
outline: none;
}
.new-todo-inputedit {
border: auto;
outline: auto;
}
.new-todo .button-container {
padding: 5px;
}
.add-button {
border: none;
background-color: #9135f6;
color: white;
border-radius: 5px;
font-size: 1rem;
padding: 1rem;
width: 100%;
cursor:pointer;
}

TodoList.js

import React from ‘react’;
import { connect } from ‘react-redux’;
import TodoItem from ‘../TodoItem/TodoItem’;
import ‘./TodoList.css’;
import { RemoveTodo } from ‘../../redux/actions’;
const TodoList = ({todos = [], onRemovePressed}) => (
<div className=”todo-wrapper”>
{todos.map(todo => <TodoItem todo={todo} onRemovePressed={onRemovePressed} key={todo?.text}/>)}
</div>
);
const mapStateToProps = state => ({
todos: state.todosReducer
});
const mapDispatchToProps = dispatch => ({
onRemovePressed: text => dispatch(RemoveTodo(text)),
});
export default connect(mapStateToProps, mapDispatchToProps)(TodoList);

todoList.css

.todo-wrapper {
display: flex;
align-items: center;
justify-content: center;
padding-top: 2rem;
flex-wrap: wrap;
}

todoItem.js

import React, {useState} from ‘react’;
import { useDispatch } from ‘react-redux’
import ‘./TodoItem.css’;
import { UpdateTodo } from ‘../../redux/actions’;
const TodoItem = ({todo, onRemovePressed}) => {
const dispatch = useDispatch()
const [isEdit, setIsEdit] = useState(null)
const [updatedText, setUpdatedText]= useState(todo?.text)
const editUpdateHandler = () =>{
if(isEdit){
dispatch(UpdateTodo({…todo, “text”:updatedText}))
} else {
setIsEdit(true)
}
}
return (
<div className=”todo-item”>
{isEdit ? <input
type=”text”
className=”new-todo-input new-todo-inputedit”
placeholder=”Task title”
value={updatedText}
onChange={e => setUpdatedText(e.target.value)}/> :<p>{todo.text}</p>}
<div className=”button-container”>
{/* <button className=”mark-completed-button”> Mark as Completed </button> */}
<p>{new Date(todo.createdOn).toLocaleDateString()}</p>
<button className=”button update-button” onClick={() => editUpdateHandler()}> {isEdit ? “update” : “Edit”} </button>
<button className=”button remove-button” onClick={() => onRemovePressed(todo)}> Delete </button>
</div>
</div>
)}
export default TodoItem;

todoItem.css

.todo-item {
margin: 1rem;
background: #2b2e3e;
border-radius: 16px;
box-shadow: 0px 0px 3px #d1b8ef;
display: flex;
padding:0.5rem;
justify-content: space-between;
align-items: center;
min-height: 200px;
width: 200px;
display: flex;
flex-direction: column;
width: 260px;
}
.todo-item .button-container {
display: flex;
align-items: center;
}
.button {
border: none;
color: white;
padding: 10px;
cursor:pointer;
border-radius: 10px;
margin-left:1rem;
}
.remove-button{
background:#ff6e6e;
}
.update-button{
background:#f19732;
}
.mark-completed-button {
border: none;
background-color: cyan;
color: black;
padding: 10px;
margin: 5px;
}

App.js - добавить все компоненты в app.js

import { hot } from ‘react-hot-loader’;
import React from ‘react’;
import “./App.css”;
import TodoList from ‘./components/TodoList/TodoList’
import Todo from ‘./components/Todo/Todo’;
const App = () => (
<div className=”App”>
<h1>Organize your work</h1>
<Todo />
<TodoList />
</div>
);
export default hot(module)(App);

index.js

нам нужно обновить index.js, чтобы интегрировать redux в приложение

import React from ‘react’;
import ReactDom from ‘react-dom’;
import App from ‘./App’;
import { Provider } from ‘react-redux’;
import { configureStore } from “./store”;
import * as TodoActions from ‘./redux/actions’
const store = configureStore()
store.dispatch(TodoActions.GetTodos())
ReactDom.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById(‘root’),
);

Давайте протестируем приложение, выполнив следующую команду

npm run dev

после успешного запуска вы увидите следующий вывод

VIII. Создайте пакет и обслуживайте интерфейс с экспресс-сервера

Чтобы собрать пакет нашего интерфейса, выполните следующую команду

npm build:client

это создаст папку dist внутри нашего проекта, как показано ниже

Перейдите на server / index.js и добавьте следующую выделенную строку

// Import DB Connection
require(“./config.js”);
//serving frontend using middlewares
app.use(express.static(path.join(__dirname, “..”, “dist”)));
app.use(express.static(“public”));

Теперь давайте запустим приложение, используя следующую команду

npm run dev

Вы увидите тот же результат, но на этот раз приложение работает на порту 5000.

IX - Развертывание приложения в цифровом океане

создать аккаунт на D igital Ocean

После создания перейдите в приложение и создайте новое приложение.

Выберите источник вашего приложения. В моем случае мой код находится в GitHub, поэтому я выбираю github

Выберите имя репозитория и сохраните мастер ветки

Установите свою конфигурацию

Назовите свои веб-службы

Нажмите запустить базовое приложение

Теперь приступайте к развертыванию, и после развертывания вы получите развернутый URL-адрес

Откройте URL-адрес, и ваше приложение ВВЕРХ и работает

использованная литература

Https://github.com/karkranikhil/todo-app/tree/master

Https://cloud.digitalocean.com/

Спасибо Кушалу Джайну за помощь и вклад в эту статью.