Обучение по Express и Node.js от StrongLoop

Этот перевод обеспечивается StrongLoop / IBM.

Этот документ может быть устаревшим по отношению к документации на английском языке. Последние обновления содержатся в документации на английском языке.

Переход к Express 4

Обзор

Express 4, на самом деле, ломает существующий код Express 3. Это означает, что существующее приложение Express 3 не будет работать, если обновить версию Express в установленных зависимостях данного приложения.

В этой статье содержится следующая информация:

Изменения в Express 4

В Express 4 реализованы следующие существенные изменения:

См. также:

Изменения ядра Express и системы промежуточных обработчиков

Express 4 больше не является зависимым от Connect, и из его ядра удалены все встроенные промежуточные обработчики, за исключением функции express.static. Это означает, что теперь Express представляет собой независимый веб-фреймворк маршрутизации и промежуточной обработки, и обновления промежуточных обработчиков никак не влияют на новые версии и выпуски Express.

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

  1. Установите модуль: npm install --save <module-name>
  2. В своем приложении затребуйте модуль: require('module-name')
  3. Используйте модуль согласно документации к нему: app.use( ... )

В таблице ниже приводится список соответствий между промежуточными обработчиками Express 3 и Express 4.

Express 3Express 4
express.bodyParser body-parser + multer
express.compress compression
express.cookieSession cookie-session
express.cookieParser cookie-parser
express.logger morgan
express.session express-session
express.favicon serve-favicon
express.responseTime response-time
express.errorHandler errorhandler
express.methodOverride method-override
express.timeout connect-timeout
express.vhost vhost
express.csrf csurf
express.directory serve-index
express.static serve-static

Это полный список промежуточных обработчиков Express 4.

В большинстве случаев можно просто заменить промежуточные обработчики старой, 3-й, версии на соответствующие обработчики Express 4. Дополнительную информацию можно найти в документации к модулю в GitHub.

app.use принимает параметры

В версии 4 можно использовать параметр переменной для определения пути загрузки функций промежуточной обработки, после чего считать значение параметра из обработчика маршрута. Например:


app.use('/book/:id', function(req, res, next) {
  console.log('ID:', req.params.id);
  next();
});

Система маршрутизации

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

Способ определения маршрутов остается неизменным, но в системе маршрутизации предусмотрено две новые функции, предназначенные для упорядочения маршрутов:

Метод app.route()

Новый метод app.route() позволяет создавать обработчики маршрутов, образующие цепочки, для пути маршрута. Поскольку путь указан в одном расположении, удобно создавать модульные маршруты, чтобы минимизировать избыточность и количество опечаток. Дополнительная информация о маршрутах приводится в документации по Router().

Ниже приведен пример объединенных в цепочку обработчиков маршрутов, определенных с помощью функции app.route().


app.route('/book')
  .get(function(req, res) {
    res.send('Get a random book');
  })
  .post(function(req, res) {
    res.send('Add a book');
  })
  .put(function(req, res) {
    res.send('Update the book');
  });

Класс express.Router

Еще одной функцией, позволяющей упорядочить маршруты, является новый класс express.Router, с помощью которого можно создавать модульные монтируемые обработчики маршрутов. Экземпляр Router представляет собой комплексную систему промежуточных обработчиков и маршрутизации; по этой причине его часто называют “мини-приложением”.

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

Например, создайте файл маршрутизатора с именем birds.js в каталоге приложения со следующим содержанием:


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

// middleware specific to this router
router.use(function timeLog(req, res, next) {
  console.log('Time: ', Date.now());
  next();
});
// define the home page route
router.get('/', function(req, res) {
  res.send('Birds home page');
});
// define the about route
router.get('/about', function(req, res) {
  res.send('About birds');
});

module.exports = router;

Потом загрузите модуль маршрутизации в приложение:


var birds = require('./birds');
...
app.use('/birds', birds);

Данное приложение теперь сможет обрабатывать запросы, адресованные ресурсам в путях /birds и /birds/about, и вызывать специальный промежуточный обработчик timeLog данного маршрута.

Прочие изменения

В приведенной ниже таблице перечислены прочие, не слишком масштабные, но важные изменения, внесенные в версии Express 4:

Объект Описание
Node.js Express 4 требуется Node.js 0.10.x или более поздних версий; поддержка Node.js 0.8.x приостановлена.

http.createServer()

Модуль http теперь необходим только в случае, если вам требуется работать с ним непосредственно (socket.io/SPDY/HTTPS). Приложение можно запустить с помощью функции app.listen().

app.configure()

Функция app.configure() удалена. Для определения среды и соответствующей настройки приложения используйте process.env.NODE_ENV или функцию app.get('env').

json spaces

Свойство приложения json spaces в Express 4 по умолчанию отключено.

req.accepted()

Используйте req.accepts(), req.acceptsEncodings(), req.acceptsCharsets() и req.acceptsLanguages().

res.location()

Относительные URL-адреса более не распознаются.

req.params

Был массив; теперь объект.

res.locals

Была функция; теперь объект.

res.headerSent

Изменен на res.headersSent.

app.route

Теперь представлен как app.mountpath.

res.on('header')

Удален.

res.charset

Удален.

res.setHeader('Set-Cookie', val)

Функциональность ограничена установкой исходного значения cookie. Для использования дополнительных функциональных возможностей применяется res.cookie().

Пример миграции приложения

Ниже приводится пример миграции приложения Express 3 в Express 4. Рассмотрим файлы app.js и package.json.

Приложение версии 3

app.js

Рассмотрим приложение Express v.3, включающее в себя следующий файл app.js:


var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.methodOverride());
app.use(express.session({ secret: 'your secret here' }));
app.use(express.bodyParser());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

app.get('/', routes.index);
app.get('/users', user.list);

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

package.json

Сопутствующий ему файл package.json версии 3, может выглядеть примерно так:


{
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "3.12.0",
    "jade": "*"
  }
}

Процесс

Процесс миграции начинается с установки обязательных промежуточных обработчиков для приложения Express 4 и обновления Express и Jade до соответствующих последних версий с помощью следующей команды:


$ npm install serve-favicon morgan method-override express-session body-parser multer errorhandler express@latest jade@latest --save

Внесите в файл app.js следующие изменения:

  1. Встроенные функции промежуточной обработки Express express.favicon, express.logger, express.methodOverride, express.session, express.bodyParser и express.errorHandler более не доступны в объекте express. Необходимо вручную установить соответствующие им альтернативные объекты и загрузить их в приложение.

  2. Функцию app.router загружать не нужно. Она не является действительным объектом приложения Express 4, поэтому удалите код app.use(app.router);.

  3. Убедитесь в том, что функции промежуточной обработки загружаются в соответствующем порядке, - загрузите errorHandler после загрузки маршрутов приложения.

Приложение версии 4

package.json

При запуске указанной выше команды npm будет выполнено обновление package.json следующим образом:


{
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "body-parser": "^1.5.2",
    "errorhandler": "^1.1.1",
    "express": "^4.8.0",
    "express-session": "^1.7.2",
    "jade": "^1.5.0",
    "method-override": "^2.1.2",
    "morgan": "^1.2.2",
    "multer": "^0.1.3",
    "serve-favicon": "^2.0.1"
  }
}

app.js

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


var http = require('http');
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var path = require('path');

var favicon = require('serve-favicon');
var logger = require('morgan');
var methodOverride = require('method-override');
var session = require('express-session');
var bodyParser = require('body-parser');
var multer = require('multer');
var errorHandler = require('errorhandler');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(methodOverride());
app.use(session({ resave: true,
                  saveUninitialized: true,
                  secret: 'uwotm8' }));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(multer());
app.use(express.static(path.join(__dirname, 'public')));

app.get('/', routes.index);
app.get('/users', user.list);

// error handling middleware should be loaded after the loading the routes
if ('development' == app.get('env')) {
  app.use(errorHandler());
}

var server = http.createServer(app);
server.listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Если вам не нужно работать непосредственно с модулем http (socket.io/SPDY/HTTPS), загружать его не обязательно, а приложение можно просто запустить следующим образом:

app.listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Запустите приложение

Процесс миграции завершен, и данное приложение теперь является приложением версии Express 4. Для подтверждения запустите приложение с помощью следующей команды:


$ node .

Загрузите http://localhost:3000. Будет отображена домашняя страница в Express 4.

Обновление до версии генератора приложений Express 4

Инструмент командной строки для генерации приложений Express остается неизменным - express, но для обновления его до новой версии необходимо удалить установку генератора приложений Express 3, а затем установить новый express-generator.

Установка

Если в системе уже установлен генератор приложений Express 3, его необходимо удалить:


$ npm uninstall -g express

В зависимости от настроек прав доступа к файлам и каталогам, эту команду, возможно, следует вызвать с помощью sudo.

Теперь установите новый генератор:


$ npm install -g express-generator

В зависимости от настроек прав доступа к файлам и каталогам, эту команду, возможно, следует вызвать с помощью sudo.

Итак, команда express в вашей системе обновлена до версии генератора Express 4.

Изменения генератора приложений

Опции команд и их использование, в основном, остались без изменений, за исключением следующих:

Пример

Выполните следующую команду для создания приложения Express 4:


$ express app4

Обратив внимание на содержимое файла app4/app.js, вы заметите, что все функции промежуточной обработки (кроме express.static), обязательные для приложения, загружаются как независимые модули, а промежуточный обработчик router больше не загружается в приложение явным образом.

Также вы заметите, что файл app.js теперь является модулем Node.js, а не самостоятельным приложением, которое генерировалось старой версией генератора.

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


$ npm start

Обратив внимание на сценарий запуска npm в файле package.json, вы заметите, что, фактически, командой, запускающей приложение, является node ./bin/www, которой в Express 3 соответствовала команда node app.js.

Поскольку файл app.js, созданный генератором Express 4, теперь является модулем Node.js, его уже нельзя запускать отдельно как приложение (если не изменить код). Модуль необходимо загрузить в файл Node.js и запустить через файл Node.js. В данном случае, файлом Node.js является ./bin/www.

Ни каталог bin, ни файл www без расширения не являются обязательными для создания приложения Express или запуска такого приложения. Это всего лишь рекомендованные генератором значения, которые можно менять в соответствии с вашими потребностями.

Для того чтобы избавиться от каталога www и оставить все, “как было в Express 3”, удалите строку module.exports = app; в конце файла app.js, а вместо нее вставьте следующий код:


app.set('port', process.env.PORT || 3000);

var server = app.listen(app.get('port'), function() {
  debug('Express server listening on port ' + server.address().port);
});

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


var debug = require('debug')('app4');

Далее, замените "start": "node ./bin/www" в файле package.json на "start": "node app.js".

Итак, функциональность ./bin/www была перемещена обратно в app.js. Такое изменение не является рекомендованным, но цель данного упражнения заключалась в том, чтобы помочь вам разобраться в принципах работы файла ./bin/www и понять, почему файл app.js теперь нельзя запускать как самостоятельный.