Всем привет. В преддверии старта курса «Fullstack разработчик JavaScript», хотим поделиться небольшим материалом, который был написан нашим внештатным автором.
Express один из самых популярных веб-фреймворков, который поддерживает роутинг, миддлвейрс и систему шаблонов. Делать бэкенд на Node.js без Express в 2020 году — довольно странное занятие, ведь Express де-факто — каркас для создания веб-приложения на Node.js.
Сегодня мы попробуем создать несложное CRUD API используя базу данных MySQL. Опытный в Node.js читатель спросит, а где же MongoDB, с которым Node.js обычно применятся в паре но, скажу сразу, это статья больше для PHP разработчиков, которые хотят немного потрогать Node.js, и чтобы смягчить переход в новую экосистему мы воспользуемся MySQL. API мы будем создавать для несложного Todo приложения, на тот случай, если кто-то захочет к своей todo (и даже неважно, написанной с помощью React или нет), присоединить немного бэка и поиграть с ним.
В нашем приложении можно будет создавать, получать, обновлять и удалять Todo. В общем, у нас будет минимальный набор функций CRUD (create read update delete).
В конце мы совместим приложение c приложением на React и все протестируем.
Для начала приведу структуру файлов приложения:
Дальше я приведу таблицу действий и методов, которые есть в нашем приложении:
Переходим в вашу любимую директорию, запускаем терминал и создаем ваше приложение. Кстати, из заголовка, наверное, понятно, что Node.js у вас уже должна быть установлена. Если вы еще этого не сделали, тоэтого просто не может быть скачайте по ссылке отсюда.
Дальше необходимо инициализировать наше приложение с помощью npm init. Т.к. приложение у нас скорее тестовое и обучающее, я воспользуюсь командной, которая заполнит все данные по дефолту, чтобы не тратить время на мелкие детали:
Если что, потом руками в
Потом нам нужно поставить все необходимые для работы приложения пакеты:
Если вы собираетесь отправлять потом вашу разработку на github, вам стоит создать скрытый файли не позориться. Пишем:
Там вписываем
В корневой папке проекта создаем файл
Теперь мы можем запустить сервер с помощью:
Express нам нужен для создания своего api, а пакет body-parser помогает нам парсить request и создавать
Сейчас наш сервер умеет следующее:
Первично наше приложение работает, дальше можно заняться базой данных.
Я очень надеюсь, что у читателя данной статьи нет проблемы с тем, чтобы самостоятельно скачать и установить MySQL и MySQLWorkBranch. Дальше вы самостоятельно создаете scheme(БД) с названием, которое вам больше нравится (в моем случае TODO), и потом выбрать молнию-запрос и скопировать/набрать следующую команду:
В нашей базе данных будет все по минимуму: только id и сам текст дел. Однако добавить ещё колоночку, в которой может описана, к примеру, срочность вашего дела, надеюсь, проблем не вызовет.
Давайте установим и сконфигурируем соединение с базой данных. Мы создадим новую папку app прямо в нашей корневой папке, и там создадим файл
После этого создаем папку для описания наших моделей app/mode, в которой мы потом создадим модель:
В папке
Итого, нам придется заняться следующими делами:
Остальную часть кода я размещу в spoiler, потому, что не вижу смысла приводить его весь, ведь там по сути повторяется паттерн кода, меняются только sql — команды и аргументы:
На этом пока все. На подходе следующая часть этой статьи, в которой мы закончим написание бэка и примемся за его тестирование. И по традиции, несколько полезных ссылок:
Express один из самых популярных веб-фреймворков, который поддерживает роутинг, миддлвейрс и систему шаблонов. Делать бэкенд на Node.js без Express в 2020 году — довольно странное занятие, ведь Express де-факто — каркас для создания веб-приложения на Node.js.
Сегодня мы попробуем создать несложное CRUD API используя базу данных MySQL. Опытный в Node.js читатель спросит, а где же MongoDB, с которым Node.js обычно применятся в паре но, скажу сразу, это статья больше для PHP разработчиков, которые хотят немного потрогать Node.js, и чтобы смягчить переход в новую экосистему мы воспользуемся MySQL. API мы будем создавать для несложного Todo приложения, на тот случай, если кто-то захочет к своей todo (и даже неважно, написанной с помощью React или нет), присоединить немного бэка и поиграть с ним.
«Архитектура» и суть нашего приложения
В нашем приложении можно будет создавать, получать, обновлять и удалять Todo. В общем, у нас будет минимальный набор функций CRUD (create read update delete).
В конце мы совместим приложение c приложением на React и все протестируем.
Для начала приведу структуру файлов приложения:
Дальше я приведу таблицу действий и методов, которые есть в нашем приложении:
Методы | Url | Действия |
---|---|---|
GET | /deals | получение всех дел |
GET | /deals/2 | Получение id c номером 2 |
POST | /deals | добавление нового дела |
PUT | /deals/3 | Обновить пользователя с id=3 |
DELETE | /deals/3 | удалить пользователя с id=3 |
DELETE | /deals | удалить всех пользователей |
Создание своего Node.js приложения
Переходим в вашу любимую директорию, запускаем терминал и создаем ваше приложение. Кстати, из заголовка, наверное, понятно, что Node.js у вас уже должна быть установлена. Если вы еще этого не сделали, то
$ mkdir CRUD_API
$ cd CRUD_API
Дальше необходимо инициализировать наше приложение с помощью npm init. Т.к. приложение у нас скорее тестовое и обучающее, я воспользуюсь командной, которая заполнит все данные по дефолту, чтобы не тратить время на мелкие детали:
npm init -y
Если что, потом руками в
package.json
вы сможете поменять данные на те, которые вам нужны: репозиторий github, тэги, автора, и т.д. Потом нам нужно поставить все необходимые для работы приложения пакеты:
npm i express mysql body-parser --save
Если вы собираетесь отправлять потом вашу разработку на github, вам стоит создать скрытый файл
.gitignore
, чтобы не таскать с собой тяжелейшие node_modules touch .gitignore
code .gitignore
Там вписываем
node_modules
, в дальнейшем в этот файл вы сможете вписать наименования папок и файлов, которые хотите увидеть потом на удаленном сервере.Базовая настройка Express
В корневой папке проекта создаем файл
server.js
: const express = require("express");
const bodyParser = require("body-parser");
const app = express();
//делаем наш парсинг в формате json
app.use(bodyParser.json());
// парсит запросы по типу: application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
// простой response - request
app.get("/", (req, res) => {
res.json({ message: "Это стартовая страница нашего приложения" });
});
// установить порт, и слушать запросы
app.listen(3001, () => {
console.log("Сервер запущен на 3001 порту");
});
Теперь мы можем запустить сервер с помощью:
node server.js
Express нам нужен для создания своего api, а пакет body-parser помогает нам парсить request и создавать
req.body
, который пригодится для работы роутинга.Сейчас наш сервер умеет следующее:
- Создаем Express app, который отдает body-parser миддлевеир используя app.use()
- у нас есть простой get, просто для тестирования работы приложения
- Слушаем 3001 порт на все входящие изменения
Первично наше приложение работает, дальше можно заняться базой данных.
Создаем свою таблицу данных MySQL
Я очень надеюсь, что у читателя данной статьи нет проблемы с тем, чтобы самостоятельно скачать и установить MySQL и MySQLWorkBranch. Дальше вы самостоятельно создаете scheme(БД) с названием, которое вам больше нравится (в моем случае TODO), и потом выбрать молнию-запрос и скопировать/набрать следующую команду:
CREATE TABLE IF NOT EXISTS `todo` (
id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
text varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
В нашей базе данных будет все по минимуму: только id и сам текст дел. Однако добавить ещё колоночку, в которой может описана, к примеру, срочность вашего дела, надеюсь, проблем не вызовет.
Конфигурация & коннект с нашей базой данных
Давайте установим и сконфигурируем соединение с базой данных. Мы создадим новую папку app прямо в нашей корневой папке, и там создадим файл
db.config.js
в папке config
, вот примерно с таким содержанием, которое зависит от ваших настроек в MySQLWorkBranch. В моем случае файл будет выглядеть вот так: module.exports = {
HOST: "localhost",
USER: "pavel",
PASSWORD: "",
DB: "TODO"
};
После этого создаем папку для описания наших моделей app/mode, в которой мы потом создадим модель:
const mysql = require("mysql");
const dbConfig = require("../config/db.config.js");
// создаем соединение с нашей базой данных
const connection = mysql.createConnection({
host: dbConfig.HOST,
user: dbConfig.USER,
password: dbConfig.PASSWORD,
database: dbConfig.DB
});
// открываем наше соединение с базой данных
connection.connect(err => {
if (err) throw error;
console.log("успешно соединено с базой данных");
});
module.exports = connection;
//экспортируем наше соединение
Создаем Модель
В папке
model
, мы создаем файл, который называется deal.model.js
. Если у вас возникает вопрос, что же такое вообще модель, вам стоит прочитать статью вроде этой и ознакомиться с паттерном проектирования MVC. Я собираюсь создать конструктор для Deal объекта, и использовать connection для следующих CRUD функций:- создание нового дела
- нахождение дела по id
- получение всех дел
- возможность обновлять наше дело по id
- Удаление одного дела по id
- полное удаление всех дел
Итого, нам придется заняться следующими делами:
// конструктор нашего дела
const Deal = function(deal) {
this.text = deal.text;
};
//у нашей модели будут функции, с помощью которых можно осуществлять все операции CRUD, которые были озвучены в начале статьи:
Deal.create = (newDeal, result) => {
sql.query("INSERT INTO TODO SET ?", newDeal, (err, res) => {
//операция вставки из SQL
if (err) {
console.log("error: ", err);
result(err, null);
//немного бедная обработка ошибок, но на первое время хватит
return;
}
console.log("Дело сделано", { id: res.insertId, ...newDeal });
result(null, { id: res.insertId, ...newDeal });
});
};
Остальную часть кода я размещу в spoiler, потому, что не вижу смысла приводить его весь, ведь там по сути повторяется паттерн кода, меняются только sql — команды и аргументы:
остальная часть кода
Deal.findById = (dealId, result) => {
sql.query(`SELECT * FROM TODO WHERE id = ${dealId}`, (err, res) => {
if (err) {
console.log(«error: », err);
result(err, null);
return;
}
if (res.length) {
console.log(«найдено дело: », res[0]);
result(null, res[0]);
return;
}
// когда ничего не удалось найти
result({ kind: «not_found» }, null);
});
};
Deal.getAll = result => {
sql.query(«SELECT * FROM TODO», (err, res) => {
if (err) {
console.log(«error: », err);
result(null, err);
return;
}
console.log(«deals: », res);
result(null, res);
});
};
Deal.updateById = (id, deal, result) => {
sql.query(
«UPDATE TODO SET text =? WHERE id = ?»,
[deal.text, id],
(err, res) => {
if (err) {
console.log(«error: », err);
result(null, err);
return;
}
if (res.affectedRows == 0) {
result({ kind: «not_found» }, null);
return;
}
console.log(«Обновлено дело », { id: id, ...deal });
result(null, { id: id, ...deal });
}
);
};
Deal.remove = (id, result) => {
sql.query(«DELETE FROM TODO WHERE id = ?», id, (err, res) => {
if (err) {
console.log(«error: », err);
result(null, err);
return;
}
if (res.affectedRows == 0) {
// если дело не удалось получить по id
result({ kind: «not_found» }, null);
return;
}
console.log(«Удален пользователь с », id);
result(null, res);
});
};
Deal.removeAll = result => {
sql.query(«DELETE FROM TODO», (err, res) => {
if (err) {
console.log(«error: », err);
result(null, err);
return;
}
console.log(`deleted ${res.affectedRows} deals`);
result(null, res);
});
};
sql.query(`SELECT * FROM TODO WHERE id = ${dealId}`, (err, res) => {
if (err) {
console.log(«error: », err);
result(err, null);
return;
}
if (res.length) {
console.log(«найдено дело: », res[0]);
result(null, res[0]);
return;
}
// когда ничего не удалось найти
result({ kind: «not_found» }, null);
});
};
Deal.getAll = result => {
sql.query(«SELECT * FROM TODO», (err, res) => {
if (err) {
console.log(«error: », err);
result(null, err);
return;
}
console.log(«deals: », res);
result(null, res);
});
};
Deal.updateById = (id, deal, result) => {
sql.query(
«UPDATE TODO SET text =? WHERE id = ?»,
[deal.text, id],
(err, res) => {
if (err) {
console.log(«error: », err);
result(null, err);
return;
}
if (res.affectedRows == 0) {
result({ kind: «not_found» }, null);
return;
}
console.log(«Обновлено дело », { id: id, ...deal });
result(null, { id: id, ...deal });
}
);
};
Deal.remove = (id, result) => {
sql.query(«DELETE FROM TODO WHERE id = ?», id, (err, res) => {
if (err) {
console.log(«error: », err);
result(null, err);
return;
}
if (res.affectedRows == 0) {
// если дело не удалось получить по id
result({ kind: «not_found» }, null);
return;
}
console.log(«Удален пользователь с », id);
result(null, res);
});
};
Deal.removeAll = result => {
sql.query(«DELETE FROM TODO», (err, res) => {
if (err) {
console.log(«error: », err);
result(null, err);
return;
}
console.log(`deleted ${res.affectedRows} deals`);
result(null, res);
});
};
На этом пока все. На подходе следующая часть этой статьи, в которой мы закончим написание бэка и примемся за его тестирование. И по традиции, несколько полезных ссылок: