Contexte

Déjà, précisons le contexte :

  • une page web tout simple, comportant en gros un peu de bla bla et une liste d'items
  • lisible
  • pas trop moche si possible
  • très facile à mettre à jour (ce qui arrivera de temps en temps)

Ok, une page html avec un peu de css posée sur un serveur fait le boulot. Mais c'était trop simple, allons bon !

Le html c'est surfait !

Déjà, le html c'est vraiment surfait. Faut réellement être un développeur de la vieille école pour écrire du PHP^W html à la main. Franchement, qui voudrait en écrire encore aujourd'hui ?

La solution (enfin l'une) se trouve donc dans haml. haml est un langage de balisage léger pour écrire des templates. C'est plutôt orienté ruby et ça se lit très facilement.

L'indentation est utilisée pour gérer l'enchainement des blocs plutôt que les balises ouvrantes/fermantes (comme en python ou coffeescript par exemple).

Si on prend l'exemple sur wikipedia voici ce que ça permet.

Version html :

<div id="sidebar">
  <ul class="main">
    <li class="active">
      <a href="accueil.html">
        Accueil
      </a>
    </li>
    <li>
      <a href="nouvelles.html">
        Nouvelles
      </a>
    </li>
    <li class="disabled">
      <a>Membres</a>
    </li>
  </ul>
</div>

Version haml :

#sidebar
  %ul.main
    %li.active
      %a{"href" => "accueil.html"}
        Accueil
    %li
      %a{"href" => "nouvelles.html"}
        Nouvelles
    %li.disabled
      %a Membres

Tout de suite, le gain est énorme ! Plus de syntaxe xml, plus lisible, indentation forcée, etc.

Ruby et rake, pour faire faussement compliqué

Le problème de tout ça c'est qu'il faut maintenant transformer ceci en ... html ! Ben oui, votre navigateur il ne comprend pas le haml.

Heureusement, Ruby vole à notre secours !

Tout d'abord, il est nécessaire d'installer la gem haml :

gem install haml

Vous pouvez donc ensuite compiler votre fichier haml (index.haml) en fichier html (index.html) :

require 'haml'
 
haml = IO.read("index.haml")
hamlengine = Haml::Engine.new(haml)
html = hamlengine.render()
 
File.open("index.html", "w") { |f| f.write(html) }

Si vous appellez ce fichier compile.rb il vous suffit d'exécuter la commande ruby compile.rb pour générer votre fichier html.

Facile, non !

Par contre, arrêtons de voir les choses en petit ! Un tel script n'est pas suffisant, il faut se dépasser un peu quand même !

Ce script va donc être placé dans un fichier Rakefile. Voici donc le contenu de ce fichier :

require 'haml'
 
task :default => :build
desc 'Build site'
task :build do
  haml = IO.read("index.haml")
  hamlengine = Haml::Engine.new(haml)
  html = hamlengine.render()
  File.open("_site/index.html", "w") { |f| f.write(html) }
end

Vous saisissez la différence ? Non ? Ben pourtant elle est évidente, il suffit désormais d'exécuter la commande rake au lieu de ruby compile.rb !

Et si on coloriait un peu ?

Maintenant que la partie html est réalisée, passons un peu à la mise en style.

Précédemment, on utilisait essentiellement du css. Tout comme le html qui est désormais surfait, le css est également aujourd'hui une technologie quasi obsolète.

Heureusement pour nous, des petits gars bien malins nous ont concoqueté Sass. Si vous avez compris ce qu'était haml par rapport à html, dites simplement qu'il en est de même à propos de Sass par rapport à css.

Sass est donc un pré-processeur css vous permettant de l'écrire plus mieux, en enlargeant votre productivité. Il y a plein de possibilités bien sympa, comme les mixins, les nested rules et plein d'autres choses.

Lorsque vous écriviez précedemment, en css :

ul {
  color: red;
}
ul li {
  margin-left: 1em;
}
ul li.green {
  color: green;
}
ul li a {
  text-decoration: underline;
}
ul li a:hover {
  font-weight: bold;
}

Vous pouvez désormais écrire en Sass :

ul
  color: red
  li
    margin-left: 1em
    &.green
      color: green
    a
      text-decoration: underline
      &:hover
        font-weight: bold

Impressionnant, non !

Evidemment, pour pouvoir tout de même générer le css correspondant (car, pour rappel, ton navigateur il ne comprend pas Sass) on va encore utiliser Ruby et la gem dédiée :

gem install sass

Voici donc un petit script pour transformer notre Sass (css/style.sass) en css (style.css) :

require 'sass'
 
sassengine = Sass::Engine.for_file("css/style.sass", :syntax => :sass, :style => :compressed)
css = sassengine.render()
File.open("style.css", "w") { |f| f.write(css) }

Mais comme on est des gens bien, on va surtout le rajouter au Rakefile précédemment créé afin qu'il ressemble à :

require 'sass'
require 'haml'
 
task :default => :build
desc 'Build site'
task :build do
  sassengine = Sass::Engine.for_file("css/style.sass", :syntax => :sass, :style => :compressed)
  css = sassengine.render()
  File.open("style.css", "w") { |f| f.write(css) }
 
  haml = IO.read("index.haml")
  hamlengine = Haml::Engine.new(haml)
  html = hamlengine.render()
  File.open("_site/index.html", "w") { |f| f.write(html) }
end

Et voilà ! Un simple appel à rake nous permet donc d'obtenir notre html et notre css !

On devait pas parler de couleurs ?

Ha si !

Puisqu'on y est, on ne vas pas utiliser la feuille de style standard, say trop pour les loosers !

Tout d'abord, histoire que tous le monde ait la même trogne, on va commencer par utiliser la feuille de reset normalize.css. C'est une bonne alternative à beaucoup de feuilles de reset qu'on trouve habituellement, et elle fait bien son boulot.

Ensuite, ben c'est simple, on va surtout utiliser les couleurs provenant de solarized. Il s'agit d'un ensemble de couleurs plutôt bien homogènes, cohérentes entre elles et agréables à l'oeil. Parfait quoi !

Histoire de mettre aussi un peu de fun dans l'histoire, ajoutons quelques icones. Mais comme on fait les choses biens, point d'image ! C'est trop surfait les images aussi ! Donc direction Font Awesome. Il s'agit d'une police de caractère orientée icones. L'avantage est que c'est plutôt léger, vectoriel, coloriable facilement, propre, bien intégré à Twitter bootstrap mais également utilisable sans. C'est propre, c'est net, c'est facile, que demander d'autre ?

Voici d'ailleurs le code Sass que j'ai utilisé pour ajouter mes quelques icones dans ma page :

$fontAwesomePath: "font/fontawesome-webfont" !default
 
@font-face
  font-family: "FontAwesome"
  src: url("#{$fontAwesomePath}.eot")
  src: url("#{$fontAwesomePath}.eot") format('eot'), url("#{$fontAwesomePath}.woff") format('woff'), url("#{$fontAwesomePath}.ttf") format('truetype'), url("#{$fontAwesomePath}.svg#FontAwesomeRegular") format('svg')
  font-weight: normal
  font-style: normal
  
[class^="icon-"]:before,
[class*=" icon-"]:before
  font-family: FontAwesome
  font-weight: normal
  font-style: normal
  display: inline-block
  text-decoration: inherit
  
.icon-check-empty:before
  content: "\f096"
  
.icon-check:before
  content: "\f046"
  
.icon-envelope-alt:before
  content: "\f0e0"
  
.icon-phone:before
  content: "\f095"
  
.icon-comments-alt:before
  content: "\f0e6"
  
.icon-comments:before
  content: "\f086"

On pousse le style un poil plus loin ?

Histoire d'aller un tout petit peut plus loin, j'ai utilisé deux autres web font pour améliorer un peu la typographie. C'est pas grand chose mais ça fait tout de suite la différence. C'est propre, léger, et agréable visuellement alors pourquoi s'en priver ?

J'ai donc utilisé Numans comme police de base et Josefin Sans pour les titres. C'est pas grand chose mais le gain est réellement intéressant.

Voici le Sass correspondant :

@import url("//fonts.googleapis.com/css?family=Josefin+Sans:700")
@import url("//fonts.googleapis.com/css?family=Numans")
  
html, body
  font-family: "Numans", arial, helvetica, sans-serif
h1, h2, h3, h4, h5, h6
  font-family: "Josefin Sans", arial, helvetica, sans-serif

Modification et mise en ligne

Ha oui, l'objectif initial était également de pouvoir être facilement modifié et mis en ligne.

Pour la publication c'est facile. J'ai simplement mis une règle deploy dans mon Rakefile qui effectue un rsync vers mon serveur web. Comme c'est du statique je n'ai rien d'autre à faire, rien a redémarré. La modification est donc instantanément en ligne.

Mon Rakefile a donc la tête suivante. Il faut tout de même prendre en compte que, pour simplifier les choses, je génère mon contenu dans un répertoire _site qui me permet de le pousser sans me soucier des fichiers sources.

require 'sass'
require 'haml'
  
task :default => :build
desc 'Build site'
task :build do
  sh 'mkdir _site'
  sh 'rm -rf _site/*'
  
  sassengine = Sass::Engine.for_file("css/application.sass", :syntax => :sass, :style => :compressed)
  css = sassengine.render()
  File.open("_site/application.css", "w") { |f| f.write(css) }
  
  haml = IO.read("index.haml")
  hamlengine = Haml::Engine.new(haml)
  html = hamlengine.render()
  File.open("_site/index.html", "w") { |f| f.write(html) }
  
  sh 'cp -R font _site'
end
  
desc 'Build and deploy'
task :deploy => :build do
  sh 'rsync --checksum -rtzh --progress --delete _site/ www:/var/www/plop'
end

Et voilà ! rake me compile mon projet, je peux aller le voir directement dans _site ou utiliser serve. rake deploy quant à lui me génère le contenu et le pousse sur mon serveur web.

Il ne manquerait pas un truc ?

Et si, il manque une dernière brique : git. En effet, tout le contenu source (donc _site omis) est versionné en utilisant git. Je n'utilise pas de serveur type github ou autre, j'ai juste créé un dépôt sur mon propre serveur de fichier. Je pousse alors via ssh, c'est très largement suffisant et je n'ai pas besoin de plus de droits, je suis le seul à bosser dessus. L'avantage est qu'un dépôt git se monte en un rien de temps et qu'une connexion classique suffit à le récupérer. Je peux alors rappatrier les sources sur une autre machine qui contient Ruby et les gem nécessaire et je peux alors le modifier, générer et pousser vers mon serveur !

Et voilà !

Et voui, et voilà !

Ok, certains diront que c'est utiliser un bulldozer pour écraser une mouche, et ils n'auront probablement pas tord. Quoi qu'il en soit, cela apporte une réelle plus value en terme de confort. Et surtout c'est une base réutilisable de nombreuses fois, extensible (il suffit par exemple de rajouter une entrée pour compiler du coffeescript et ajouter un peu de dynamisme dans les pages, etc).

Apparté

'tain mais je sais pas comment il fait, c'est mega super lourd de placer autant de liens dans un post !

Apparté n°2

Oui, l'écriture de ce billet est probablement plus longue que l'écriture de la dite page oueb en html+css !

Bonus

Vous trouverez les sources de l'exemple sur un dépôt github : web_page_today et l'exemple généré.