Готовый, полнофункциональный экспресс-проект

Node.js внешний интерфейс
Готовый, полнофункциональный экспресс-проект

предисловие

Node.js, несомненно, является важной вехой для фронтенда.Сегодня, когда он становится все более и более популярным, освоение node.js — это не только бонус, но и навык, которым должны овладеть фронтендеры. И Express стал самой популярной средой node.js с ее быстрыми, открытыми и минимальными функциями, поэтому использование Express для разработки веб-сервера — хороший и надежный выбор. Однако после инициализации экспресса это не готовый проект веб-сервера с различными функциями, такими как: ведение журнала, перехват ошибок, подключение mysql, аутентификация по токену, веб-сокет и ряд общих функций, которые требуют от разработчиков Установите плагин самостоятельно, чтобы завершить функцию настройки.Если вы не знакомы с разработкой веб-сервера или экспресс-фреймворком, это будет работа, которая потребляет огромные ресурсы. В этой статье настраивается ряд общих функций, таких как ведение журнала, захват ошибок, соединение mysql, аутентификация токена, веб-сокет и т. д., в исходной архитектуре Express, а проект в этой статье был открыт на github для всех, чтобы изучить и использовать в реальных проектах, надеясь облегчить работу каждого, выполнить работу более эффективно и иметь больше времени для улучшения своих способностей.

Я много работал над организацией в течение долгого времени, и я надеюсь вручную поставить лайк и поощрить ~

Адрес блога на github:GitHub.com/ревматизм123/… , в котором собраны все блоги автора, и приглашаем подписаться и отметиться ~

Адрес этого проекта на гитхабе:GitHub.com/ревматизм123/…

1. Структура проекта

1.1. Базовая среда

Для этого проекта экспресс-сервера соответствующая конфигурация операционной среды выглядит следующим образом:

имя инструмента номер версии
node.js 11.12.0
npm 6.7.0
express 4.16.0
mysql 5.7

1.2. Запуск проекта

(1) Установите плагин, перейдите в каталог express_project и выполните следующую команду:

npm install

(2) Запустите среду разработки, войдите в каталог express_project и выполните следующие команды:

npm run dev

(3) Запустите официальную среду, войдите в каталог express_project и выполните следующую команду:

npm run start

1.3, каталог проекта

Структура каталогов проекта выглядит следующим образом:

├─ bin                数据库初始化脚本				
│  ├─ db	      项目数据库安装,其中 setup.sh 为命令入口,初始化数据库
├─ common	      共用方法、常量目录
├─ conf		      数据库基本配置目录
├─ dao		      代码主逻辑目录
├─ log                日志目录					
├─ public	      静态文件目录
├─ routes	      url 路由配置						
├─ .eslintrc.js	      eslint 配置
├─ app.js	      express 入口
├─ package.json	      项目依赖包配置
├─ README.md	      项目说明

Во-вторых, введение общей функции

2.1 в сочетании с mysql

2.1.1, установить и настроить mysql

Я не буду вводить здесь установку и настройку mysql, для конкретных операций обратитесь кдокумент конфигурации, рекомендуется установить инструмент управления базой данных mysqlnavicat for mysql, который обычно используется для просмотра добавлений, удалений, модификаций и запросов данных в базе данных;

2.1.2, инициализация базы данных

В каталоге bin/db мы настроили и написали сценарий инициализации базы данных, в котором setup.sh является записанной командой для подключения к базе данных, создания новой базы данных и т. д. Основная логика была аннотирована следующим образом:

mysql -uroot -p123456 --default-character-set=utf8 <<EOF // 需要将帐号密码改成自己的
drop database if exists research; // 删除数据库
create database research character set utf8; // 新建数据库
use research; // 切换到 research 数据库,对应改成自己的
source init.sql; // 初始化 sql 建表 
EOF
cmd /k

Мы можем вставить исходные данные каждой таблицы в init.sql.Соответствующий код выглядит следующим образом.Что касается простой логики того, как вставлять данные таблицы, мы не будем вводить ее здесь.Читатели могут проверить соответствующие файлы sql, чтобы понять.

source t_user.sql;
source t_exam.sql;
source t_video.sql;
source t_app_version.sql;
source t_system.sql;

2.1.3, конфигурация базы данных

Мы настраиваем основную информацию о mysql в файле conf/db.js. Соответствующие элементы конфигурации следующие. Вы можете соответствующим образом изменить элементы конфигурации и изменить их на свою собственную конфигурацию.

module.exports = {
  mysql: {
    host: '127.0.0.1',
    user: 'root',
    password: '123456',
    database: 'research',
    port: 3306
  }
};

2.1.4, подключение к базе данных и работа с ней

Основные операции по добавлению, удалению, изменению и проверке данных можно скопировать через уже настроенные файлы и логику.Для краткого ознакомления возьмем пример добавления пользователя.В файле dao/userDao.js:

var conf = require('../conf/db'); // 引入数据库配置
var pool = mysql.createPool(conf.mysql); // 使用连接池

  add: function (req, res, next) {
    pool.getConnection(function (err, connection) {
      if (err) {
        logger.error(err);
        return;
      }
      var param = req.body;
      // 建立连接,向表中插入值
      connection.query(sql.insert, [param.uid, param.name, param.password, param.role,param.sex], function (err, result) {
        if (err) {
          logger.error(err);
        } else {
          result = {
            code: 0,
            msg: '增加成功'
          };
        }
        // 以json形式,把操作结果返回给前台页面
        common.jsonWrite(res, result);
        // 释放连接
        connection.release();
      });
    });
  },

2.2, функция журнала

2.2.1, Морган записывает журнал запросов

morgan — это промежуточное программное обеспечение журнала по умолчанию для Express. Его также можно использовать отдельно от Express в качестве компонента журнала node.js. Конкретный API morgan см.репозиторий Моргана на github; Здесь мы в основном знакомимся с тем, какие конфигурации и функции были реализованы для вас в нашем проекте. Проект имеет следующую конфигурацию в файле app.js:

const logger = require('morgan');
// 输出日志到目录
var accessLogStream = fs.createWriteStream(path.join(__dirname, '/log/request.log'), { flags: 'a', encoding: 'utf8' }); 
app.use(logger('combined', { stream: accessLogStream }));

Мы настроили указанное выше ведение журнала запросов таким образом, чтобы каждый HTTP-запрос регистрировался в файле log/request.log.

2.2.2, Winston записывает журнал ошибок

Поскольку morgan может записывать только журналы http-запросов, нам также нужен winston для записи других журналов, которые мы хотим записывать, таких как: ошибки доступа к базе данных и т. д. Winston — одна из самых популярных библиотек журналов на node.js. Он разработан, чтобы быть простой и общей библиотекой журналов, которая поддерживает несколько транспортов (транспорт на самом деле является устройством хранения, например, где хранятся журналы). Каждый экземпляр регистратора в winston может иметь несколько конфигураций транспорта на разных уровнях журнала; конечно, он также может регистрировать записи запросов. Конкретный API winston может относиться крепозиторий Уинстона на github, мы не будем делать здесь подробное введение.

Здесь мы в основном рассказываем, какие конфигурации и функции мы используем Winston, чтобы помочь вам в нашем проекте. Проект имеет следующую конфигурацию в файле common/logger.js:

var { createLogger, format, transports } = require('winston');
var { combine, timestamp, printf } = format;
var path = require('path');

var myFormat = printf(({ level, message, label, timestamp }) => {
  return `${timestamp} ${level}: ${message}`;
});

var logger = createLogger({
  level: 'error',
  format: combine(
    timestamp(),
    myFormat
  ),
  transports: [
    new (transports.Console)(),
    new (transports.File)({
      filename: path.join(__dirname, '../log/error.log')
    })
  ]
});

module.exports = logger;

С помощью приведенной выше конфигурации файла logger.js нам нужно только ввести файл там, где это необходимо, а затем вызвать logger.error(err) для записи соответствующего уровня ведения журнала, и соответствующий журнал ошибок будет записан в файле log/error. .журнал.

2.3, обработка запросов маршрутизации

Разделяем обработку запросов по модулям в проекте Создаем новую конфигурацию роутинга для каждого модуля в каталоге route.Например пользовательский модуль это файл user.js.Вносим роутинг каждого модуля в main app.js На примере пользовательского модуля соответствующая логика кода выглядит следующим образом:

// 引入用户模块路由配置
var usersRouter = require('./routes/users');
// 使用用户模块的路由配置
app.use('/users', usersRouter);

Конфигурация маршрутизации в файле route/users.js выглядит следующим образом:

var express = require('express');
var router = express.Router();

// 增加用户
router.post('/addUser', function (req, res, next) {
  userDao.add(req, res, next);
});
// 获取全部用户
router.get('/queryAll', function (req, res, next) {
  userDao.queryAll(req, res, next);
});
// 删除用户
router.post('/deleteUser', function (req, res, next) {
  userDao.delete(req, res, next);
});
...

В приведенной выше конфигурации клиент перейдет к маршруту пользовательского модуля для обработки через путь запроса, начинающийся с /users.Если путь запроса /users/addUser, будет выполнена логическая обработка добавления пользователей. Благодаря этой спецификации и конфигурации, если в это время добавляется новый модуль, необходимо только добавить файл маршрутизации модуля в соответствии с исходной спецификацией и выполнить соответствующую обработку конфигурации маршрутизации, которая не повлияет на исходную конфигурацию маршрутизации модуля, и также не будет конфликтов маршрутизации и т.д.

2.4, аутентификация по токену

Express-jwt — это промежуточное ПО для node.js. Оно проверяет действительность JsonWebTokens указанного HTTP-запроса. Если он действителен, значение jsonWebTokens устанавливается в req.user, а затем направляется на соответствующий маршрутизатор. Этот модуль позволяет вам использовать токены JWT в вашем приложении node.js для аутентификации HTTP-запросов. Конкретный API экспресс-jwt может относиться крепозиторий github для экспресс-jwt, мы не будем делать здесь подробное введение.

Здесь мы в основном рассказываем, какие конфигурации и функции мы используем, чтобы помочь вам в нашем проекте. Проект имеет следующую конфигурацию перехвата токена в файле app.js.Если токен не прошел проверку подлинности, он вернет ошибку проверки подлинности клиента 401;

var expressJWT = require('express-jwt');
// token 设置
app.use(expressJWT({
  secret: CONSTANT.SECRET_KEY
}).unless({
  // 除了以下这些 URL,其他的URL都需要验证
  path: ['/getToken',
    '/getToken/adminLogin',
    '/appVersion/upload',
    '/appVersion/download',
    /^\/public\/.*/,
    /^\/static\/.*/,
    /^\/user_disk\/.*/,
    /^\/user_video\/.*/
  ]
}));

Мы можем внедрить соответствующий идентификатор пользователя, вошедшего в систему, в токен при создании токена, как настроено в файле dao/tokenDao.js;

// uid 注入 token 中
ret = {
  code: 0,
  data: {
	token: jsonWebToken.sign({
	  uid: obj.uid
	}, CONSTANT.SECRET_KEY, {
	  expiresIn: 60 * 60 * 24
	}),
  }
};

Позже мы можем получить информацию об идентификаторе пользователя, ранее введенную в токен, через информацию о запросе req.body.uid в запросе.

2.5. Междоменная конфигурация

Мы выполнили междоменную настройку проекта в app.js проекта, чтобы некоторые клиенты, такие как разработка одностраничных приложений, мобильные приложения и т. д., могли получить доступ к соответствующему интерфейсу сервера через домен. Делаем соответствующую междоменную настройку в файле app.js:

app.all('*', function (req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Headers', '*');
  res.header('Access-Control-Allow-Methods', '*');
  next();
});

2.6, конфигурация статического каталога

Мы настроили статический каталог в проекте для предоставления услуг для файлов статических ресурсов (изображений, файлов css, файлов js и т. д.); передайте каталог, содержащий статические ресурсы, промежуточному программному обеспечению express.static для предоставления статических ресурсов. Изображения, файлы css и файлы javascript в общем каталоге предоставляются следующим образом.Конечно, вы также можете создать свой собственный каталог статических ресурсов с помощью аналогичной конфигурации в соответствии с вашими потребностями.

app.use('/', express.static(path.join(__dirname, 'public')));

2.7, обработка ошибок исключений

Если мы не обработаем серверную программу, когда серверный код выдаст исключение, это приведет к завершению процесса узла, так что пользователь не сможет нормально получить доступ к серверу, что вызовет серьезные проблемы. Настраиваем и используем в проекте модуль домена для перехвата исключений, генерируемых в серверной программе, основные API домена — это domain.run и события ошибок. Проще говоря, исключения, возникающие в функциях, выполняемых domain.run, могут быть перехвачены событием ошибки домена. Код, который мы настраиваем для использования домена в проекте, выглядит следующим образом:

var domain = require('domain');
// 处理没有捕获的异常,导致 node 退出
app.use(function (req, res, next) {  
  var reqDomain = domain.create();  
  reqDomain.on('error', function (err) {   
     res.status(err.status || 500);    
     res.render('error'); 
  }); 
  reqDomain.run(next);
});

2.8, автоматический перезапуск

Каждый раз, когда мы модифицируем файл js, нам нужно перезапустить сервер, чтобы измененное содержимое вступило в силу, но каждый перезапуск доставляет неудобства и влияет на эффект разработки; поэтому мы вводим подключаемый модуль nodemon в среду разработки, чтобы реализовать реальный -горячее обновление и автоматический перезапуск проекта. Итак, как упоминалось в разделе 1.3, мы должны использовать команду npm run dev для запуска проекта в среде разработки, потому что у нас есть следующая команда, настроенная в файле package.json:

  "scripts": {
    "dev": "nodemon ./app",
  },

2.9, использование pm2

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

2.10 Обработка загрузки файлов

Приложение на стороне сервера неизбежно должно иметь дело с операцией загрузки файлов. Мы настраиваем многосторонний плагин для всех в проекте и предоставляем сопутствующие операции, такие как загрузка и переименование. Соответствующая логика кода и комментарии находятся в dao/common .js. Если вы не знакомы с многосторонним плагином, вы можете обратиться кРепозиторий github для многосторонних плагинов, мы не будем делать здесь подробное введение.

var upload = function (path, req, res, next) {
  return new Promise(function (resolve, reject) {
    // 解析一个文件上传
    var form = new multiparty.Form();
    // 设置编辑
    form.encoding = 'utf-8';
    // 设置文件存储路径
    form.uploadDir = path;
    // 设置单文件大小限制
    form.maxFilesSize = 2000 * 1024 * 1024;
    var textObj = {};
    var imgObj = {};
    form.parse(req, function (err, fields, files) {
      if (err) {
        console.log(err);
      }
      Object.keys(fields).forEach(function (name) { // 文本
        textObj[name] = fields[name];
      });
      Object.keys(files).forEach(function (name) {
        if (files[name] && files[name][0] && files[name][0].originalFilename) {
          imgObj[name] = files[name];
          var newPath = unescape(path + '/' + files[name][0].originalFilename);
          var num = 1;
          var suffix = newPath.split('.').pop();
          var lastIndex = newPath.lastIndexOf('.');
          var tmpname = newPath.substring(0, lastIndex);
          while (fs.existsSync(newPath)) {
            newPath = tmpname + '_' + num + '.' + suffix;
            num++;
          }
          fs.renameSync(files[name][0].path, newPath);
          imgObj[name][0].path = newPath;
        }
      });
      resolve([imgObj, textObj])
    });
  });
};

2.11, операции с файлами/каталогами

Программа сервера работает с каталогами и файлами сервера, что является относительно частой операцией.По сравнению с модулем работы с файлами fs по умолчанию в node.js, мы настроили плагин fs-extra в проекте для работы с каталогами и файлами сервера. -extra модуль — это расширение системного модуля fs, предоставляющее более удобные API и наследующее API модуля fs; например, мы используем метод mkdir для создания файловой директории в проекте, метод sureDir для подтверждения наличия каталог существует, и метод удаления для удаления файлов, методы копирования для копирования файлов и т. д. Вы можете увидеть богатые методы работы fs-extra в файле dao/filesDao.js. Если вы не работали с плагином fs-extra, рекомендуется проверитьего репозиторий на гитхабе, есть сопутствующие детали.

2.12 Настроить проверку кода eslint

Чтобы сохранить стиль кода проекта хорошим и последовательным, мы добавляем eslint в проект для проверки спецификации кода js; вы можете настроить, какие файлы вы не хотите проверять через eslint в файле .eslintignore; вы также можете проверьте код в .eslintrc.js Настройте стиль кода вашей команды в файле.

3. Резюме

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

Я много работал над организацией в течение долгого времени, и я надеюсь вручную поставить лайк и поощрить ~

Адрес блога на github:GitHub.com/ревматизм123/… , в котором собраны все блоги автора, и приглашаем подписаться и отметиться ~

Адрес этого проекта на гитхабе:GitHub.com/ревматизм123/…