hapi — Extend Your Server Functionality With Plugins

Within last week’s tutorial, you’ve learned how to get your first hapi server up and running. This guide will continue on that basis and you’ll extend the server’s functionality by adding a plugin that enhances log output. Actually, it’s important to understand hapi’s powerful plugin system, because it allows you to break your application down into smaller, independent modules. However, we’ll get to that in a second.

Before moving on, have a look at other posts within this series, there might be a good catch.

hapi Series Overview

Make Use of hapi’s Plugin System

hapi ships with an extensive and powerful plugin system right away. Actually, it’s an unwritten best practice to break your application into isolated chunks of functionality and reusable utilities. Optimally, you can break down your application into individual plugins and the hapi server instances just provides the required configuration.

Add Console Output as a Plugin

Process monitoring can be an essential part of your application to listen on server events to identify the data flow within your application and individual states. Further, it can be used to provide proper console logs. There’s a process monitoring plugin for hapi, called good, and you’ll use it to listen in server events. Additionally, you’ll use a reporter plugin —good-console— to output data for selected events to the console.

Starting Point

As a basis for the upcoming examples, create a simple hapi server listening on localhost with port 3000.

var Hapi = require('hapi')

// create new server instance
var server = new Hapi.Server()

// add server’s connection information
server.connection({  
  host: 'localhost',
  port: 3000
})

That’s the starting point and you’ll extend that server by adding a plugin as described in the following paragraph.

Load a Plugin to Your Server Instance

The hapi server instance provides a register(server, options, next) method that excepts either a single plugin or a list of plugins. The method signature for register() outlines the server instance itself and as a second parameter, an options object. Of course, each plugin requires its own options and has a different schema. Just have a look at the plugin’s documentation to know what options you need to provide.

Generally, you can easily add a plugin like this:

// shortcut to register a plugin to hapi’s server instance
server.register(require('my-plugin'))  

Further, you’ve the ability to add a callback function as the last parameter for the server.register() method. However, if your plugin doesn’t require any options, you can just pass it to hapi’s server and extend its default functionality.

In a later tutorial, we’ll go in detail on how to create your own custom plugin. For now, we’ll use the existing good plugin from hapi’s ecosystem and register it to the server. Besides good, we’ll define good-console as a reporter within the good plugin’s options.

The snippet above showed you how to easily register a plugin to your hapi server instance. There are situations where your plugin needs application specific configuration or options and you want them to pass during the plugin registration phase. Actually, that’s also available using the register() method by passing an object that provides two fields: register and options.

The following code block illustrates the registration of the good plugin within the server.register({…}) method.

var Good = require('good')

// register plugins to server instance
server.register({  
  register: Good,
  options: {
    reporters: [{
      reporter: require('good-console'),
      events: {
        response: '*',
        log: '*'
      }
    }]
  }
})

As you can see, if you want to pass further options to your plugin, use the method shown in the code above. The good plugin requires and receives further options and we define good-console as the console output for the server events of response and log. That means, using the server.log method will trigger the log event and good outputs the provided data to the command line.

At this point, you may ask yourself: it’s recommended to break down the application code into plugins, is there a way to register multiple plugins at once to avoid having lots of server.register statements? In short: yep, hapi got your back!

Load Multiple Plugins at the Same Time to Your Server

Actually, hapi allows you to load either one or many plugins at the same time using the register() method. Of course, you can use the ways as already described above to add a plugin. the following code block outlines the three ways to import plugins into hapi’s server instance.

var Good = require('good')

// register multiple plugins at once to server instance
server.register([  
  {
    register: require('good'),
    options: {
      reporters: [ {
        reporter: require('good-console'),
        events: { log: '*', response: '*' }
      } ]
    }
  },
  // register plugin without options #1
  {
    register: require('my-plugin')
  },
  // register plugin without options #2
  require('another-plugin')
])

Please note that you need to provide a list of plugins for the server.register() method to add multiple at the same time. Within the list, you can either define an object having at least the register field defined and optionally providing options. Further, you can just pass the plain plugin by requiring it right away.

Impact of Good Plugin to the Server

Up to this point, you’ve learned how to register the good plugin to your server. Let’s explore the changes when applying the plugin for use. The example code for this tutorial is available on GitHub and we recommend to check it out on your own.

In the following, you’ll see the difference between the console outputs with and without using the good plugin.

Before

// start hapi server
server.start(function (err) {  
  console.log('Server running at: ' + server.info.uri)
})

Console output:

$ node server.js
Server running at: http://localhost:3000  

After

// start hapi server
server.start(function (err) {  
  server.log('info', 'Server running at: ' + server.info.uri)
})

Console output:

$ node server.js
160411/102456.564, [log,info], data: Server running at: http://localhost:3000  

Leveraging good allows you to keep track of fine grained information and especially the output importance. Using just console.log(msg) won’t put any priority to the information, but using server.log('info', msg) or server.log('error', msg) indicates directly the difference between each of the log messages.

That’s just the tip of the logging iceberg and actually it’s not the priority of this post. The important take away is to understand how you register plugins to hapi.

Outlook

This tutorial guided you through the required knowledge to import existing or custom plugins. You’ve learned how to register one or many plugins to your hapi server instance and besides that, how to pass plugin specific options during registration phase.

We’ve mentioned at the beginning of this post, that it’s best practice to create custom plugins for the functionality of your application. Within the next post, you’ll learn how to create your own custom plugin to extend the server’s functionality.

If you feel there’s anything missing in this guide, please let us know in the comments below or send us a tweet @futurestud_io

Enjoy coding & make it rock!


Additional Resources

Explore the Library

Find interesting tutorials and solutions for your problems.