10 лучших практик написания приложений на NodeJS

Статья написана студентом Хекслета. Мнение автора может не совпадать с позицией редакции
Читать в полной версии →

Node.js — это популярная среда выполнения, которая позволяет разработчикам писать серверные приложения с использованием JavaScript. При создании приложений Node.js существуют определенные рекомендации, которым разработчики должны следовать, чтобы их код был эффективным, масштабируемым и удобным в сопровождении. В этой статье мы рассмотрим некоторые методы написания приложений Node.js, а также примеры кода для демонстрации каждого из них.

Используйте Linter

Linter — это инструмент, который анализирует ваш код на наличие потенциальных ошибок и несоответствий стиля. Использование линтера может помочь вам обнаружить ошибки на ранней стадии и обеспечить согласованность и легкость чтения вашего кода. Одним из популярных линтеров для приложений Node.js является ESLint. Вот пример того, как установить и использовать ESLint в проекте Node.js:

npm install eslint --save-dev
npx eslint index.js

Используйте менеджер пакетов (такие как npm, yarn, etc.)

Приложения Node.js часто зависят от сторонних библиотек и пакетов. Использование диспетчера пакетов может помочь вам управлять этими зависимостями и обеспечивать их актуальность. Npm — это менеджер пакетов по умолчанию для Node.js, который широко используется в сообществе Node.js. Вот пример того, как установить пакет с помощью npm:

npm install express

Используйте переменные среды

Приложениям Node.js часто требуются параметры конфигурации, такие как учетные данные базы данных, ключи API и другая конфиденциальная информация. Хранение этой информации в вашем коде может быть угрозой безопасности. Вместо этого вы должны использовать переменные среды для хранения этой информации. Переменные среды — это значения, которые задаются в среде операционной системы и могут быть доступны вашему приложению Node.js. Вот пример использования переменных среды в приложении Node.js:

const port = process.env.PORT || 3000;

Используйте асинхронный код Node.js

Такой код предназначен для обработки асинхронных операций. Использование асинхронного кода может помочь повысить производительность и масштабируемость вашего приложения. Вы можете использовать обратные вызовы, промисы или async/await для написания асинхронного кода в Node.js. Вот пример использования Promise для чтения файла в Node.js:

const fs = require('fs');

const readFile = (path) => {
  return new Promise((resolve, reject) => {
    fs.readFile(path, (err, data) => {
      if (err) {
        reject(err);
      } else {
        resolve(data);
      }
    });
  });
};

readFile('myfile.txt')
  .then((data) => {
    console.log(data.toString());
  })
  .catch((err) => {
    console.error(err);
  });

А теперь пример с использованием async/await:

const fs = require('fs');

const readFile = async (path) => {
  try {
    const data = await fs.promises.readFile(path);
    console.log(data.toString());
  } catch (err) {
    console.error(err);
  }
};

readFile('myfile.txt');

Использование Middleware

ПО промежуточного слоя (Middleware) — это способ добавить функциональность циклу запроса/ответа вашего приложения Node.js. Middleware можно использовать для таких задач, как ведение журнала, проверка подлинности и обработка ошибок. Express — это популярный фреймворк Node.js, предоставляющий функциональность middleware. Вот пример того, как использовать middleware в приложении Express:

const express = require('express');
const app = express();

app.use((req, res, next) => {
  console.log('Time:', Date.now());
  next();
});

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.listen(3000, () => {
  console.log('Server listening on port 3000');
});

Используйте middleware для обработки ошибок

Приложения Node.js могут столкнуться с ошибками во время выполнения. Использование middleware для обработки ошибок может помочь вам изящно обработать эти ошибки и предотвратить сбой вашего приложения. Вот пример того, как использовать промежуточное ПО для обработки ошибок в приложении Express:

const express = require('express');
const app = express();

app.get('/', (req, res, next) => {
  const err = new Error('Not Found');
  err.status = 404;
  next(err);
});

app.use((err, req, res, next) => {
  res.status(err.status || 500);
  res.json({
    error: {
      message: err.message
    }
  });
});

app.listen(3000, () => {
  console.log('Server listening on port 3000');
});

В этом примере middleware функция обработки ошибок определяется с помощью app.use() метода. Эта функция принимает четыре аргумента: err, req, res, и next. Аргумент err содержит объект ошибки, который был передан функции next() в предыдущем middleware. Аргументы req и res являются объектами запроса и ответа соответственно. Аргумент next — это функция обратного вызова, которая вызывает следующий middleware в цепочке.

Функция middleware обработки ошибок устанавливает код состояния HTTP ответа на код состояния объекта ошибки или 500, если код состояния не был указан. Затем он отправляет ответ JSON, содержащий сообщение об ошибке, соответствующее сообщению об ошибке объекта ошибки.

Используя middleware для обработки ошибок в приложении Node.js, вы можете перехватывать и обрабатывать ошибки, возникающие во время выполнения, и предотвращать их сбой в приложении.

Используйте Logging

Логирование — важный инструмент для мониторинга поведения вашего приложения Node.js. Logs могут помочь вам выявить и диагностировать ошибки и проблемы с производительностью.

Winston — популярная библиотека логирования приложений на Node.js. Вот пример того, как использовать Winston для записи сообщений в файл:

const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  defaultMeta: { service: 'my-app' },
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

logger.info('Hello, Winston!');

Используйте compression (сжатие)

Приложения Node.js могут отправлять клиентам большие объемы данных, что может повлиять на производительность. Использование сжатия может помочь уменьшить размер данных, отправляемых по сети, и повысить производительность. Middleware для сжатия в Express можно использовать для сжатия ответов. Вот пример того, как использовать сжатие в приложении Express:

const express = require('express');
const compression = require('compression');

const app = express();
app.use(compression());

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.listen(3000, () => {
  console.log('Server listening on port 3000');
});

Использование clustering.

Node.js является однопоточным, что означает, что он может использовать только одно ядро ​​ЦП. Кластеризация — это способ использовать несколько ядер ЦП для повышения производительности вашего приложения Node.js. Модуль кластера в Node.js можно использовать для создания дочерних процессов, которые используют один и тот же порт сервера. Вот пример использования кластеризации в приложении Node.js:

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  console.log(`Master ${process.pid} is running`);

  // Fork workers
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`worker ${worker.process.pid} died`);
  });
} else {
  // Workers can share any TCP connection
  // In this case it is an HTTP server
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('hello world\n');
  }).listen(8000);

  console.log(`Worker ${process.pid} started`);
}

Используйте очередь задач (task queue)

Приложения Node.js часто выполняют задачи, выполнение которых занимает много времени, например отправка электронных писем или создание отчетов. Использование очереди задач может помочь выгрузить эти задачи из основного процесса Node.js и повысить производительность. Bull — популярная библиотека очередей задач для Node.js. Вот пример использования Bull для обработки заданий в приложении Node.js:

const Queue = require('bull');
const myQueue = new Queue('my-queue');

myQueue.process((job) => {
  console.log(`Processing job ${job.id}`);
  return Promise.resolve();
});

myQueue.add({ foo: 'bar' });

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