Developing on the client side with Ionic is a pleasure. It’s based on the web tech we know and love, and it runs straight in the browser so we can dive straight into the development in minutes. You can only get so far developing purely on the front-end/client-side, though.
If your application needs to provide authentication, pull in data from an external source, store data externally, share data with other users – generally anything that requires that the application break out of the little sandbox it lives in and communicate with the outside world – then you will need to use some kind of backend/server-side code. When you integrate a backend, your application will be communicating with some server on the Internet that will act as the go-between for your application and any external services it needs to interact with (like a remote database).
Your backend could make use of a service like Firebase, or perhaps your application will only need to communicate with some 3rd party API, or maybe in some cases, you would want to create and host your own backend. When it comes to deciding on a backend, your options are almost unlimited.
If you are unfamiliar with exactly how a backend fits into the scope of an Ionic application, I would recommend reading this article first, and for an overview of a few of the options out there you can read A Summary of Backend Options for HTML5 Mobile Applications.
One particularly popular backend when it comes to Ionic/Angular applications is NodeJS. The popularity of NodeJS as a backend technology is at least partly due to the fact that it allows you to write your backend with JavaScript as well. In the same way that web developers may feel more comfortable using Ionic due to the familiarity of building with web tech, those same developers may also feel more comfortable building with NodeJS rather than learning a new language/syntax for the backend.
It is super easy to spin up a NoseJS server and host it for free somewhere (or just run it locally for development), and so I often rely on NodeJS for tutorials that require some kind of backend. I’ve written several tutorials in the past that rely on a NodeJS server:
- Building a Hotel Booking App with Ionic, MongoDB & Node
- Building a Review App with Ionic, MongoDB & Node
- Using JSON Web Tokens (JWT) for Custom Authentication in Ionic
However, the main focus is usually on the Ionic code, and I’ve never gone into much detail about the creation of the server itself. Even though it uses JavaScript, NodeJS code can look pretty intimidating at first (not to mention the fact that writing your own server sounds pretty difficult).
With that in mind, I am going to spend a bit of time writing about some Node basics. In this tutorial, I am going to start by giving a very bare bones introduction to what a basic NodeJS server might look like. I’ll try not to get too bogged down in specifics, and instead, attempt to explain it in a way that will make sense to people who have little to no backend experience.
A Basic NodeJS Server
Almost every NodeJS server I create starts more or less the same, and it looks like this:
server.js
var express = require('express');
var bodyParser = require('body-parser');
var logger = require('morgan');
var methodOverride = require('method-override');
var cors = require('cors');
var app = express();
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(methodOverride());
app.use(cors());
app.listen(process.env.PORT || 8080);
An important thing to note if you are used to Ionic development is that we are just using standard ES5 JavaScript here – the ES6 features and other features made available to us through the use of TypeScript that is set up by default in Ionic are not set up here. We won’t be using keywords like let
, const
, and import
, nor will we be able to use other common ES6 features like fat arrow functions.
What we are doing in the code above is setting up a few variables to hold references to the various packages we will be using (again, we use require
instead of import
because we are using ES5 Javascript).
We will be talking more about express
shortly, but this is what we will be primarily relying on to build our server. The other packages are not quite as important to understand at this stage – body-parser
will help grab information from POST requests, method-override
provides support for DELETE
and PUT
requests, morgan
outputs useful debugging messages, and the cors
package provides a simple way to handle CORS (Cross Origin Resource Sharing) issues.
We create a new express
application on the app
variable, and then we set up our various packages on that application. We can then ask the server to start listening for requests by calling the listen
method. If there is a PORT
environment variable defined (we will talk about what that means in another tutorial) then it will start listening on whatever port is defined, otherwise the server will start listening for requests on port 8080
by default (just like when you serve your Ionic applications in the browser it will run over port 3000
).
Before the server becomes useful we will need to talk a little more about Express, but the above is all of the code we need to get the server running. Depending on your requirements, your server may include different packages that you will set up here (like whatever database integration you may be setting up).
In order for this server to work, you will also need to define a package.json
file that lists any dependencies:
{
"name": "app-name",
"version": "0.1.0",
"description": "My Description",
"engines": {
"node": "6.11.1"
},
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"body-parser": "^1.15.2",
"cors": "^2.8.0",
"del": "2.2.0",
"express": "^4.14.0",
"http": "0.0.0",
"method-override": "^2.3.6",
"morgan": "^1.7.0"
}
}
This is not much different to a normal package.json
file in an Ionic application. You can either manually add your dependencies here, or you can install them individually with:
npm install package-name --save
One important part of this package.json
is that it defines the “start” script to be run. To start this server, the node server.js
command must be run, because the file that contains our server code is called server.js. To run the server locally, you would first need to install any dependencies by running:
npm install
and then you just need to run the following command:
node server.js
and the server would start running locally, meaning you could access it over:
http://localhost:8080/
Using Express to Create Routes
We have created a working NodeJS server above, and the server would listen for requests, but it is pretty pointless right now because the server wouldn’t do anything with the requests and it doesn’t provide any responses.
The way that we would integrate our Ionic application with our NodeJS server is for the Ionic application to make HTTP requests to the server. Our Ionic application might make a request to:
this.http
.get('http://localhost:8080/posts')
.map((res) => res.json())
.subscribe((data) => {
console.log(data);
});
We are making a request to the /posts
route and then we would expect that the server give us some useful information in the response. So, we need to set up these “routes” on our server that our application can make requests to, and we can do that using Express. To set up a route in a NodeJS application that is using Express, all we need to do is this:
var express = require('express');
var bodyParser = require('body-parser');
var logger = require('morgan');
var methodOverride = require('method-override');
var cors = require('cors');
var app = express();
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(methodOverride());
app.use(cors());
app.get('/posts', function (req, res) {
console.log('posts!');
});
app.listen(process.env.PORT || 8080);
If we were to run this server and take a look at the terminal, whenever the server received a GET
request to this URL:
http://localhost:8080/posts
we would see posts!
output in our debug messages. This also isn’t entirely useful, so we need to extend that route a bit further:
app.get('/posts', function (req, res) {
res.json({ success: true });
});
We can use the req
parameter to get information about the request that was made (this would be especially useful if you wanted to send some data along with a POST request for example), and we can use the res
parameter to send a response from the server. In this case, we use the json
method to send a JSON response, which could then be received by our Ionic application.
If you wanted to handle a POST
request instead of a GET
request you would do this instead:
app.post('/posts', function (req, res) {
res.json({ success: true });
});
This is a simplistic example, usually, you would have some code executing to go fetch that data from somewhere, maybe you would check if the user was authenticated, and you would also have code to handle errors and send responses appropriately. But this is the basic idea.
Deploying the Server
If you were to install the Ionic application on your phone, or anywhere other than the machine your server is running on, and attempt to make a request from the application it wouldn’t work. Since the server is running locally, you can only make requests to the server if your application is also running locally.
In order to make your application accessible to everybody in the world, you will need to host your NodeJS server, and then you would make requests to:
this.http
.get('https://my-server.com/posts')
.map((res) => res.json())
.subscribe((data) => {
console.log(data);
});
One particularly easy way to get your NodeJS server up and running is to use Heroku. I plan on covering this in-depth in another tutorial, but if you can’t wait you can check it out here.