Интеграция Javascript с Backend Frameworks, такими как Node.js и Express
Table of Contents
Интеграция JavaScript с Backend Frameworks, такими как Node.js и Express
Возможность использовать JavaScript как на стороне клиента, так и на стороне сервера коренным образом изменила современную веб-разработку. Node.js обеспечивает среду выполнения, которая делает это возможным, в то время как Express обеспечивает тонкую, не вызывающую доверия структуру, которая упрощает создание надежных API и веб-серверов. Вместе они позволяют разработчикам создавать масштабируемые приложения в реальном времени с использованием одного языка во всем стеке.
Эта статья охватывает полный ландшафт интеграции: от создания основы до обработки данных, промежуточного программного обеспечения, безопасности, тестирования и развертывания. К концу вы поймете, как создавать готовые к производству бэкэнды с Node.js и Express и как легко подключать их к интерфейсу JavaScript.
Понять Node.js и Express
Node.js — это кроссплатформенная среда выполнения с открытым исходным кодом, построенная на движке JavaScript V8 Chrome. Она позволяет выполнять JavaScript вне браузера на сервере. Её событийная, неблокирующая модель ввода/вывода делает её особенно эффективной для I/O-тяжелых рабочих нагрузок, таких как серверы API, приложения реального времени и потоковые сервисы.
Express является самой популярной веб-платформой для Node.js. Он предоставляет минимальный набор функций для создания веб-серверов и API, включая поддержку маршрутизации, промежуточного программного обеспечения и шаблонного движка. Express не вызывает доверия, что означает, что вы можете свободно структурировать свое приложение по своему усмотрению — преимущество, которое дает опытным командам гибкость и контроль.
Согласно официальной документации Express , фреймворк является «быстрым, непредвзятым, минималистским». Эта философия поддерживает управляемость кривой обучения, в то же время позволяя использовать сложные, полнофункциональные приложения.
Зачем использовать Node.js и Express?
- Унифицированный язык: JavaScript как на интерфейсе, так и на бэкэнде уменьшает переключение контекста и позволяет совместно использовать код (например, логика проверки, утилиты).
- Неблокирующий I/O: Node.js эффективно обрабатывает многие одновременные соединения без накладных расходов на тяжелую резьбу.
- Богатая экосистема: npm предоставляет сотни тысяч пакетов, от драйверов баз данных до библиотек аутентификации.
- Возможности реального времени: встроенная поддержка WebSockets через библиотеки, такие как FLT:0, естественным образом интегрируется с Express.
Настройка готового к производству сервера
Начните с установки Node.js с nodejs.org. После установки создайте каталог проекта и инициализируйте package.json:
mkdir my-backend
cd my-backend
npm init -y
Установите Express в качестве зависимости:
npm install express
Для разработки также установите , чтобы автоматически перезагрузить сервер на изменения файлов:
npm install -D nodemon
Создайте файл с минимальным сервером:
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('Hello, world!');
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Обратите внимание на использование . Это делает приложение переносимым в различных средах — лучшая практика для развертывания.
Добавление переменных среды
Используйте пакет для загрузки переменных среды из файла :
npm install dotenv
Создайте файл :
PORT=5000
DB_CONNECTION_STRING=mongodb://localhost:27017/myapp
В , загрузите конфигурацию вверху:
require('dotenv').config();
Этот шаблон удерживает конфиденциальные данные из вашей кодовой базы и упрощает управление конфигурацией.
Обсуждение Middleware: The Heart of Express
Функции промежуточного программного обеспечения являются строительными блоками логики приложения Express. Они имеют доступ к объекту запроса, объекту ответа и функции . Они могут выполнять код, изменять запрос/ответ, заканчивать цикл или вызывать следующее промежуточное программное обеспечение.
К распространенным случаям использования относятся регистрация, аутентификация, анализ органов запроса и ошибки обработки.
Встроенное Middleware
Express предоставляет несколько встроенных функций промежуточного программного обеспечения:
- — Парсирует входящие полезные нагрузки JSON.
- — Парсирует кодируемые URL-адресами тела (от HTML-форм).
- — Обслуживает статические файлы, такие как изображения, CSS и клиентский JavaScript.
Пример с JSON parsing:
app.use(express.json());
app.post('/api/users', (req, res) => {
console.log(req.body); // Access parsed JSON
res.json({ success: true });
});
Пользовательский Middleware
Создайте многоразовую логику, написав собственное промежуточное ПО. Например, регистратор запросов:
const logger = (req, res, next) => {
console.log(`${req.method} ${req.url} - ${new Date().toISOString()}`);
next();
};
app.use(logger);
Вопросы порядка: промежуточное ПО выполняется в том порядке, в котором оно определено. Всегда помещайте промежуточное ПО для обработки ошибок последним, с четырьмя параметрами:
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Something broke!' });
});
RESTful API и RESTful API
Экспресс-маршрутизация отображает методы и пути HTTP для функций обработчика. Чистая структура маршрутизации улучшает ремонтопригодность и масштабируемость.
Базовая маршрутизация
app.get('/api/items', (req, res) => {
// return list of items
});
app.post('/api/items', (req, res) => {
// create new item
});
app.put('/api/items/:id', (req, res) => {
const { id } = req.params;
// update item with given id
});
app.delete('/api/items/:id', (req, res) => {
// delete item
});
Использование Express Router для модульности
Для более крупных приложений разделите маршруты на отдельные файлы с помощью . Создайте папку и файл :
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.json([{ id: 1, name: 'Sample Item' }]);
});
router.post('/', (req, res) => {
// create logic
});
module.exports = router;
В [[27]] [[[27]]]:
const itemsRouter = require('./routes/items');
app.use('/api/items', itemsRouter);
Такой подход позволяет сохранить точку входа в систему чистой и логически сгруппировать маршруты.
Подключение к базе данных
Большинство бэкэндов должны сохранять данные. Популярные базы данных NoSQL и SQL хорошо интегрируются с Node.js.
MongoDB с мангустом
Монгуст, ODM для MongoDB:
npm install mongoose
Подключайтесь к файлу сервера:
const mongoose = require('mongoose');
mongoose.connect(process.env.DB_CONNECTION_STRING)
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('Connection error', err));
Определить схему и модель (например, ):
const mongoose = require('mongoose');
const itemSchema = new mongoose.Schema({
name: { type: String, required: true },
price: Number,
created_at: { type: Date, default: Date.now }
});
module.exports = mongoose.model('Item', itemSchema);
Используйте модель на своих маршрутах:
const Item = require('./models/Item');
app.post('/api/items', async (req, res) => {
try {
const item = new Item(req.body);
await item.save();
res.status(201).json(item);
} catch (err) {
res.status(400).json({ error: err.message });
}
});
PostgreSQL с узлом-постгре
Для реляционных баз данных используйте пакет :
npm install pg
Создайте пул и запрос:
const { Pool } = require('pg');
const pool = new Pool({
connectionString: process.env.DATABASE_URL
});
app.get('/api/users', async (req, res) => {
const result = await pool.query('SELECT * FROM users');
res.json(result.rows);
});
Рассмотрим использование ORM, как Секвелизовать или Knex для более абстрактных взаимодействий.
Интеграция Frontend-Backend
Как только бэкэнд обслуживает данные через конечные точки API, ваш интерфейсный JavaScript может потреблять их с помощью API или библиотек, таких как Axios.
Выбираем из экспресса
Предположим, что ваш Express API работает на . клиентский скрипт (например, React, Vue или простой HTML) может извлекать данные:
fetch('http://localhost:3000/api/items')
.then(response => {
if (!response.ok) throw new Error('Network response error');
return response.json();
})
.then(data => {
console.log('Items:', data);
// render data on page
})
.catch(err => console.error('Fetch error:', err));
Обработка CORS
Когда интерфейс и бэкэнд находятся на разных портах или доменах, вам необходимо включить Cross-Origin Resource Sharing (CORS).
npm install cors
Используйте его как промежуточное ПО:
const cors = require('cors');
app.use(cors()); // Allows all origins – restrict in production
Для производства настройте конкретные источники:
app.use(cors({
origin: 'https://your-frontend-domain.com',
methods: ['GET', 'POST']
}));
Лучшие практики безопасности
Внедрение интеграции бэкэндов создает проблемы безопасности.
- Helmet: Настраивает различные HTTP-заголовки для защиты от распространенных атак.
- Ограничение ставок: Использование для предотвращения злоупотреблений.
- Вводная проверка: Санитаризация и проверка пользовательских входов с использованием библиотек, таких как или .
- HTTPS: Всегда обслуживайте HTTPS в производстве.
- Аутентификации: Используйте JSON Web Tokens (JWT) или сессионный аут с .
Пример с шлемом:
const helmet = require('helmet');
app.use(helmet());
Пример с ограничением скорости:
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100
});
app.use('/api', limiter);
Обработка ошибок и регистрация
Производственные приложения нуждаются в надежной обработке ошибок. Создайте централизованное промежуточное ПО для обработки ошибок, которое регистрирует ошибки и возвращает последовательные ответы.
// Custom error handler
const errorHandler = (err, req, res, next) => {
console.error('Error:', err.message);
const statusCode = err.statusCode || 500;
res.status(statusCode).json({
error: err.message,
stack: process.env.NODE_ENV === 'development' ? err.stack : undefined
});
};
app.use(errorHandler);
Для ведения лесозаготовок используйте в разработке и более структурированный лесозаготовитель, как в производстве:
npm install morgan winston
const morgan = require('morgan');
app.use(morgan('dev'));
Тестирование интеграции
Напишите тесты, чтобы убедиться, что ваш бэкэнд ведет себя так, как ожидалось. Популярные фреймворки тестирования включают Jest и Mocha. Для тестов интеграции HTTP используйте supertest.
Пример с шуткой и супер-тестом
Установите зависимости от dev:
npm install -D jest supertest
Создайте тестовый файл :
const request = require('supertest');
const app = require('./index'); // export app from index.js
describe('GET /api/items', () => {
it('responds with JSON array', async () => {
const res = await request(app)
.get('/api/items')
.expect('Content-Type', /json/)
.expect(200);
expect(Array.isArray(res.body)).toBe(true);
});
});
Примечание: Отделите определение приложения от прослушивающего сервера, чтобы избежать конфликтов портов во время тестов. Экспортируйте приложение и слушайте только тогда, когда файл запускается напрямую:
if (require.main === module) {
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
}
module.exports = app;
Рассмотрение вопроса о развертывании
При развертывании бэкэнда Node.js+Express следуйте этим рекомендациям:
- Используйте менеджер процессов , как PM2, чтобы сохранить приложение живым и обрабатывать кластеризацию.
- Настройка переменных среды на хостинговой платформе (например, Heroku, DigitalOcean, AWS Elastic Beanstalk).
- Включить регистрацию и мониторинг с помощью таких сервисов, как Logtail или Datadog.
- Используйте обратный прокси (Nginx, Caddy) для SSL-окончания, кэширования и заголовков безопасности.
Общий шаблон развертывания заключается в том, чтобы поддерживать бэкэнд и фронтенд в качестве отдельных проектов, обмениваясь данными через API по HTTPS. Кроме того, вы можете обслуживать файлы сборки фронтенда через Express с использованием и обрабатывать все маршруты для поддержки маршрутизации на стороне клиента (например, React Router).
Оптимизация производительности
Node.js однопоточный, но вы все равно можете достичь высокой пропускной способности с помощью соответствующих стратегий:
- Используйте асинхронизацию/ожидание для всех операций ввода/вывода, чтобы избежать блокировки цикла событий.
- Компресс-ответы с промежуточного ПО.
- Кэшировать частые ответы с использованием магазинов в памяти, таких как Redis.
- Кластеризация приложения по нескольким ядрам ЦП с использованием встроенного модуля или кластерного режима PM2.
Пример с компрессией:
const compression = require('compression');
app.use(compression());
Коммуникация в реальном времени с WebSockets
Express плавно интегрируется с , чтобы обеспечить двунаправленную, ориентированную на события связь. Это идеально подходит для приложений чата, живых уведомлений и инструментов совместной работы.
npm install socket.io
Создайте сервер с поддержкой HTTP и WebSocket:
const http = require('http');
const socketIo = require('socket.io');
const server = http.createServer(app);
const io = socketIo(server, { cors: { origin: '*' } });
io.on('connection', (socket) => {
console.log('New client connected');
socket.on('disconnect', () => console.log('Client disconnected'));
});
server.listen(PORT, () => console.log(`Server with WebSocket on port ${PORT}`));
Фронтенд может подключаться к этому серверу WebSocket и излучать/слушать события с помощью библиотеки .
Полнотекстовые фреймворки и шаблоны
Помимо базовой интеграции, многие команды принимают фреймворки, которые объединяют Node.js, Express и фронтенд фреймворк в сплоченный стек. Наиболее распространенным является стек MERN (MongoDB, Express, React, Node.js). Другие включают MEVN (Vue) и MEAN (Angular).
Эти стеки позволяют разработчикам создавать полные приложения из базы данных в пользовательский интерфейс, часто с общими моделями и типами. Например, вы можете определить схемы Mongoose на бэкэнде и повторно использовать ту же логику проверки на фронтенде после преобразования в библиотеку форм.
Заключение
Интеграция JavaScript с Node.js и Express заключается не только в запуске аналогичного кода с обеих сторон - речь идет об использовании всей мощности экосистемы JavaScript для создания сплоченных, поддерживаемых и высокопроизводительных веб-приложений. От базовой настройки до продвинутых шаблонов, таких как промежуточное ПО, интеграция с базами данных, аутентификация и функции в реальном времени, Express обеспечивает гибкость, необходимую для адаптации к различным требованиям проекта.
Овладев этими методами, можно устранить несоответствие импеданса между бэкэндом и фронтэндом, ускорить циклы разработки и развернуть приложения, масштабирующиеся. Сейчас самое время воплотить теорию в жизнь: начать новый проект, экспериментировать со промежуточной программой, подключить базу данных и увидеть, как оживает интеграция.