Mojolicious

Luc Didry

13 juin 2014

Le développement web peut redevenir fun !
Le développement web peut redevenir fun !

De quoi parlons-nous ?

D'un framework Web
D'un framework Web

De quoi ne parlons-nous pas ?

De la création d'une appli avec Mojolicious.

C'est plutôt le sujet de la conférence suivante, sur Lutim.

On se concentrera ici sur certains aspects qui font la force de Mojolicious.

Quelques infos

Créé par Sebastian Riedel
Créé par Sebastian Riedel
(également créateur de Catalyst)

Mojolicious n'a pas de dépendances !

(il a cependant des dépendances optionnelles : EV, IO::Socket::IP, IO::Socket::SSL)

C'est aussi un micro-framework.

(bien utile pour un prototypage rapide)

Il fournit un client et un serveur !

(on verra le détail plus loin)

Il est à la pointe de la technologie :

Ligne de commande

Mojolicious fournit mojo, un script qui permet de :

  • créer une application Mojolicious ;
  • créer un plugin Mojolicious ;
  • aller chercher des pages web ;
  • envoyer votre application sur le CPAN ;

À vrai dire… mojo est une application Mojolicious tout comme les applis qu'on crée !

Donc certaines commandes seront obligatoirement à exécuter avec votre application.

Mais toutes sont valides avec votre application.

Voyons voir un peu tout ça

Les commandes mojo

mojo generate <app|lite_app|makefile|plugin>

 

C'est le point de départ pour bosser avec Mojolicious

Cela crée la structure de votre application selon des templates fournis avec Mojolicious

$ mojo generate app Test
$ tree test
test
├── lib
│   ├── Test
│   │   └── Example.pm
│   └── Test.pm
├── log
├── public
│   └── index.html
├── script
│   └── test
├── t
│   └── basic.t
└── templates
├── example
│   └── welcome.html.ep
└── layouts
└── default.html.ep
mojo cpanify -u sri -p secr3t \
Mojolicious-Plugin-MyPlugin-0.01.tar.gz

 

Envoie un tarball sur le CPAN.

Les commandes de votre application

./myapp.pl get [OPTIONS] URL [SELECTOR|JSON-POINTER] [COMMANDS]

Avec ./myapp.pl get / par exemple, on peut tester son appli sans la lancer ✌

Mais on peut aussi s'amuser avec des pages distantes

mojo get https://lut.im .hennypenny text

nous donne

Let's Upload That Image!
./myapp.pl inflate

Extrait les fichiers embarqués d'une application Mojolicious::Lite

$ mojo generate lite_app test
$ tree
.
└── test
$ ./test inflate
$ tree
.
├── templates
│   ├── index.html.ep
│   └── layouts
│       └── default.html.ep
└── test
./myapp.pl <daemon|prefork> [OPTIONS]

Lance l'application avec un serveur HTTP et WebSocket

(simple thread ou préforké)

./myapp.pl routes

Affiche les routes disponibles dans votre application

/perldoc/:module  *    perldocmodule
/                 GET
./myapp.pl test

Lance les tests de votre application

Les serveurs de Mojolicious

Mojolicious fournit deux serveurs :

  • un serveur de développement, morbo ;
  • un serveur de production, hypnotoad.

Morbo

  • utilise le mode development ;
  • surveille le script de l'appli, les dossiers des templates et des bibliothèques ;
  • recharge l'appli s'il y a un changement.
morbo myapp.pl

Codez, rechargez votre navigateur, c'est prêt !

Il n'est par contre pas fait pour la production.

Au passage : les pages d'erreur en mode development sont très bien faites et fort utiles.

Le message d'erreur et les dernières lignes de log sont présentées fort à propos.

Hypnotoad

  • utilise le mode production ;
  • basiquement, c'est comme ./myapp.pl prefork, mais optimisé pour la production ;
  • permet des mises à jour de l'appli sans arrêt de service.
hypnotoad myapp.pl

Plus qu'à placer un reverse-proxy devant et votre appli est en production ☺

Mise à jour zéro downtime

$ hypnotoad test
$ vim test
$ hypnotoad test
Starting hot deployment for Hypnotoad server 7052.

La configuration d'hypnotoad peut être incluse dans la configuration de l'appli si on utilise les plugins Mojolicious::Plugin::Config ou Mojolicious::Plugin::JSONConfig.

C'est pas du serveur, mais ça peut servir au déploiement

On peut utiliser Mojolicious en CGI

ScriptAlias / /home/sri/myapp/script/myapp/

On peut utiliser Mojolicious en PSGI

$ plackup ./myapp.pl
HTTP::Server::PSGI: Accepting connections at http://0:5000/

Tiens, pourquoi pas un myapp.fcgi ?

#!/usr/bin/env plackup -s FCGI
use Plack::Builder;

builder {
  enable 'Deflater';
  require 'myapp.pl';
};

Test Driven Development

Mojolicious permet de tester simplement et rapidement son application !

Lors de la création d'une application, un répertoire t est créé, ainsi qu'un exemple de test.

use Test::More;
use Test::Mojo;

use FindBin;
  require "$FindBin::Bin/../myapp.pl";

my $t = Test::Mojo->new;
  $t->get_ok('/')->status_is(200);

done_testing();

On lance alors les tests avec ./myapp.pl test

Énormément de tests sont possibles grâce à Test::Mojo.

$t = $t->content_is('working!');

En regex ce coup-ci :

$t = $t->content_like(qr/working!/);

On peut utiliser des selecteurs CSS grâce à Mojo::DOM :

$t = $t->element_exists('div.foo[x=y]');

On peut aussi tester les réponses en JSON (merci Mojo::JSON)

$t = $t->json_is({foo => [1, 2, 3]});

Ça marche aussi pour les WebSockets 😊

$t = $t->message_is('working!');

Il y a aussi les différents types de requête HTTP, bien sûr, et les tests se chaînent sans problème :

$t->post_ok('/hello.json' => json => {hello => 'world'})
  ->status_is(200)
  ->json_is({bye => 'world'});

Créer un élément non-bloquant

#!/usr/bin/env perl
use Mojo::UserAgent;
use Mojo::IOLoop;
use 5.10.0;

my $delay = Mojo::IOLoop->delay(sub {
  my ($delay, @titles) = @_;
  say "**************";
  say for @titles;
});

my $ua = Mojo::UserAgent->new;
for my $url ('https://lut.im', 'mojolicio.us', 'www.cpan.org') {
  my $end = $delay->begin(0);
  $ua->get($url => sub {
    my ($ua, $tx) = @_;
    say $tx->res->dom->at('title')->text;
    $end->($tx->res->dom->at('title')->text);
  });
}
$delay->wait;
$ ./test
Mojolicious - Perl real-time web framework
Lutim
The Comprehensive Perl Archive Network - www.cpan.org
**************
Lutim
Mojolicious - Perl real-time web framework
The Comprehensive Perl Archive Network - www.cpan.org

On voit bien que les réponses ne sont pas arrivées en même temps mais que le résultat est dans le bon ordre.

Les trois requêtes ont été exécutées parralèlement, accélérant grandement le temps de réponse.

Pour plus de détails sur les éléments non-bloquants de Mojolicious, voir les billets de Joel Berger sur http://blogs.perl.org

Plugins Mojolicious

Un certain nombre de plugins sont inclus de base dans Mojolicious.

Voici mes préférés :

  • Mojolicious::Plugin::Config
  • Mojolicious::Plugin::DefaultHelpers
  • Mojolicious::Plugin::TagHelpers
  • Mojolicious::Plugin::PODRenderer

L'écosystème des plugins de Mojolicious est très appréciable !

Questions ?

http://mojolicio.us

Mojolicious::Guide::Cookbook

http://github.com/ldidry
http://twitter.com/framasky
http://slides.fiat-tux.fr