Applications with Mojolicious – Part One: Introduction

This is the first post of a series on the Mojolicous web framework originating from my experiences at ISP, Fachbereich Informatik of the Technische Universität Darmstadt. Step by step, we will create a simple blogging platform using Mojolicious.

This first post will motivate the use of Mojolicious and provide an introduction on how to set up a project.

Mojolicious Series

Installation

Mojolicious requires Perl ≥ 5.10 and recommends the use of at least 5.16. You might want to use a perl management tool like perlbrew, but that is out of the scope of this series and no requirement for following along.

The current installation script referred from http://mojolicio.us installs cpanminus first. The following code fetches the script to install App::cpanminus and, with it, Mojolicious:

1
curl -L https://cpanmin.us | perl - -M https://cpan.metacpan.org -n Mojolicious

If you do already have App::cpanminus (and don't want to pipe to shell from HTTP), just install it directly through cpanminus: cpanm Mojolicious.

Basic Setup

A Mojolicious application follows the same structure as a regular Perl module (with some added bonus). If you are familiar with modules, the following will be well-known to you.

Built-in Generator

Mojolicious comes with a project generator to bootstrap your project and create all necessary files. It generates a bunch of exemples that we will replace later on. It creates a trivial, but handy examplary site.

We have decided to name our app Moblo. To generate the project, run the following command:

1
mojo generate app Moblo

This will create the following directory structure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
moblo
├── lib                         # Application Library (Controller, Model)
│   ├── moblo                   # Controller Namespace
│   │   └── Example.pm          # Controller class Moblo::Example
│   └── moblo.pm                # Main Application (startup, routes)
|
├── public                      # Static files (Images, CSS, Javascript)
│   └── index.html              # Generated index file (Unnecessary in our case)
|
├── script
│   └── moblo                   # Application command-line script
|
├── t                           # Test directory
│   └── basic.t                 # Generated test for the example action
|
└── templates                   # Template/Views
    ├── example                 # Templates for Moblo::Example controller
    │   └── welcome.html.ep     # Template block for action 'welcome'
    |
    └── layouts                 # View skeletons (e..g, surrounding head/footer)
        └── default.html.ep     # Default skeleton

Let's have a look at the generated examples. Open the main application module lib/moblo.pm. Within the startup method, one line does the wiring of the whole example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package Moblo;
use Mojo::Base 'Mojolicious';

sub startup {
  my $self = shift;

  # .. snip ..

  # Router
  my $r = $self->routes;

  # Normal route to controller
  $r->get('/')->to('example#welcome');
}

1;

my $r = $self->routes is the main router object. Use it to match URLs to controllers and actions. The line $r->get('/')->to('example#welcome') creates a route for HTTP GET requests from the URL root to the method Moblo::Example::welcome. This is the short variant of the route definition, and could also be written as:

1
$r->route('/')->via('GET')->to(controller => 'Example', action => 'welcome')

In the course of this series, we will cover most of the options the routes have to offer. Still, due to the breadth of route conditions and shortcuts, I strongly recommend reading the routing guide from Mojolicious for full coverage of the routing mechanisms.


Now, what happens in the controller that the route targets? The example action welcome renders the default template for that controller with an additional stash variable set:

1
$self->render(msg => 'Welcome to the Mojolicious real-time web framework!');

But, what is the stash? It is the concept of passing data around in the framework before the request is rendered. Templates can use the data directly. We will cover it in great detail in a later tutorial.

Now, for the last part of the request, a quick look at the template file templates/example/welcome.html.ep:

1
2
3
4
5
6
7
% layout 'default';
% title 'Welcome';
<h2></h2>
This page was generated from the template "templates/example/welcome.html.ep"
and the layout "templates/layouts/default.html.ep",
<a href="<%== url_for %>">click here</a> to reload the page or
<a href="/index.html">here</a> to move forward to a static page.

The first line sets the layout to 'default', which resides under templates/layouts/default.html.ep and uses a special helper method to set the page title within that layout. The rest of the template contains the content, which is rendered within the default layout. The rendered layout is returned from the controller, which completes the GET '/' request.

Running the App

To run the app during development, you can use the morbo development server to start your app as follows:

1
2
$ morbo script/moblo
Server available at http://127.0.0.1:3000.

You can then quickly check your routes and templates, as the server will auto-reload on every change. It uses the development mode of Mojolicious which, upon errors, will display the affected code plus a whole page of additional information. Obviously, this is rather inappropriate for production use. For scalable deployments, Mojolicous provides several options ranging from Proxy behind Apache/Nginx or own preforking servers. We will look into several of these options in a later post.

Code at GitHub

While the code for this first post is not that interesting (it does not differ from the generated version), I am publishing the code for each post in this github repository.

Further Documentation

This completes the overview of the Mojolicious framework. You should have gained a basic understanding of the framework file structure and a glimpse of the different mechanisism it employs. Surely this brief introduction does not even scratch the surface of what Mojolicious is capable of. Thus, stay tuned for the next part of this series, where we will dig deeper into the routing.

Mojolicious provides excellent documentation through perldoc, which they also provide online at http://mojolicio.us/perldoc. I recommend reading through at least the Rendering and Routing guides before you do your own experimenting, as there are many simple tricks to tackle problems.

This concludes the introduction to Mojolicious. In the second part, we start creating our own routes and templates.