Headless Drupal & Node.js | Part 3/3: Express JS and Drupal API integration

Posted by Joris Snoek on 09 Oct, 2015
Node Author

Here at Lucius HQ we are always interesting in cool new stuff. So to discover the decoupled world, we built our new corporate website with Node.js and headless Drupal 8. In this blog serie we explain the implementation.

This is the third and last part of the 'Headless Drupal & Node.js' serie. Previously:

In this last part I'll show you:

  1. Installation and intro Express JS in Node.js
  2. Routes and dynamic templates with EJS in Express JS.
  3. Connect the JSON data from the RESTful Drupal 8 web service

1) Installation and intro Express JS in Node.js

As described in in part 2, Node.js on it's own is a minimalistic webserver and not primary developed for websites. If you want to implement websites in Node.js, then Express JS will give you the needed kick-start. It's a 'Fast, unopinionated, minimalist web framework for Node.js'.

It contains robust features to build web -and mobile applications, you can also implement is for building API's. Express JS provides Node.js with the needed structure that's not present if you use Node.js on it's own. Express JS facilitates in:

Templating

Express JS contains two templating engines: the default is Jade, the second is EJS. Jade is ‘whitespace based’ and is used as follows:

EJS is more 'full HTML' based, we choose to work with that.

Routing

Express JS also provides a routing system so you can manipulate the content of your website based on URL as needed for dynamic, cms driven websites.

MVC

Express JS is MVC based: Model View Controler, a modern way to build web application. This facilitates a modular based implementation of your web application so your application is more structured, better to maintain and extend.

  • Model: the data that your web application is going to use.
  • View: this is where the data will be poured into - the template in EJS.
  • Controller: the Javascript that pours the data in the dynamic templates.

Installation Express JS

In part 2 I described the install of modules with NPM. You can install NPM modules in two ways on your server:

  1. As a global application
  2. Per project based

It depends on your project how to install, for this project I install it both ways: global and in the project.

Global installation Express JS

The global version is needed, because that also installs needed Command Line Interface Tools (CLI’s). In your terminal enter:

npm install -g express

If you get an error, then try as super user:

sudo npm install -g express

Now when you enter express --version you should get a response like:

Installation Express JS in your project

Now enter npm install express --save

Express JS will be added to your project as a dependency, you can also see that in the package.json file (see also part 2).

Express JS is now installed, we can start with a 'Hello Express'.

‘Hello Express’

We implemented hellotest.js as the main app file in part 2. I open that file and add following code:


var express = require('express');

==> Create the variable 'express' and define the library 'express' you want to use.

var app = express();

==> Create the variable 'app' for this application that we'll build with Express JS. By namespacing this application we can now use the methods that Express JS provides in the global variable 'app'.

app.get ('/', function(req, res){
    res.send('Hello Express');
});

==> This simple example provides a route for a homepage request. It answers with a short text.

As you can read in part 2: in Node.js you needed to define the mime-type yourself. But because Express JS knows you're working with a web protocol that's not needed anymore.

var server = app.listen (2000, function(){
    console.log('Waiting for you on port 2000');
});

==> Create the server on port 2000.

To test this in a browser I first need to start the app: enter node hellotest.js in a terminal:

Now when I browse to http://localhost:2000 I see

As you can see, this is similar to the example in Node.js as described in part 2, but we use Express JS methods that make thing easier for us. For a complete overview of all methods, properties and events, see Express JS API.

Routes in Express JS

Routes take care of dynamic, url-based websites. Express JS excels in facilitating the needed routes, it's like Drupal's hook_menu(). I add two routes as follows:

When I go to my browser /about-us:

Routes with variables

It's also possible to parse information via routes to the application. The information can be placed in the parameters variable within the request object. The variables will be mapped to - and will be available in - the request parameters array:

var name = req.params.name;

==> Places everything after /about/ in a variable 'name'. This is done via the request parameters array req.params of Express JS: it places an object 'name' in the array and sends that to a local variable 'name'.

Then I'll print 'name' within h1 tags, wich generates simple dynamic output based on URL.

You can add multiple variables:

This wil result in:

The 404 for example:

2) Routes and dynamische templates with EJS in Express JS

Till now we used res.send, but there is a better way to do this: via dynamic templates. As described above, Express JS uses Jade as default templating engine. We use EJS:

Within EJS you can use full HTML and provide dynamic content via tags.

Installation EJS

Enter in your terminal: npm install ejs --save

You should now see the dependency in the package.json:

Now EJS is installed, you can activate it in the application:

app.set('view engine','ejs');

Now we create a new folder 'views', where we place a default HTML document 'default.ejs':

And we can call this template with res.render(). Applied to the homepage:

Express JS knows that he has to look in the folder 'views' for template files, that's a default. You can define your own custom folder:

app.set(‘views’, __dirname + ‘/YOURFOLDER’);

__dirname is a global, so you can use this anywhere.

Send data (content) to the template

You can add an extra object with data to your template:

In the template, you can print this:

In browser:

You can also use Javascript in the EJS templates like this <% your kick-arse Javascript %> instead of <%= your printable variable %>.

Good to know:

  • 'templates' are the same as 'views'.
  • 'data' is also called 'the modal'.
  • if you put together the 'modal' with 'views' you'll get dynamic websites.

Structure routes an templates in Express JS

When you define routes than it's a best practice to place them outside of the 'main app' file. This way you keep your stuff more organized:

  • Create a new folder 'routes'.
  • Create a new file in there 'index.js'.
  • Import the express module and define the 'router' variable.
  • Move the routing code to the new file:

Now change the main-app file, 'hellotest.js' in this example:

  • Define the 'routes' variable
  • Add app.use  (‘/’, routes):

Alrighty, now your routes and views are split up in different folders, so your application is better organized.

Last thing to do is integrated the content data from the Drupal 8 RSSTful API.

3) Drupal RESTful API data integration in Node.js

We now have implemented the fundamentals in Node.js with help of Express JS. Also, we have the Drupal data available in JSON, see part 1. Now it's time for the magic: integrate these two.

Installation NPM 'Request' module

To import the external JSON data we first need an extra NPM module Request. This is a populair module, that makes it easy to make http calls and exchange data. So to install it, enter in your terminal npm install request (prepend ‘sudo’ when you get an error):

Now the module is installed, we have to import it in our project:

var request = require(“request”);

Importing the JSON data from the Drupal web service

Now the Request module is installed, we can use it's functions. I use this script to read the blog data:

  • Line 5: I create the variable that will contain the URL of the Drupal JSON export.
  • Line 13-32: read the JSON object and add the correct fields in an array. That array is placed in a global variable app.locals.blogsdata.

app.locals.XYZ is used in Node.js for global variables, these will be available in all templates. To make this easy for myself I place the blog data in a global var for now. Because we also need it on all pages in the footer.

So now all blog content data from the Drupal API is available in the global var app.locals.blogsdata.

Integration the Drupal data in a dynamic EJS template

As an example we use our blog overview page, that shows the 5 most recent (Dutch) Drupal blogs. We can build this page as follows:

Create the base HTML page and include the content part with an extra file:

Create a new folder 'content' within the 'views' folder and create a file 'blog-overview-articles.ejs'. In this file we print the Drupal blog data with help of some server-side Javascript:

To fresh up your memory, this is the JSON object we are working with from part 1

Now we've built the blog overview page in Node.js combined with content data from the Drupal 8 API. You can see the result here (Dutch Drupal blog).

Integrating the Drupal API data on blog detail page

The URL format is as follows: '/blog/blog-item-title/'. The content of the page depends on this variable URL, especially the part after '/blog/'. Earlier in this post you saw how to handle variables via URL. So we now can route the data as follows:

We check the current URL and see if there is a match on a URL in the JSON object. When that is found, the associated data is placed in an array that will be send to the template.

Wrap up

Ok, that's it for the serie 'Headless Drupal & Node.js'. Off course this is just an quick intro of Drupal Web services, Node.js and Express JS.

We only touched the 'GET' of the Drupal RESTful API. Stuf like POST, PUT, DELETE, OPTIONS are also possible in Drupal 8. But we didn't need them in this example.

Also we only touched the surface of Node.js and Express JS, but hopefully enough to build some cool high performance dynamic websites.

We are planning to write more in-depth blogs about this stuff, so stay tuned!

-- Cheers, Joris