Hamster time tracker – le verdict

Bonjour,

J’avais besoin d’un time tracker, et je disais qu’il serait difficile de trouver aussi bien que timedoctor.

Et bien, c’est vrai. Mais j’aime l’open source et je veux trouver un équivalent libre (et accessoirement gratuit).

Dans ma quête j’ai pris celui qui me semblait le moins pire : Hamster time tracker.

Ce n’est pas un tracker automatique qui donne touts les application ouvertes et utilisées au cours de la journée. On assigne une tâche sous la forme tache@categorie et on arrête quand on ne travaille plus sur la tâche.

Cette application n’est pas faite pour un travail de groupe. C’est uniquement pour qu’un individu sâche ce qu’il fait. Son aspect manuel est un peu frustrant mais on s’y fait. De plus, on peut corriger les temps. C’est à dire changer le début et la fin de chaque tâche qui se sont écoulées.

Il a un petit défaut de granularité. Il calcul à la minute près. C’est suffisant mais si on commence une tâche et qu’elle prend moins d’une minute, il l’efface au lieu de lui assigner une minute.

Il peut fournir un résumé quotidien ou hebdomadaire des taches effectuées. Il manque donc un résultat mensuel et annuel. Les heures sont au format heures décimales, c’est à dire que 1h30 est affiché 1.5h, ce qui est un peu frustrant.

Comme tout outil, quand on apprend à l’utiliser, on apprend aussi à ne pas lui demander ce qu’il ne sait pas faire. Je trace donc uniquement le début et la fin du travail pour les clients.

Autre défaut qui gène mais pas au point d’être blocant, l’icone de la barre de navigation ne réagit pas comme touts les autres. Quand la fenêtre principale est réduite, un clic sur l’icône et elle apparaît. Jusqu’ici tout est normal. Là où c’est agaçant, c’est qu’un nouveau clic ne la réduit pas, on doit donc la fermer par le bouton de fermeture de la fenêtre. Quand la fenêtre est cachée, un clic sur l’icône ne la ramène pas au premier plan.

En conclusion, c’est un programme qui est largement perfectible mais que je vais conserver car il répond a mes besoins.

Sanitiser une chaine en javascript

Bonjour,

Je veux aujourd’hui partager une soluton simple à un problème qui se posait à moi assez souvent.

Comment afficher une chaine en javascript dans un élément html ?

C’est simple, vous me direz :

<div id="cible">
</div>
<script>
   String maChaine='Salut tout le monde !';
   cible = document.getElementById('cible');
   cible.innerHTML = maChaine;
</script>

Ca marche dans certains cas, mais si j’ai :

<div id="cible">
</div>
<script>
   String maChaine='Salut <i>tout</i> le monde !';
   cible = document.getElementById('cible');
   cible.innerHTML = maChaine;
</script>

On a :

« Salut tout le monde ! »

Et ce n’est pas une fonctionnalité trop cool.

J’aimerais avoir :

« Salut <i>tout</i> le monde ! »

Et oui, il faut échapper la chaine pour afficher toute la chaine sans rien interpréter. C’est ce que les « vrais » veulent.

Les vrais quoi ? Les vrais programmeurs, les pros quoi ! Adhérez à cette idée si vous ne voulez pas passer pour un amateur.

Alors, comment on fait ?

On peut installer une librairie qui fait ça, et on va ajouter du bloat à une application qui n’en a vraiement pas besoin.

On peut aussi le faire tout seul, ça prend 5min et ça durera pour toujours, ou jusqu’à ce que javascript propose un équivalent.

On va ajouter une méthode à String qu’on appellera toText()

String.prototype.toText = function (){return this.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;').replace('"', '&quot;');}

On utilisera toText() à chaque fois qu’on veut écrire notre chaine.

cible.innerHTML = maChaine.toText();

Le tour est joué.

J’ai échappé le strict minimum, soit 4 caractères. Libre à chacun d’en ajouter.

Timeout lors de la publication

Bonjour,

J’ai un petit souci depuis toujours sur wordpress chez free.

Lorsque je publie, il arrive très souvent (environ une fois sur deux) que la page bloque.

Ce n’est pas plus grave que ça car l’article est quand même publié. Le blocage arrive donc lors de la redirection vers la page de confirmation.

Le message d’erreur est le suivant : Network Error (tcp_error)

 

Je n’ai pas cherché de solution car ce n’est pas trop grave.

Je serais quand même intéressé par toute suggestion.

Mettre en place https

Bonjour,

Aujourd’hui j’ai du mettre en place https.

La méthode qui fût demandée est via Let’s encrypt. L’avantage c’est le prix : gratuit. L’inconvénient c’est qu’il faut renouveler la clé régulièrement (tous les 90 jours, il me semble) et ne peut pas l’utiliser pour tous les services.

J’ai essayé avec une ip dynamique et ça marche très bien.

On télécharge certbot et on le lance en tant que root.

On met en place
/etc/apache2/sites-available/mon-site.conf

On alias vers
/etc/apache2/sites-enabled/mon-site.conf

Et le tour est joué.

Cloacking

Bonjour,

Aujourd’hui j’ai appris que je faisais depuis longtemps sans le savoir du cloaking. J’ai l’impression d’être M. JOURDAIN découvrant la prose.

Alors c’est quoi le cloacking ?

Le cloacking c’est le fait de séparer les visiteurs et de donner une version différente de son site.

Avec cette définition, on a l’impression qu’un portail ou une interface d’admin c’est du cloacking. Pourtant, non. Dans ce cas, le visiteur sait ce qu’il y a, et il sait que le contenu change en fonction de certains privilèges.

La différence est donc, pour moi, le fait que le site donne des informations différentes à l’insu de certains visiteurs (des fois même à l’insu de tous les visiteurs).

Bien, je sais ce qu’est le cloacking, mais à quoi ça sert ?

Je vais d’abord expliquer le besoin qui m’a conduit à utiliser cette technique avant qu’elle ai eu un nom. Puis je vais donner des exemples d’autres applications.

Il y a longtemps (vers 2004), je maintenais un site qui était un « gros poisson ». Et comme tout site connu, c’était la cible régulière de pirates en tous genres.

Parmis eux, il y a ceux qui veulent tester leur savoir-faire sur un « vrai » site, et il y a ceux qui veulent avoir l’information sans payer. Il y a d’autres profiles comme les concurrents qui « aimeraient » que le site ait des difficultés, etc.

C’était ma première confrontation à des êtres malveillants envers un site que je maintenais. Et, ce que les pirates en face ne savaient pas, c’est qu’il y a des gens « en face » qui testent leurs connaissances sur la sécurité informatique sur des « vrais » pirates.

J’ai étudié des logs, stéganographié (tiens, un autre sujet intéressant d’article) des documents, traqué pendant deux ans quelqu’un qui a appris beaucoup en ignorant que j’en apprenais plus dans le même temps (sur lui et sur les techniques de plus en plus élaborées pour trouver les failles).

Le cloacking était donc un outil parmis d’autres pour arriver à mes fins. Lorsqu’un bot était détecté, je donnais une page malformée. Ainsi les attaques avec les outils de pentest devenaient inutiles. Lorsque une attaque était détectée mais pas le bot (attaque manuelle directement sur navigateur), je donne une page qui ressemble à celle du site, sans accès aux données et je log tout ce qui transite. Enfin, si aucune attaque, le site se comporte normalement.

J’ai donc 3 sites différents suivant le visiteur. Et, bien sur, les critères évoluent avec le temps pour corriger tout faux-positif, quelle que soit la catégorie.

Une utilisation récente que j’ai eu (d’où l’idée de cet article) est de donner un site complètement différent, pas une admin automatique, un autre site, si on y accède depuis une adresse spécifique.

On peut noter les utilisations pour le référencement. On donne une version spéciale pour google et bing. C’est une utilisation que je ne cautionne pas, mais qui a ses adeptes.

Je vais en rester là sur ce sujet passionnant.

Mettre un site en maintenance

Bonjour,

Lorsqu’on gère un site, il faut savoir rester professionnel.

Un peu de bla bla

Il y a beaucoup de façons de faire « amateur », et une de celles-ci est de laisser une page blanche, ou une page d’erreur quand le site est cassé.

Mettre une page « site en maintenance » montre que l’on fait attention à notre site et par conséquent à ceux qui le voient.

Bien sûr, on ne peut pas toujours prévoir les pannes, mais une action rapide est de rigueur. Ce qui serait mieux c’est une action pro-active. On met d’abord la page « en maintenance », puis on travail à l’aise.

Si on sait que la base de données ne sera pas disponible, une page « revenez dans une heure » est beaucoup mieux qu’une page avec des warnings « database not found » sur chaque texte dynamique.

Un peu de pratique

Maintenant c’est bien de paraître pro, mais on fait comment ?

Une option serait d’installer un plug-in qui affiche la page désirée aux heures prévues. Mais cela suppose que l’on soit sur un cms ou framework qui donne ce genre d’extension.

Pour ma part, je fais beaucoup plus basique : je mets une page _index.html à la racine du site (à côté de la page index.php).

Notez bien l’extention, .html. C’est important pour nous faciliter la vie plus tard.

Les sites ont généralement et par défaut une précédence de index.html sur index.php. C’est important aussi.

La page _index.html doit être la plus simple possible, sobre sans image. Ce ne sont que des suggestions, rien d’obligatoire ici. Par contre interdit d’avoir du contenu dynamique.

Maintenant que tout est en place, on renomme la page _index.html en index.html et le site n’est plus visible pour les nouveaux visiteurs.

Il reste les « pas nouveaux » visiteurs qui ont des chemins en cache dans leur navigateur ou des signets directement sur cetaines pages.

Pour tout ce beau monde, on fait un .htaccess (que l’on nommera .htaccess_ quand on n’est pas en maintenance) qui donnera index.html à tout le monde avec un code erreur 302 pour satisfaire les robots.

Garder ces fichiers a portée permet de changer le nom des fichiers sans faire de transfert et d’éviter d’avoir des accidents.

Drag and drop en html et javascript

Bonjour,

Aujourd’hui j’ai du implémenter un outil pour réorganiser une arborescence.

Il y a donc une imbrication de <ul> (et les <li> qui vont avec) et l’utilisateur pourra bouger n’importe quelle partie de l’arborescence.

Mise en place basique

Voici un exemple d’arborescence en html :

<!DOCTYPE html>
<html>
    <head>
        <title>Drag and drop</title>
    </head>
    <body>
        <ul>
            <li>Element 1</li>
            <li>Element 2</li>
            <li>Element 3
                <ul>
                    <li>Element 4</li>
                </ul>
            </li>
        </ul>
    </body>
</html>

Il faut rendre les <li> draggable avec l’attribut draggable= »true »

Ensuite faire une balise <script>, de préférence en fin de page, avant </body>.

On y mettra les fonctions pour le drag and drop (drag pour ondragstart et drop pour ondrop)

function drag(ev) {
}
function drop(ev) {
    ev.preventDefault();
}
function dragOver(ev) {
    ev.preventDefault();
}

Ceci ne suffit pas, il faut affecter ces fonctions aux évènements des éléments concernés. Mais on va faire ça bien, c’est à dire dans une fonction init qui se lancera dès que le dom est prêt.

function init() {
    // attache drop
    elements = document.querySelectorAll('li');
    for (i = 0 ; i < elements.length ; i++) {
        elements[i].addEventListener('drop', drop);
        elements[i].addEventListener('dragover', dragOver);
    }
    // attache drag
    elements = document.querySelectorAll('li[draggable]');
    for (i = 0 ; i < elements.length ; i++) {
        elements[i].addEventListener('dragstart', drag);
    }
}
document.addEventListener('DOMContentLoaded', init);

J’attache drop avant drag pour du chipotage, je donnerais la réponse en commentaire si ça intéresse quelqu’un. En plus, j’attache drag seulement aux éléments draggable et drop à tous les li, juste pour montrer que c’est pas forcément en double sens.

On y est presque, il faut maintenant détacher l’élément source et l’attacher dans l’élément cible. Pour cela, il faut générer un id dans les éléments draggable si ils en ont pas déjà un.

// attache drag
elements = document.querySelectorAll('li[draggable]');
for (i = 0 ; i < elements.length ; i++) {
    id = elements[i].getAttribute('id');
    if (id == null || id == '') {
        elements[i].setAttribute('id', 'draggable'+i);
    }
    elements[i].addEventListener('dragstart', drag);
}

Maintenant que tout est en place, on peut donner les actions de déplacement dans le dom.

function drag(ev) {
    element = ev.target;
    ev.dataTransfer.setData('text', element.getAttribute('id'));
}
function drop(ev) {
    ev.preventDefault();
    data = ev.dataTransfer.getData('text');
    element = document.getElementById(data);
}

Ca marche mais une fois ou deux, ce code, il y a plein de bogue !

Amélioration et hierarchie

On va voir ce qui se passe et corriger. On met directement un <li> dans un autre <li>, il faudrait construire un <ul> et mettre notre <li> dedans, comme ça on aura corrigé le problème et on peut avoir une hiérarchie.

function drop(ev) {
    ev.preventDefault();
    data = ev.dataTransfer.getData('text');
    element = document.createElement('ul');
        element2 = document.getElementById(data);
        parent = element2.parentElement;
        element.appendChild(element2);
    ev.target.appendChild(element);
}

Ca marche bien maintenant. Mais quand je lâche un élément sur lui même, il disparaît.

Empêcher la source d’être la cible

Ce petit problème est en fait la raison d’être de cet article.

Je vais d’abord exposer la méthode qui m’est naturellement venue à l’esprit :

Dans drag, on annule les évènements drop pour l’élément choisi. Puis dans drop, on remet les évènements pour tout le monde.

function drag(ev) {
    element = ev.target;
    ev.dataTransfer.setData('text', element.getAttribute('id'));
    // annule drop pour la cible et ses enfants
    element = ev.target;
    elements = element.querySelectorAll('li');
    element.removeEventListener('drop', drop);
    element.removeEventListener('dragover', dragover);
    for (i = 0 ; i < elements.length ; i++) {
        elements[i].removeEventListener('drop', drop);
        elements[i].removeEventListener('dragover', dragover);
    }
}
function drop(ev) {
    ev.preventDefault();
    data = ev.dataTransfer.getData('text');
    element = document.createElement('ul');
    element2 = document.getElementById(data);
    // remet drop pour la cible et ses enfants
    elements = element2.querySelectorAll('li');
    element2.addEventListener('drop', drop);
    element2.addEventListener('dragover', dragover);
    for (i = 0 ; i < elements.length ; i++) {
        elements[i].addEventListener('drop', drop);
        elements[i].addEventListener('dragover', dragover);
    }
    parent = element2.parentElement;
    element.appendChild(element2);
    ev.target.appendChild(element);
}

Ca marche quand on se trompe pas, mais des fois on drop là ou ça ne lance pas drop.

Il faut donc tout faire dans drag. Dès qu’on drag (ouais, je vais me passer de faire une blague ici), on reset les drop (on met les drop à tout le monde) et on empêche l’élément et ses descendants de drop.

function drag(ev) {
    element = ev.target;
    ev.dataTransfer.setData('text', element.getAttribute('id'));
    // remet drop pour tout le monde
    elements = document.querySelectorAll('li');
    for (i = 0 ; i < elements.length ; i++) {
        elements[i].addEventListener('drop', drop);
        elements[i].addEventListener('dragover', dragover);
    }
    // annule drop pour la cible et ses enfants
    element = ev.target;
    elements = element.querySelectorAll('li');
    element.removeEventListener('drop', drop);
    element.removeEventListener('dragover', dragover);
    for (i = 0 ; i < elements.length ; i++) {
        elements[i].removeEventListener('drop', drop);
        elements[i].removeEventListener('dragover', dragover);
    }
}
function drop(ev) {
    ev.preventDefault();
    data = ev.dataTransfer.getData('text');
    element = document.createElement('ul');
    element2 = document.getElementById(data);
    parent = element2.parentElement;
    element.appendChild(element2);
    ev.target.appendChild(element);
}

C’est déjà mieux, mais quand on joue trop longtemps, il y a des fois où on peut faire un drag and drop sur l’élément ou son descendant, et ça fait planter.

J’ai essayé de me dépatouiller avec les events, mais en vain. J’ai donc décidé de mettre un drapeau sur les éléments qui ne doivent pas accepter le drop.

function drag(ev) {
    element = ev.target;
    ev.dataTransfer.setData('text', element.getAttribute('id'));
    // remet drop pour tout le monde
    elements = document.querySelectorAll('li');
    for (i = 0 ; i < elements.length ; i++) {
        elements[i].removeAttribute('data-notarget');
    }
    // annule drop pour la cible et ses enfants
    element = ev.target;
    elements = element.querySelectorAll('li');
    element.setAttribute('data-notarget', 'true');
    for (i = 0 ; i < elements.length ; i++) {
        elements[i].setAttribute('data-notarget', 'true');
    }
}
function drop(ev) {
    isTarget = ev.target.getAttribute('data-notarget');
    if (isTarget == null || isTarget == '') {
        ev.preventDefault();
        data = ev.dataTransfer.getData('text');
        element = document.createElement('ul');
        element2 = document.getElementById(data);
        parent = element2.parentElement;
        element.appendChild(element2);
        ev.target.appendChild(element);
    }
}
function dragover(ev) {
    isTarget = ev.target.getAttribute('data-notarget');
    if (isTarget == null || isTarget == '') {
        ev.preventDefault();
    }
}

On a une solution plus robuste, mais il y a quand même quelque plantages.

Après une multitude de tests, j’ai réussit à trouver la cause : l’élément <ul> est aussi droppable et execute drop quand on vise bien dessus (sur la puce par exemple).

Je considère que c’est un bug et pas une feature, car si j’aurais voulu que <ul> soit droppable, je lui aurais affecté manuellement cet évènement.

Donc, il faut inhiber le drop sur <ul>

function drop(ev) {
    isTarget = ev.target.getAttribute('data-notarget');
    if (isTarget == null || isTarget == '') {
        ev.preventDefault();
        data = ev.dataTransfer.getData('text');
        element = document.createElement('ul');
        element.setAttribute('data-notarget', 'true');
        element2 = document.getElementById(data);
        parent = element2.parentElement;
        element.appendChild(element2);
        ev.target.appendChild(element);
    }
}
function init() {
    // exclusion de ul
    elements = document.querySelectorAll('ul');
    for (i = 0 ; i < elements.length ; i++) {
        elements[i].setAttribute('data-notarget', 'true');
    }
    // attache drop
    elements = document.querySelectorAll('li');
    for (i = 0 ; i < elements.length ; i++) {
        elements[i].addEventListener('drop', drop);
        elements[i].addEventListener('dragover', dragover);
    }
    // attache drag
    elements = document.querySelectorAll('li[draggable]');
    for (i = 0 ; i < elements.length ; i++) {
        id = elements[i].getAttribute('id');
        if (id == null || id == '') {
            elements[i].setAttribute('id', 'draggable'+i);
        }
        elements[i].addEventListener('dragstart', drag);
    }
}

Maintenant, c’est du code robuste, qui ne plante plus. Mais si je change <ul> par <ol> de partout, j’ai que des 1 qui se suivent. Pourquoi ?

C’est parcequ’on ne se pose pas la question de savoir si il existe un <ul> (ou <ol> quand on a fait le changement). On fabrique <ul>, on remplit, puis on ajoute au dom. On ne vérifie pas non plus si le <ul> qu’on laisse derrière est vide. Il faut donc nettoyer tout ça.

Nettoyage du dom et amélioration de la hiérarchie

En plus du nettoyage, j’ai un petit souci avec la hierarchie. Les éléments ne peuvent pas passer en premier ordre. La solution que j’ai trouvé, c’est de faire un <ul> qui permettra de déposer n’importe quel élément, mais qui n’est pas draggable.

Pour le nettoyage du dom, tout est dit un peu plus haut.

<ol>
    <li>D&eacute;poser ici les &eacute;l&eacute;ments de plus haut niveau
        <ol>
            <li draggable="true">Element 1</li>
            <li draggable="true">Element 2</li>
            <li draggable="true">Element 3
                <ol>
                    <li draggable="true">Element 4</li>
                </ol>
            </li>
        </ol>
    </li>
</ol>
function drop(ev) {
    isTarget = ev.target.getAttribute('data-notarget');
    if (isTarget == null || isTarget == '') {
        ev.preventDefault();
        data = ev.dataTransfer.getData('text');
        elements = ev.target.getElementsByTagName('ol');
        element = null;
        if (elements.length != 0) {
            element = elements[0];
        } else {
            element = document.createElement('ol');
            element.setAttribute('data-notarget', 'true');
        }
        element2 = document.getElementById(data);
        parent = element2.parentElement;
        element.appendChild(element2);
        ev.target.appendChild(element);
        if (parent.children.length == 0) {
            parent.remove();
        }
    }
}

Voilà, on a un drag and drop qui est fonctionnel et qui est propre.

Peaufinage

Comment on peut faire un effet d’inversion vidéo sur les éléments droppables ?

C’est facile, il suffit de savoir qu’il y a un évènement supplémentaire qui est dragleave (et pas dragout ça aurait été trop simple).

Je ne vais pas donner d’exemple qui fonctionne de partout car il faut gérer les bug de firefox sur dragleave qui donne pas le <li> mais le texte dedans alors que dragover marche bien !

<!DOCTYPE html>
<html>
 <head>
 <title>Drag and drop</title>
 </head>
 <body>
 <ol>
 <li>D&eacute;poser ici les &eacute;l&eacute;ments de plus haut niveau
 <ol>
 <li draggable="true">Element 1</li>
 <li draggable="true">Element 2</li>
 <li draggable="true">Element 3
 <ol>
 <li draggable="true">Element 4</li>
 </ol>
 </li>
 </ol>
 </li>
 </ol>
 <script>
 function drag(ev) {
 element = ev.target;
 ev.dataTransfer.setData('text', element.getAttribute('id'));
 // remet drop pour tout le monde
 elements = document.querySelectorAll('li');
 for (i = 0 ; i < elements.length ; i++) {
 elements[i].removeAttribute('data-notarget');
 }
 // annule drop pour la cible et ses enfants
 element = ev.target;
 elements = element.querySelectorAll('li');
 element.setAttribute('data-notarget', 'true');
 for (i = 0 ; i < elements.length ; i++) {
 elements[i].setAttribute('data-notarget', 'true');
 }
 ev.stopPropagation();
 }
 function drop(ev) {
 target = ev.target;
 isTarget = target.getAttribute('data-notarget');
 if (isTarget == null || isTarget == '') {
 ev.preventDefault();
 ev.target.style.backgroundColor = '#fff';
 data = ev.dataTransfer.getData('text');
 elements = ev.target.getElementsByTagName('ol');
 element.setAttribute('data-notarget', 'true');
 element = null;
 if (elements.length != 0) {
 element = elements[0];
 } else {
 element = document.createElement('ol');
 }
 element2 = document.getElementById(data);
 parent = element2.parentElement;
 element.appendChild(element2);
 ev.target.appendChild(element);
 if (parent.children.length == 0) {
 parent.remove();
 }
 }
 ev.stopPropagation();
 }
 function dragover(ev) {
 target = ev.target;
 isTarget = target.getAttribute('data-notarget');
 if (isTarget == null || isTarget == '') {
 ev.preventDefault();
 ev.target.style.backgroundColor = '#fcc';
 }
 ev.stopPropagation();
 }
 function dragleave(ev) {
 target = ev.target;
 isTarget = target.getAttribute('data-notarget');
 if (isTarget == null || isTarget == '') {
 ev.preventDefault();
 ev.target.style.backgroundColor = '#fff';
 }
 ev.stopPropagation();
 }
 function init() {
 // exclusion de ol
 elements = document.querySelectorAll('ol');
 for (i = 0 ; i < elements.length ; i++) {
 elements[i].setAttribute('data-notarget', 'true');
 }
 // drop related events
 elements = document.querySelectorAll('li');
 for (i = 0 ; i < elements.length ; i++) {
 elements[i].addEventListener('drop', drop);
 elements[i].addEventListener('dragover', dragover);
 elements[i].addEventListener('dragleave', dragleave);
 }
 // drag related events
 elements = document.querySelectorAll('li[draggable]');
 for (i = 0 ; i < elements.length ; i++) {
 id = elements[i].getAttribute('id');
 if (id == null || id == '') {
 elements[i].setAttribute('id', 'draggable'+i);
 }
 elements[i].addEventListener('dragstart', drag);
 }
 }
 document.addEventListener('DOMContentLoaded', init);
 </script>
 </body>
</html>

Ce drag and drop marche bien sur chrome, mais pas sur firefox 45.1.1 a cause de dragleave. Vu que c’est clairement un bug, je ne vais pas investiguer.

WP fastest cache, le verdict

Bonjour,

WordPress n’est pas un foudre de guerre, tout le monde le sait. Comment remédier à sa lenteur ?

Ma solution est d’installer une extension qui gérera un cache.

J’ai déjà testé 2 d’entre elles : W3 total cache et WP fastest cache.

J’ai été déçu par W3 total cache et c’est pour ça que je l’ai remplacé par WP fastest cache.

Après quelques jours d’utilisation, je dirais que l’accélération est aléatoire.

Des fois c’est rapide et d’autres fois c’est lent. Quand c’est lent, j’ai pas l’impression que ce soit plus lent que wordpress sans cache. Donc, rien de perceptible dans le pire des cas.

Je vais donc garder ce gestionnaire de cache pour mon blog.

Scheduled post trigger, le verdict

Bonjour,

Il y a quelques temps, j’ai installé scheduled post trigger pour palier à un bug de wordpress.

Aujourd’hui, je vais donner mon verdict sur l’utilisation de cette extension.

Je vais directement parler du résultat : le travail est fait, mais je ne sais pas quand.

En effet, des fois, je regarde le blog bien après l’heure prévue et l’article n’est pas publié. Puis en revenant dessus, c’est en place. Mais vu que je me connecte sur le back-end en parallèle, je ne sais pas ce qui lance le test des articles en retard sur leur publication.

Je pourrais faire des tests plus poussés pour savoir comment ça marche. Peut-être faire mieux : regarder le code source pour être sûr de ce qui est fait. Ce n’est pas ma priorité pour le moment, je vais donc mettre un point final à cette histoire d’articles en retard.

Comme d’habitude, j’ai une petite victoire ici et je vais m’en tenir à ceci.

nginx et apache

Bonjour,

J’ai du faire une installation qui est de plus en plus répendue sur les serveurs.

Installer nginx et apache sur le même serveur. Apache est en back-end et nginx comme serveur front.

Je vais d’abord donner l’avis de ceux qui mettent en place cette architecture :

Nginx est un serveur rapide, donc on l’utilise. Ensuite, on s’apperçoit que tout ne marche pas (attention, j’ai pas dit que rien ne marchait !). Parmis ce qui ne marche pas, il y a php et l’url rewriting. Pour php, on peut le mettre en fast cgi et le tour est joué. Même si il y a le mot « fast », c’est quand même plus lent qu’un module, comme apache sait le faire. Les experts nginx ne courent pas les rues, donc transcrire le .htaccess n’est pas toujours envisageable (ou suffisament bien fait).

Avec tous ces problèmes, on est tenté de réinstaller apache et de ne plus se casser la tête, mais c’est sans compter sur la hiérarchie qui veut nginx car c’est plus rapide !!!

Il faut donc utiliser nginx pour le contenu statique (pages html, images, javascript, css, etc.) et quand il y a des pages php, il fait passer ça à apache. C’est le reverse proxying.

Et pour le rewriting ?

Là aussi, on voit la grande utilité d’nginx, on sert les fichiers qui existent, sinon on donne la requête à apache.

On a théoriquement le meilleur des 2 mondes. Nginx donne rapidement les pages qui ne demande pas de traitement et apache prête main forte quand il y a du contenu dynamique.

Alors, oui, il y a des pointes de sarcasme dans ce billet.

Pourquoi ?

Et bien j’ai déjà émis mon point de vue sur l’utilisation du cache et que c’est un troc, de l’espace mémoire contre du temps de calcul.

Ici on installe 2 fois le même service (on utilise plus de place en mémoire, c’est un bon départ pour le troc vu plus haut). Il faut régler les téléscopages, donc faire écouter apache sur un autre port (utilisation de resource en plus). Il faut bloquer le port depuis l’extérieur (un peu plus de travail pour le firewall). Nginx doit être réglé pour donner les fichiers directement et faire suivre tout ce qu’il ne comprend pas (on perd donc du temps à rediriger tout le contenu dynamique).

On gagne beaucoup sur le statique et on perd un peu sur le dynamique, mais au final, c’est mieux non ? Comme à mon habitude, la réponse est non !

Il y a dans apache un module mod_expires, il permet de gérer le cache client. Et quand on le règle bien, on ne télécharge plus rien.

Alors c’est quoi qui est mieux ? Nginx qui donne du contenu très rapidement ou apache qui donne un contenu beaucoup plus lentement mais une seule fois dans l’année !

Mon opinion en clair : il faut en prendre 1 et bien le régler. Nginx seul peut gérer les pages statiques, les pages dynamiques, le rewriting et la gestion du cache client. Il faut juste s’investir un peu. Apache peut en faire autant. La combinaison des 2 marche bien pour ceux qui ne font pas d’effort ni de mesure.

Si vous voulez des détails techniques su la mise en place de l’une des configurations, demandez le en commentaire.