Migrating to Express 4 (2024)

Overview

Express 4 is a breaking change from Express 3. That means an existing Express 3 app will not work if you update the Express version in its dependencies.

This article covers:

  • Changes in Express 4.
  • An example of migrating an Express 3 app to Express 4.
  • Upgrading to the Express 4 app generator.

Changes in Express 4

There are several significant changes in Express 4:

  • Changes to Express core and middleware system. The dependencies on Connect and built-in middleware were removed, so you must add middleware yourself.
  • Changes to the routing system.
  • Various other changes.

See also:

Changes to Express core and middleware system

Express 4 no longer depends on Connect, and removes all built-inmiddleware from its core, except for the express.static function. This means thatExpress is now an independent routing and middleware web framework, andExpress versioning and releases are not affected by middleware updates.

Without built-in middleware, you must explicitly add all themiddleware that is required to run your app. Simply follow these steps:

  1. Install the module: npm install --save <module-name>
  2. In your app, require the module: require('module-name')
  3. Use the module according to its documentation: app.use( ... )

The following table lists Express 3 middleware and their counterparts in Express 4.

Express 3Express 4
express.bodyParserbody-parser +multer
express.compresscompression
express.cookieSessioncookie-session
express.cookieParsercookie-parser
express.loggermorgan
express.sessionexpress-session
express.faviconserve-favicon
express.responseTimeresponse-time
express.errorHandlererrorhandler
express.methodOverridemethod-override
express.timeoutconnect-timeout
express.vhostvhost
express.csrfcsurf
express.directoryserve-index
express.staticserve-static

Here is the complete list of Express 4 middleware.

In most cases, you can simply replace the old version 3 middleware withits Express 4 counterpart. For details, see the module documentation inGitHub.

app.use accepts parameters

In version 4 you can use a variable parameter to define the path where middleware functions are loaded, then read the value of the parameter from the route handler.For example:

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

The routing system

Apps now implicitly load routing middleware, so you no longer have toworry about the order in which middleware is loaded with respect tothe router middleware.

The way you define routes is unchanged, but the routing system has twonew features to help organize your routes:

  • A new method, app.route(), to create chainable route handlers for a route path.
  • A new class, express.Router, to create modular mountable route handlers.

app.route() method

The new app.route() method enables you to create chainable route handlersfor a route path. Because the path is specified in a single location, creating modular routes is helpful, as is reducing redundancy and typos. For moreinformation about routes, see Router() documentation.

Here is an example of chained route handlers that are defined by using the app.route() function.

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

express.Router class

The other feature that helps to organize routes is a new class,express.Router, that you can use to create modular mountableroute handlers. A Router instance is a complete middleware androuting system; for this reason it is often referred to as a “mini-app”.

The following example creates a router as a module, loads middleware init, defines some routes, and mounts it on a path on the main app.

For example, create a router file named birds.js in the app directory,with the following content:

var express = require('express')var router = express.Router()// middleware specific to this routerrouter.use((req, res, next) => { console.log('Time: ', Date.now()) next()})// define the home page routerouter.get('/', (req, res) => { res.send('Birds home page')})// define the about routerouter.get('/about', (req, res) => { res.send('About birds')})module.exports = router

Then, load the router module in the app:

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

The app will now be able to handle requests to the /birds and/birds/about paths, and will call the timeLogmiddleware that is specific to the route.

Other changes

The following table lists other small but important changes in Express 4:

ObjectDescription
Node.jsExpress 4 requires Node.js 0.10.x or later and has dropped support forNode.js 0.8.x.

http.createServer()

The http module is no longer needed, unless you need to directly work with it (socket.io/SPDY/HTTPS). The app can be started by using theapp.listen() function.

app.configure()

The app.configure() function has been removed. Use theprocess.env.NODE_ENV orapp.get('env') function to detect the environment and configure the app accordingly.

json spaces

The json spaces application property is disabled by default in Express 4.

req.accepted()

Use req.accepts(), req.acceptsEncodings(),req.acceptsCharsets(), and req.acceptsLanguages().

res.location()

No longer resolves relative URLs.

req.params

Was an array; now an object.

res.locals

Was a function; now an object.

res.headerSent

Changed to res.headersSent.

app.route

Now available as app.mountpath.

res.on('header')

Removed.

res.charset

Removed.

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

Functionality is now limited to setting the basic cookie value. Useres.cookie() for added functionality.

Example app migration

Here is an example of migrating an Express 3 application to Express 4.The files of interest are app.js and package.json.

Version 3 app

app.js

Consider an Express v.3 application with the following app.js file:

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 environmentsapp.set('port', process.env.PORT || 3000)app.set('views', path.join(__dirname, 'views'))app.set('view engine', 'pug')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 onlyif (app.get('env') === 'development') { app.use(express.errorHandler())}app.get('/', routes.index)app.get('/users', user.list)http.createServer(app).listen(app.get('port'), () => { console.log('Express server listening on port ' + app.get('port'))})

package.json

The accompanying version 3 package.json file might looksomething like this:

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

Process

Begin the migration process by installing the required middleware for theExpress 4 app and updating Express and Pug to their respective latestversion with the following command:

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

Make the following changes to app.js:

  1. The built-in Express middleware functions express.favicon,express.logger, express.methodOverride,express.session, express.bodyParser andexpress.errorHandler are no longer available on theexpress object. You must install their alternativesmanually and load them in the app.

  2. You no longer need to load the app.router function.It is not a valid Express 4 app object, so remove theapp.use(app.router); code.

  3. Make sure that the middleware functions are loaded in the correct order - load errorHandler after loading the app routes.

Version 4 app

package.json

Running the above npm command will update package.json as follows:

{ "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", "pug": "^2.0.0", "method-override": "^2.1.2", "morgan": "^1.2.2", "multer": "^0.1.3", "serve-favicon": "^2.0.1" }}

app.js

Then, remove invalid code, load the required middleware, and make otherchanges as necessary. The app.js file will look like this:

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 environmentsapp.set('port', process.env.PORT || 3000)app.set('views', path.join(__dirname, 'views'))app.set('view engine', 'pug')app.use(favicon(path.join(__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 routesif (app.get('env') === 'development') { app.use(errorHandler())}var server = http.createServer(app)server.listen(app.get('port'), () => { console.log('Express server listening on port ' + app.get('port'))})

Unless you need to work directly with the http module (socket.io/SPDY/HTTPS), loading it is not required, and the app can be simply started this way:

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

Run the app

The migration process is complete, and the app is now anExpress 4 app. To confirm, start the app by using the following command:

$ node .

Load http://localhost:3000and see the home page being rendered by Express 4.

Upgrading to the Express 4 app generator

The command-line tool to generate an Express app is stillexpress, but to upgrade to the new version, you must uninstallthe Express 3 app generator and then install the newexpress-generator.

Installing

If you already have the Express 3 app generator installed on your system,you must uninstall it:

$ npm uninstall -g express

Depending on how your file and directory privileges are configured,you might need to run this command with sudo.

Now install the new generator:

$ npm install -g express-generator

Depending on how your file and directory privileges are configured,you might need to run this command with sudo.

Now the express command on your system is updated to theExpress 4 generator.

Changes to the app generator

Command options and use largely remain the same, with the following exceptions:

  • Removed the --sessions option.
  • Removed the --jshtml option.
  • Added the --hogan option to support Hogan.js.

Example

Execute the following command to create an Express 4 app:

$ express app4

If you look at the contents of the app4/app.js file, you will noticethat all the middleware functions (except express.static) that are required forthe app are loaded as independent modules, and the router middlewareis no longer explicitly loaded in the app.

You will also notice that the app.js file is now a Node.js module, in contrast to the standalone app that was generated by the old generator.

After installing the dependencies, start the app by using the following command:

$ npm start

If you look at the npm start script in the package.json file,you will notice that the actual command that starts the app isnode ./bin/www, which used to be node app.jsin Express 3.

Because the app.js file that was generated by the Express 4 generatoris now a Node.js module, it can no longer be started independently as an app(unless you modify the code). The module must be loaded in a Node.js fileand started via the Node.js file. The Node.js file is ./bin/wwwin this case.

Neither the bin directory nor the extensionless wwwfile is mandatory for creating an Express app or starting the app. They arejust suggestions made by the generator, so feel free to modify them to suit yourneeds.

To get rid of the www directory and keep things the “Express 3 way”,delete the line that says module.exports = app; at the end of theapp.js file, then paste the following code in its place:

app.set('port', process.env.PORT || 3000)var server = app.listen(app.get('port'), () => { debug('Express server listening on port ' + server.address().port)})

Ensure that you load the debug module at the top of the app.js file by using the following code:

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

Next, change "start": "node ./bin/www" in the package.json file to "start": "node app.js".

You have now moved the functionality of ./bin/www back toapp.js. This change is not recommended, but the exercise helps youto understand how the ./bin/www file works, and why the app.js fileno longer starts on its own.

Migrating to Express 4 (2024)

References

Top Articles
Latest Posts
Article information

Author: Terence Hammes MD

Last Updated:

Views: 5941

Rating: 4.9 / 5 (69 voted)

Reviews: 84% of readers found this page helpful

Author information

Name: Terence Hammes MD

Birthday: 1992-04-11

Address: Suite 408 9446 Mercy Mews, West Roxie, CT 04904

Phone: +50312511349175

Job: Product Consulting Liaison

Hobby: Jogging, Motor sports, Nordic skating, Jigsaw puzzles, Bird watching, Nordic skating, Sculpting

Introduction: My name is Terence Hammes MD, I am a inexpensive, energetic, jolly, faithful, cheerful, proud, rich person who loves writing and wants to share my knowledge and understanding with you.