Introduction
In this tutorial, I will explain you step by step how to create a modern, hybrid, mobile application (iOS and Android) of your WordPress website using the latest technologies. We'll be using Ionic Framework, ECMAScript 6, npm, webpack, andApache Cordova.
At the end of this tutorial you will get the following application. It has only three modules, a Home module that displays your latest posts, a Post module that displays a specific post, and a Menu module that displays the menu.
1. Tools
Ionic Framework
The beautiful, open source front-end SDK for developing amazing mobile apps with web technologies.
Ionic Framework ecosystem is large, including Ionic CLI (command line tool), Ionic Push (easy push notifications), and Ionic Platform (backend services). It is currently one of the top open-source projects on GitHub with more than 19,000 stars and over 600,000 apps created.
Ionic covers all your application's needs. However, for this tutorial I will only focus on Ionic Framework (or Ionic SDK), which is a set of AngularJS directives (Web Components) and services.
ECMAScript 6 (ES6)
ECMAScript 2015 (6th Edition) is the current version of the ECMAScript Language Specification standard. ES6 got officially approved and published as a standard on June 17, 2015 by the ECMA General Assembly.
ECMAScript 6 gives you access to a lot of new features, many of which are inspired by CoffeeScript, including as arrow functions, generators, classes, and let scoping. Even though ES6 got approved recently, you can use it right now using a JavaScript compiler, such as Babel.
Node Package Manager (npm)
Node Package Manager is the most popular package manager in the world. The number of packages is growing faster than Ruby, Python, and Java combined. npm runs on Node.js.
Why Not Bower?
We opt for npm, because using both Bower and npm in the same project is painful and CommonJS support with Bower isn't straightforward. CommonJS defines a module format to solve JavaScript scope outside the browser and npm supports this. CommonJS modules can be required using ES5 or ES6.
1
2
// ES5
var
angular = require(
'angular'
);
1
2
// ES6
import
angular from
"angular"
;
1
2
| // ES5 var angular = require( 'angular' ); |
1
2
| // ES6 import angular from "angular" ; |
webpack
In my opinion, webpack has been a game changer in the industry, exit complicatedGrunt or Gulp scripts that you need to maintain. webpack allows you to require any type of file (.js, .coffee, .css, .scss, .png, .jpg, .svg, etc.) and pipe them throughloaders to generate static assets that are available to your application.
The difference with Grunt and Gulp is that the majority of your needs (minification and compilation) can be covered by just adding some configuration, there's no need to create scripts. For instance, requiring a Sass file, compiling it, autoprefixing it, and injecting the resulting minified CSS into your application will be as simple as this:
1
2
3
4
{
test: /\.scss$/,
loader:
"style!css!autoprefixer!sass"
}
I don't think I need to show you the equivalent using Gulp or Grunt. I think you get my point.
1
2
3
4
| { test: /\.scss$/, loader: "style!css!autoprefixer!sass" } |
2. Prerequisites
This tutorial assumes that you have:
- a basic knowledge of AngularJS and Ionic
- a WordPress website ready to be queried (a local installation is fine)
- a machine with Node.js, npm, Bower (we'll need it for some dependencies)
- Git installed with write access without sudo on the project folder
3. Installation
Before we get started, you will need to install two things:
- a WordPress plugin that turns your blog into a RESTFUL API
- the application itself
RESTFUL API
To fetch the posts for your WordPress installation, you will need to install WP REST API plugin. Make sure that you install version 1.2.x as version 2.x is on its way.
- In WordPress, go to Plugins > Add New.
- Search for WP REST API (WP API).
- Click Install Now to install the plugin.
- If the installation is successful, click Activate Plugin to activate it.
If the installation was successful, open a browser and enter http://example.com/wp-json. This should give you a response similar to the one below.
1
2
3
4
5
6
7
8
{
"name"
:
"Lorem Ipsum blog"
,
"description"
:
"Just another WordPress site"
,
"routes"
: {},
"authentication"
: {},
"meta"
: {}
}
1
2
3
4
5
6
7
8
| { "name" : "Lorem Ipsum blog" , "description" : "Just another WordPress site" , "routes" : {}, "authentication" : {}, "meta" : {} } |
Application
To install the application, clone the repository, using the following commands.
1
2
3
4
# Clone the repository and give it a name (here myTutorial)
$ git clone https:
//github
.com
/tutsplus/Hybrid-WordPressIonicAngularJS
.git myTutorial
# Open the project
$
cd
myTutorial
Next, create a configuration file and install the dependencies.
1
2
3
4
# Copy the default config to your personal config
$
cp
config
/default
.config.json config
/config
.json
# Install dependencies
$ npm
install
To make sure both the application and the REST API work together, open config/config.json. This is your personal configuration file, which is ignored by Git. Change the base URL of the API to the one for your WordPress installation.
1
2
3
4
5
Run npm run devserver
and open http://localhost:8080/webpack-dev-server/ in a browser. If everything works as expected, you should be in front of a running application that displays your WordPress posts. I have created a demo application to give you an idea of what to expect.
Now that you can see the result of what we are after, let me go through the details. Note that the following code samples are simplified. You can find the source code on GitHub.
1
2
3
4
| # Clone the repository and give it a name (here myTutorial) $ git clone https: //github .com /tutsplus/Hybrid-WordPressIonicAngularJS .git myTutorial # Open the project $ cd myTutorial |
1
2
3
4
| # Copy the default config to your personal config $ cp config /default .config.json config /config .json # Install dependencies $ npm install |
1
2
3
4
5
|
npm run devserver
and open http://localhost:8080/webpack-dev-server/ in a browser. If everything works as expected, you should be in front of a running application that displays your WordPress posts. I have created a demo application to give you an idea of what to expect.4. Dependencies
The npm install
command installed several libraries. Some of them are direct dependencies while the rest are development dependencies.
npm install
command installed several libraries. Some of them are direct dependencies while the rest are development dependencies.Direct Dependencies
The direct dependencies are dependencies that your application needs in order to run properly when built.
1
2
3
4
"dependencies"
: {
"ionic-sdk"
:
"^1.0.0"
,
"wp-api-angularjs"
:
"^1.0.0"
}
Notice that the application doesn't directly depend on AngularJS, because ionic-sdk already includes angular.js, angular-animate.js, angular-sanitize.js, and angular-ui-router.js.
wp-api-angularjs (WordPress WP API client for AngularJS) is a set of AngularJS services that allow communication with the REST API plugin that you installed earlier. You can see the complete list of dependencies on GitHub.
1
2
3
4
| "dependencies" : { "ionic-sdk" : "^1.0.0" , "wp-api-angularjs" : "^1.0.0" } |
Development Dependencies
Development dependencies are mostly webpack loaders. Loaders are functions that take the source of a resource file, apply some changes, and return the new source. We need loaders that handle .scss, .js (ES6), .html, and .json. You can see a complete list of development dependencies on GitHub.
5. Application Architecture
I have been developing AngularJS applications for a long time and after a lot of experimenting I have committed to the following architecture:
- a file that can be edited live under the
src/
or /lib
folder
- every AngularJS module needs a proper folder
- every module file
*.module.js
must define a unique namespace (and be the only place where this namespace appears)
- every module file
*.module.js
must declare all its dependencies (even if dependencies are already injected in the app)
- every module file
*.module.js
must declare all its configs, controllers, services, filters, etc.
- every config, controller, service, filter, etc. must export a function (CommonJS)
- if a module needs a specific style, the .scss file must live within the module
These recommendations are powerful as they assure that you to have loosely coupled modules that can be shared by several applications without running into problems.
This is what the application folder structure looks like:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
lib/
├── menu/
│ └── menu.module.js
│ └── menu.html
├── home/
│ └── home.module.js
│ └── home.config.js
│ └── home.controller.js
│ └── home.html
├── post/
│ └── post.module.js
│ └── post.config.js
│ └── post.controller.js
│ └── post.html
├── scss/
│ └── _variables.scss
│ └── bootstrap.scss
├── index.js
├── index.html
src/
or /lib
folder*.module.js
must define a unique namespace (and be the only place where this namespace appears)*.module.js
must declare all its dependencies (even if dependencies are already injected in the app)*.module.js
must declare all its configs, controllers, services, filters, etc.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
| lib/ ├── menu/ │ └── menu.module.js │ └── menu.html ├── home/ │ └── home.module.js │ └── home.config.js │ └── home.controller.js │ └── home.html ├── post/ │ └── post.module.js │ └── post.config.js │ └── post.controller.js │ └── post.html ├── scss/ │ └── _variables.scss │ └── bootstrap.scss ├── index.js ├── index.html |
Entry Point
When using webpack, an entry point is necessary. Our entry point is lib/index.js. It contains our application's basic dependencies (such as ionic.bundle that contains AngularJS), our home-made modules, and adds the Sass entry point.
01
02
03
04
05
06
07
08
09
10
11
// Ionic, Angular & WP-API client
import
'ionic-sdk/release/js/ionic.bundle'
;
import
'wp-api-angularjs/dist/wp-api-angularjs.bundle'
;
// Our modules
import
modHome from
'./home/home.module.js'
;
import
modPost from
'./post/post.module.js'
;
import
modMenu from
'./menu/menu.module.js'
;
// Style entry point
import
'./scss/bootstrap'
;
Now that we have imported our dependencies we can create our application module. Let's call our app prototype. It has ionic
, wp-api-angularjs
, and our home-made modules as dependencies.
1
2
3
4
5
6
7
8
// Create our prototype module
let
mod = angular.module(
'prototype'
, [
'ionic'
,
'wp-api-angularjs'
,
modHome,
modMenu,
modPost
]);
Once the module is created, we can export it as a standard CommonJS module.
1
export
default
mod = mod.name;
This is a great example of what an AngularJS module should look like.
01
02
03
04
05
06
07
08
09
10
11
| // Ionic, Angular & WP-API client import 'ionic-sdk/release/js/ionic.bundle' ; import 'wp-api-angularjs/dist/wp-api-angularjs.bundle' ; // Our modules import modHome from './home/home.module.js' ; import modPost from './post/post.module.js' ; import modMenu from './menu/menu.module.js' ; // Style entry point import './scss/bootstrap' ; |
ionic
, wp-api-angularjs
, and our home-made modules as dependencies.
1
2
3
4
5
6
7
8
| // Create our prototype module let mod = angular.module( 'prototype' , [ 'ionic' , 'wp-api-angularjs' , modHome, modMenu, modPost ]); |
1
| export default mod = mod.name; |
Routing
Our application has a side menu <ion-side-menu ui-view="menu">
in which theMenu module will be rendered. It also has a content section <ion-nav-view name="content">
in which the Home and Post modules will appear.
The ui-view
directive is part of the UI-router that Ionic uses. It tells $state
(UI-router service) where to place your templates. Similarly, the name
directive attached to <ion-nav-view>
is a custom Ionic directive that is using ui-view
underneath. You can consider both directives identical.
Here is a simplified version of the root
state, the state that all modules share:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
export
default
function
($stateProvider) {
'ngInject'
;
return
$stateProvider.state(
'root'
, {
abstract:
true
,
views: {
'@'
: {
template: `<ion-side-menus>
<ion-side-menu-content>
<ion-nav-bar
class
=
"bar-positive"
></ion-nav-bar>
<ion-nav-view name=
"content"
></ion-nav-view>
</ion-side-menu-content>
<ion-side-menu side=
"left"
ui-view=
"menu"
></ion-side-menu>
</ion-side-menus>`
}
}
});
}
For more information about named views, please refer to the documentation on GitHub.
<ion-side-menu ui-view="menu">
in which theMenu module will be rendered. It also has a content section <ion-nav-view name="content">
in which the Home and Post modules will appear.ui-view
directive is part of the UI-router that Ionic uses. It tells $state
(UI-router service) where to place your templates. Similarly, the name
directive attached to <ion-nav-view>
is a custom Ionic directive that is using ui-view
underneath. You can consider both directives identical.root
state, the state that all modules share:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
| export default function ($stateProvider) { 'ngInject' ; return $stateProvider.state( 'root' , { abstract: true , views: { '@' : { template: `<ion-side-menus> <ion-side-menu-content> <ion-nav-bar class = "bar-positive" ></ion-nav-bar> <ion-nav-view name= "content" ></ion-nav-view> </ion-side-menu-content> <ion-side-menu side= "left" ui-view= "menu" ></ion-side-menu> </ion-side-menus>` } } }); } |
Sign up here with your email
ConversionConversion EmoticonEmoticon