How does Node.js render JavaScript Highcharts server-side?

Learn how to use Node.js to easily render charts made with Highcharts as images on your server.

Consider the following context, as that is the one I discovered a few months ago. I’m working on a large Symfony project running on PHP 7 and as we all know, libraries for creating diagrams in PHP are really bad. Therefore, the option is to create the diagram using an alternative solution in JavaScript, as the diagram should only appear on the browser when the user uses the application. Unfortunately, after a few months, they need to create PDF reports that need to have the same charts that are displayed on the browser (yes, great, I also need to embed them in the PDF). In terms of the knowledge I had at the time, the situation was very problematic.

After some research, I found out that luckily I was using Highcharts in my browser to create the chart, so the solution to implement it on the server side already existed, so I didn’t need to rewrite the chart on the server – the code for side as the front-end chart should be similar.

How does Node.js render JavaScript Highcharts server-side? In this article, I’ll explain to you how to easily render highchairs on your server using Node.js and modules.highcharts-export-server

request

Let’s assume that you already have Node.js installed on your server.

Install the Highcharts export server

Server-side rendering of JavaScript Highcharts: The first way to use it is to use it as a module. This means that you can write your own scripts to create image versions of the charts in a custom way. In this case, we will simply create a script that will use custom code to generate the chart. The second way is to run the module as an HTTP service (as a server), so a third-party application like you’re using can simply make a request to that server to get an image in response.highcharts-export-server

In the first step, use NPM to install the module with the following command:

npm install highcharts-export-server

The installation will take a while as this will install the Highcharts library and PhantomJS. When you install highchairs, you’ll be prompted to provide information about licenses and other modules, and in our case, we’ll be using the free version, so the answer to most prompts will be no.

For more information on the high charts-export-server module, visit the official repository on GitHub here.

A. Use the Highcharts export server as a module

There are several ways to export charts using the HighCharts export server. I will describe the most useful ones in this article:

Export as a PNG image

How does Node.js render JavaScript Highcharts server-side? In this example, we’ll create an index.js file that will be executed using Node.js. This file contains the basic implementation of the highcharts export module, which it will import along with the file system module. Then, initialize the exporter (PhantomJS) and define the options for the chart. The object contains the information, labels, data, etc., that you normally use to draw charts on the front end. Then use the chartExporter’s export method to run the chart on a headless browser (PhantomJS), and when it is rendered, the browser will trigger a callback that allows you to get the base64 information of the image and save it to the file:chartOptions

// /index.js

// 1. Import filesystem and Highcharts Export Server module
const fs = require("fs");
const chartExporter = require("highcharts-export-server");

// Initialize the exporter
chartExporter.initPool();
// Chart details object specifies chart type and data to plot

// Usually the same object that you use to configure your charts
// in the frontend. This will be used to specify the chart type
// and data to plot. I will use a bar chart, the same data
// specified in one of the official demonstrations in the HC website
let chartOptions = {
    chart: {
        type: 'bar'
    },
    title: {
        text: 'Historic World Population by Region'
    },
    subtitle: {
        text: 'Source: Our Code World'
    },
    xAxis: {
        categories: ['Africa', 'America', 'Asia', 'Europe', 'Oceania'],
        title: {
            text: null
        }
    },
    yAxis: {
        min: 0,
        title: {
            text: 'Population (millions)',
            align: 'high'
        },
        labels: {
            overflow: 'justify'
        }
    },
    tooltip: {
        valueSuffix: ' millions'
    },
    plotOptions: {
        bar: {
            dataLabels: {
                enabled: true
            }
        }
    },
    legend: {
        layout: 'vertical',
        align: 'right',
        verticalAlign: 'top',
        x: -40,
        y: 80,
        floating: true,
        borderWidth: 1,
        backgroundColor: '#FFFFFF',
        shadow: true
    },
    credits: {
        enabled: false
    },
    series: [{
        name: 'Year 1800',
        data: [107, 31, 635, 203, 2]
    }, {
        name: 'Year 1900',
        data: [133, 156, 947, 408, 6]
    }, {
        name: 'Year 2000',
        data: [814, 841, 3714, 727, 31]
    }, {
        name: 'Year 2016',
        data: [1216, 1001, 4436, 738, 40]
    }]
};

// Export chart using these options
chartExporter.export({
    type: "png",
    options: chartOptions,
    // By default the width of the chart images is of 600
    // In this case, we want a big image
    width: 1200
}, (err, res) => {
    // Get the image data (base64)
    let imageb64 = res.data;

    // Filename of the output. In this case, we will write the image
    // to the same directory of the initialization script.
    let outputFile = "./output-chart.png";

    // Save the image data to a file
    fs.writeFileSync(outputFile, imageb64, "base64", function (err) {
        if (err) console.log(err);
    });

    console.log("The chart has been succesfully generated!");

    chartExporter.killPool();
});

If you’re running scripts using Node.js, use:

node index.js

The script will be executed, producing a successful output and image, in which case the image with the information of this example will look like this:output-chart.png

You can now embed images anywhere you want, such as in a browser, PDF, etc.

Use as a module (export as SVG file)

If you want to export the chart in SVG format, you can do that with the module as well. You need to change the type property with SVG as the value and provide the parameters:outfile

// /index.js

// 1. Import filesystem and Highcharts Export Server module
const fs = require("fs");
const chartExporter = require("highcharts-export-server");

// Initialize the exporter
chartExporter.initPool();
// Chart details object specifies chart type and data to plot

// Usually the same object that you use to configure your charts
// in the frontend. This will be used to specify the chart type
// and data to plot. I will use a bar chart, the same data
// specified in one of the official demonstrations in the HC website
let chartOptions = {
// .. Chart Type, Data etc.
};

// Export chart using these options
// Export the chart as an SVG file
chartExporter.export({
type: "svg",
outfile: "./output-file.svg",
options: chartOptions
}, (err, res) => {
console.log(`The chart has been succesfully generated as SVG at ${res.filename}!`);

chartExporter.killPool();
});

B. Use of Highcharts Export as a Service

Approach to server-side rendering JavaScript Highcharts: Right now, using it as the first solution for modules is great for small applications that don’t theoretically use the feature too much. However, if you’re trying to create a service where multiple applications can interact with creating chart images, then the best way is to run the module as a server. Therefore, you need to install highcharts-export-server globally:

npm install highcharts-export-server -g

The installation will prompt the same things as when installing a module, licenses, installing PhantomJS, etc. Once the installation is complete, you should be able to run a command from the terminal to enable it as a server using the enable server parameter:

highcharts-export-server --enableServer 1 --host localhost --port 7801

This command will essentially start the server with the given configuration:

In this case, the address will be http://localhost:7801 because I work locally. If you want to run it on a live server, you’ll also need to configure a reverse proxy if you want to use Nginx in a specific domain.

How Node .js renders JavaScript Highcharts on the server side: Now, with this, you can render charts from a web service. Perform a simple request to a defined address using the chart data, and the response will be an image of the chart. The JSON we send in the request will look like this:application/json

{
    "infile": {
        "title": {
            "text": "Steep Chart"
        },
        "xAxis": {
            "categories": [
                "Jan",
                "Feb",
                "Mar"
            ]
        },
        "series": [
            {
                "data": [
                    29.9,
                    71.5,
                    106.4
                ]
            }
        ]
    },
    "width": 1200
}

You can test this with curl, for example, the following command will request a diagram with the previous information and store it in a file:output-file.png

curl -H "Content-Type: application/json" -X POST -d "{ \"infile\": { \"title\": { \"text\": \"Steep Chart\" }, \"xAxis\": { \"categories\": [ \"Jan\", \"Feb\", \"Mar\" ] }, \"series\": [ { \"data\": [ 29.9, 71.5, 106.4 ] } ] }, \"width\": 1200 }" localhost:7801 -o output-file.png

In this case, the response would be:

Happy coding ❤️!