Catégorie : Développement web

  • Nouveau tour dans les CSS-in-JS

    L’his­toire

    J’ai aban­donné mes premiers amours qu’é­taient les feuilles de style sépa­rées avec des nommages bien séman­tiques. Je travaille par les appli­ca­tions front-end par compo­sants, j’ai besoin que les styles fonc­tionnent de façon simi­laire.

    BEM était une bonne idée mais impra­ti­cable. Le nommage est pénible et il fallait encore garder une synchro­ni­sa­tion entre la feuille de style et les compo­sants. J’ai eu plai­sir à trou­ver CSS Modules mais on conti­nue à jongler sur deux fichiers distincts avec des imports de l’un à l’autre. Il fallait faire mieux.

    J’ai besoin que les styles soient édités au même endroit que les compo­sants, toujours synchro­ni­sés, mis à jour en même temps, limi­tés chacun au compo­sant ciblé.

    Tail­wind a trouvé une solu­tion à tout ça en géné­rant statique­ment la feuille de style à partir des compo­sants eux-mêmes. Je comprends pourquoi ça plaît mais je n’ar­rive pas à consi­dé­rer que redé­fi­nir tout un pseudo-langage paral­lèle puisse être une bonne idée. On finit toujours par devoir apprendre CSS, que ce soit pour expri­mer quelque chose que le pseudo-langage ne permet pas, ou simple­ment pour comprendre pourquoi le rendu n’est pas celui qu’on imagine.

    Je suis parti vers les solu­tions CSS-in-JS quand je code du React. Faire télé­char­ger et exécu­ter toute une biblio­thèque comme Emotion est loin d’être idéal mais ça reste fina­le­ment assez négli­geable sur une appli­ca­tion front-end moderne.

    Entre temps j’ai quand même décou­vert Goober, qui implé­mente le prin­ci­pal en tout juste 1 ko. L’éli­mi­na­tion des styles morts contre­ba­lance proba­ble­ment large­ment ce 1 ko de Javas­cript. On aurait pu en rester là.


    La mise à jour

    Je suis quand même gêné de devoir embarquer une biblio­thèque Javas­cript. J’ai fouillé voir si rien de mieux que Goober et Emotion n’avait pointé le bout de son nez depuis la dernière fois que j’ai tout remis en cause. Il se trouve que le paysage a sacré­ment évolué en cinq ans.

    D’autres que moi ont eu envie d’al­ler vers du plus simple. On parle de zero-runtime. Les styles de chaque compo­sant sont extraits à la compi­la­tion pour créer une feuille de style dédiée. Les parties dyna­miques sont faites soit avec des variantes prédé­fi­nies, soit avec des variables CSS qui sont ensuite mani­pu­lée par Javas­cript via les attri­buts `style`.

    Le véné­rable c’est Vanilla-extract mais on a juste une version plus complexe et entiè­re­ment Javas­cript des CSS-Modules. C’est d’ailleurs le même auteur, et le même problème fonda­men­tal : deux fichiers distincts à mani­pu­ler et à synchro­ni­ser.

    Vient ensuite Lina­ria qui semble une vraie merveille. Il a l’es­sen­tiel de ce que proposent les CSS-in-JS avec de l’ex­trac­tion statique avec tout ce qu’on attend au niveau de l’ou­tillage : types­cript, source maps, prépro­ces­seur et véri­fi­ca­tion de syntaxe, ainsi que l’in­té­gra­tion avec tous les cadres de travail clas­siques.

    Lina­ria c’est aussi WyW-in-JS, qui opère toute la partie extrac­tion et trans­for­ma­tion, au point de permettre à qui veut de créer son propre outil concur­rent à Lina­ria. Je trouve même cette réali­sa­tion bien plus signi­fi­ca­tive que Lina­ria lui-même.

    L’équipe de MUI en a d’ailleurs profité pour faire Pigment-CSS et conver­tir tout MUI. Pigment reprend tout le prin­cipe de Lina­ria avec la gestion des thèmes, la gestion des variantes, et quelques raccour­cis syntaxiques pour ceux qui aiment l’ap­proche de Tail­wind. En échange, ces fonc­tion­na­li­tés ne sont possibles qu’en écri­vant les CSS sous forme d’objets Javas­cript plutôt que sous forme de texte CSS direc­te­ment. La biblio­thèque est aussi plus jeune et la compa­ti­bi­lité avec tous les cadres de travail ne semble pas assu­rée.

    J’ai aussi traversé Panda-CSS mais sans être convaincu. Panda génère tout en statique mais il génère tout une série d’uti­li­taires et de variables par défaut, et injecte beau­coup d’uti­li­taires dans le Javas­cript qui sera exécuté avec l’ap­pli­ca­tion. C’est un croi­se­ment entre Emotion, Tail­wind et Lina­ria, mais qui du coup me semble un peu Fran­ken­stein. À vouloir tout à la fois, on finit par ne rien avoir de franc.


    Si c’est pour utili­ser avec MUI, le choix se fait tout seul. Dans le cas contraire, au moins pour quelques mois le temps que Pigment-CSS se déve­loppe un peu plus, Lina­ria me semble un choix plus sage. S’il y a quoi que ce soit qui coince, Goober reste une solu­tion prag­ma­tique et tout à fait accep­table.

  • Comment déve­lop­pera-t-on demain ?

    Les déve­lop­peurs de mes équipes demandent depuis un moment des licences Github Copi­lot. J’ai vu quelques personnes parler de l’édi­teur Cursor.sh.

    J’avoue que j’ai eu envie de tester un peu. Sur un projet perso j’ai tenté l’ap­proche « allons-y tota­le­ment ». Je suis bluffé.

    Bon, j’ai encore le réflexe de cher­cher tout ce que je ne sais pas dans les docs. Ça veut dire que je demande prin­ci­pa­le­ment des choses que je saurais déjà faire, et poten­tiel­le­ment aussi rapi­de­ment seul qu’en saisis­sant ma demande dans l’in­ter­face. Je ne sais pas si je gagne vrai­ment du temps mais, même ainsi, l’in­ves­tis­se­ment de 2x 20$ par mois me semble une évidence.

    Avec le temps je risque de me repo­ser vrai­ment dessus et là ça fera certai­ne­ment une énorme diffé­rence. Pour un débu­tant qui apprend à coder direc­te­ment avec ces outils, ça doit être juste une révo­lu­tion.

    Le métier de déve­ve­lop­peur est en train de chan­ger radi­ca­le­ment. Je ne sais pas s’il sera le même dans 10 ans. Je ne sais même pas si ça a du sens d’en­sei­gner le code à mon fils de 11 ans.

    On est en train de tester ça au boulot, plus Code rabbit pour les revues de code. Si je trouve d’autres choses perti­nentes j’ai une propen­sion assez forte à ajou­ter aussi. Même sur un budget total de 100 ou 150 $ par mois et par déve­lop­peur, ce serait assez mal avisé de reje­ter la chose.

    Reste l’éner­gie néces­saire à tout ça, et là on touche vite la limite du modèle :

    « OpenAI’s CEO Sam Altman on Tues­day said an energy break­through is neces­sary for future arti­fi­cial intel­li­gence, which will consume vastly more power than people have expec­ted.

    Reuters, 16 janvier 2024

    Je n’ai pas de conclu­sion. L’as­pect produc­ti­vité ne fait aucun doute. La limite éner­gé­tique aussi. Malheu­reu­se­ment les deux ne vont pas du tout dans le même sens.

  • Promise Maps

    J’aime beau­coup Simon Willi­son depuis des années. Il tient un carnet de notes en guise de blog, comme j’au­rais long­temps voulu avoir le courage de faire.

    Il relaie là un commen­taire ycom­bi­na­tor :

    When caching the result of an expen­sive compu­ta­tion or a network call, don’t actually cache the result, but cache the promise that awaits the result.

    This way, if a new, unca­ched key gets reques­ted twice in rapid succes­sion, ie faster than the compu­ta­tion takes, you avoid compu­ting/fetching the same value twice. […] In other words, the promise acts as a mutex around the compu­ta­tion, and the resul­ting code is unders­tan­dable even by people unfa­mi­liar with mutexes, locks and so on.

  • Today I lear­ned : font-variant-nume­ric

    Conseil CSS : utili­sez `font-variant-nume­ric: tabu­lar-nums;` pour aligner soigneu­se­ment les nombres dans un tableau, des comp­teurs de progres­sion, etc.

    https://twit­ter.com/javan/status/1486059026064584711
  • Déve­lop­peurs, vous devriez avoir honte — Règles de mots de passe

    Je rage à chaque fois que je saisis un mot de passe fort et que le site m’en­voie bouler parce que je n’ai pas de carac­tère autre qu’al­pha­nu­mé­rique.

    Essayons quelque chose d’un peu plus smart pour évaluer la robus­tesse d’un mot de passe

    Déve­lop­peurs, vous savez proba­ble­ment tout ça, mais conti­nuez à lire parce que la fin vous est adres­sée

    Si j’en crois Hacker­noon on peut calcu­ler envi­ron 800 millions de SHA256 par seconde sur un maté­riel qui coûte 0,82 € par heure sur AWS. Ça fait 3,5 10^12 combi­nai­sons par euro.

    Traduit autre­ment, voici le nombre de combi­nai­sons qu’on peut tester, et le même chiffre écrit en puis­sance de deux (arrondi à la déci­male infé­rieure) :

    1 €3,5 × 10^122^41,6
    10 €3,5 × 10^132^44,9
    100 €3,5 × 10^142^48,3
    1 000 €3,5 × 10^152^51,6
    10 000 €3,5 × 10^162^54,9
    100 000 €3,5 × 10^172^58,2

    Quand on vous parle ailleurs de bits d’en­tro­pie, ça corres­pond à ces puis­sances de 2. Avec 1 000 € on peut tester toutes les combi­nai­sons de SHA 256 d’une chaîne aléa­toire de 51 bits.

    Ok, mais ça me dit quoi ? Une lettre c’est 26 combi­nai­sons, envi­ron 4,7 bits. Si vous ajou­tez les majus­cules vous doublez le nombre de combi­nai­sons et vous ajou­tez 1 bit. Si vous ajou­tez les chiffres et quelques carac­tères spéciaux on arrive à à peine plus de 6 bits.

    Petit calcul, en utili­sant juste les 26 lettres de l’al­pha­bet, on peut tester toutes les combi­nai­sons de 8 carac­tères pour moins de 1 €. Vu qu’on aura de bonnes chances de tomber dessus avant d’avoir testé toutes les combi­nai­sons, autant dire que même avec 9 carac­tères, votre mot de passe ne vaut pas plus de 1 €.

    Combien faut-il de carac­tères pour se trou­ver rela­ti­ve­ment à l’abri (c’est à dire que la somme inves­tie ne peut pas tester plus de 1% des combi­nai­sons) ? Ça va dépendre de ce que vous y mettez comme types de carac­tères. J’ai fait les calculs pour vous :

    a-za-z
    A-Z
    a-z
    A-Z
    0–9
    a-z
    A-Z
    0–9
    +-%
    1 €11998
    10 €111099
    100 €12101010
    1 000 €13111010
    10 000 €14111111
    100 000 €14121111

    Et là magie : 8 carac­tères, même avec des chiffres, des majus­cules et des symboles, ça résiste tout juste à 1 €. Et encore, là c’est en partant du prin­cipe que vous choi­sis­sez réel­le­ment les carac­tères de façon aléa­toire, pas que vous ajou­tez juste un symbole à la fin ou que vous trans­for­mez un E en 3.

    Vous voulez que votre mot de passe résiste à un voisin malveillant prêt à mettre plus de 10 € sur la table ? Prévoyez au moins 10 carac­tères.

    Et là, seconde magie : Si vous mettez 10 carac­tères on se moque de savoir si vous y avez mis des chiffres ou symboles. La longueur a bien plus d’im­por­tance que l’éven­tail de carac­tères utilisé.


    Main­te­nant que vous savez ça, tous les sites qui vous imposent au moins une majus­cule et un symbole mais qui vous laissent ne mettre que 8 carac­tères : Poubelle.

    Je ne suis pas en train de vous apprendre à faire un mot de passe fort. Vous devriez utili­ser un gestion­naire de mots de passe et le géné­ra­teur auto­ma­tique qui y est inclus.

    Je suis en train d’es­sayer de rendre honteux tous les déve­lop­peurs qui acceptent de mettre ces règles à la con sur les sites web dont ils ont la charge : Vous impo­sez des mots de passe qui sont à la fois imbi­tables et peu robustes.


    Vous voulez faire mieux ?

    Regar­dez dans quelle colonne est l’uti­li­sa­teur en fonc­tion des carac­tères qu’il a déjà tapé et donnez-lui un indi­ca­teur en fonc­tion de la longueur de son mot de passe.

    • Mot de passe refusé s’il est sur « Have I Been Pwned? »
    • Moins de 10 € ? mot de passe insuf­fi­sant, refusé
    • Moins de 100 € ? mot de passe faible, couleur rouge
    • Moins de 1 000 € ? mot de passe moyen, couleur orange
    • Mot de passe sûr, couleur verte, à partir de 10 000 €

    Si vous gérez un site central, par exemple un réseau social public, vous pouvez proba­ble­ment rele­ver tout ça d’un cran.

    Si ça donne accès à des données sensibles, à des possi­bi­li­tés d’achat, à la boite e-mail ou à l’opé­ra­teur télé­pho­nique, mieux vaux rele­ver tout ça de deux crans.

    Le tout prend proba­ble­ment moins de 10 lignes en javas­cript. C’est une honte que vous accep­tiez encore d’im­plé­men­ter des règles à la con « au moins une majus­cule, un chiffre et un symbole, voici les symboles auto­ri­sés […] ».

    Déve­lop­peurs, vous devriez avoir honte.

  • Où je dis du bien du CSS-in-JS

    Il n’y a que les imbé­ciles qui ne changent pas d’avis et c’est mon avis depuis toujours

    Coluche

    J’ai toujours regardé avec dédain les tenta­tives des dev JS pour contour­ner l’écri­ture de CSS mais je commence à consi­dé­rer que les outils de CSS-in-JS type Emotion sont la bonne solu­tion pour les webapp React.


    J’ai été inté­gra­teur, à faire de la belle CSS sépa­rée du code HTML. On finit quand même vite par construire des monstres ou se prendre les pieds dans le tapis dès qu’on fait plus de quelques pages types.

    Pour résoudre le problème, élimi­nons le. C’est ce que proposent les conven­tions comme BEM. Si je cari­ca­ture, il s’agit prin­ci­pa­le­ment de reti­rer les sélec­teurs CSS un attri­buant une ou plusieurs classes spéci­fiques à chaque contexte. C’est fran­che­ment moche mais ça fonc­tionne.

    CSS-Modules va un peu plus loin. Le prin­cipe est le même mais on permet au déve­lop­peur d’uti­li­ser un nommage plus agréable. C’est l’ou­til de géné­ra­tion qui gère la complexité au lieu du déve­lop­peur.


    J’avoue que j’aime bien CSS-modules. C’était mon favori jusqu’à présent.

    Ça revient à juste gérer un fichier par compo­sant en se limi­tant à des sélec­teurs très simples pour ne pas créer de conflits de spéci­fi­cité. On reste sur du CSS stan­dard et sur une approche proche de mes habi­tudes histo­riques. Mieux : L’in­té­gra­tion peut se faire indé­pen­dam­ment du langage de déve­lop­pe­ment de l’ap­pli­ca­tif.

    C’est top mais ça se base sur des compo­sants qui ne bougent pas beau­coup, dont on connait à l’avance tous les états.

    Dès qu’il s’agit de cumu­ler plusieurs états, le résul­tat dépend de l’ordre d’écri­ture dans la CSS. Parfois c’est bien prévu, parfois non.

    Dès qu’il s’agit de rendre des choses très dyna­miques, il faut de toutes façons sortir des CSS modules. Vous voulez que dans la vue large les items de navi­ga­tion se colorent au survol en fonc­tion de la caté­go­rie desti­na­tion déter­mi­née dyna­mique­ment mais qu’ils utilisent la couleur neutre dans la vue réduite desti­née aux mobiles ? Vous êtes à poil et il va falloir compo­ser avec d’autres façons d’injec­ter des CSS, peut-être même tâton­ner sur les prio­ri­tés entre classes.


    Les classes utili­taires et CSS atomiques à la Tachyon sont là pour indus­tria­li­ser en pous­sant encore plus loin.

    J’ai une classe par valeur à appliquer : .ms7-ns applique la septième valeur du cata­logue (7) comme taille hori­zon­tale maxi­mum (ms pour max-width) si la fenêtre a une taille supé­rieure au point de rupture « small » (ns pour non-small).

    Ça n’offre quasi­ment aucune abstrac­tion utile (unifor­mi­ser les valeurs on a déjà plein d’ou­tils plus effi­caces). C’est vite cryp­tique, lourd, et mons­trueux dès qu’on multi­plie les valeurs et les points de rupture possibles.

    Le seul inté­rêt par rapport à écrire direc­te­ment les attri­buts style c’est que ça permet d’ac­cé­der aux media query et aux pseudo-sélec­teurs.

    Malheu­reu­se­ment non seule­ment ça ne résout pas les conflits de prio­ri­tés mais ça les empire. Si je spécia­lise un compo­sant exis­tant en y ajou­tant une classe liée à une direc­tive déjà présente, je joue à la roulette russe. Il faut abso­lu­ment que mon compo­sant initial prévoit lui-même tous les cas possibles pour savoir quelle classe injec­ter et ou ne pas injec­ter. Pas d’al­ter­na­tive.

    J’ai vrai­ment l’im­pres­sion d’un retour en arrière mons­trueux avec ces CSS atomiques, cumu­ler les défauts sans aucun avan­tage, et c’est proba­ble­ment ce qui m’a fait reje­ter par prin­cipe les CSS-in-JS jusqu’a­lors.


    Les CSS-in-JS c’est fina­le­ment pous­ser la logique de Tachyons un cran plus loin. Quitte à déci­der de tout dans le code HTML, autant écrire direc­te­ment les styles à cet endroit là en utili­sant la vraie syntaxe CSS et en y ajou­tant la possi­bi­lité d’ac­cé­der aux media query et aux pseudo-sélec­teurs.

    Emotion c’est ça. On est à la croi­sée entre le « j’écris tout dans un attri­but style » et le « j’at­tache un module CSS ».

    En fonc­tion­ne­ment basique c’est comme un CSS module sans le sélec­teur. Je donne les direc­tives en CSS on ne peut plus clas­siques et j’ai accès aux media query, aux pseudo-sélec­teurs et aux anima­tions avec une syntaxe proche de ce que font les prépro­ces­seurs habi­tuels (et en phase avec la direc­tion que prend la syntaxe CSS elle-même).

    const style = css`
    padding: 32px;
    background-color: hotpink;
    font-size: 24px;
    border-radius: 4px;
    &:hover {
    color: blue;
    }
    `

    Je peux direc­te­ment ajou­ter le résul­tat aux classes CSS de mon compo­sant. Il se char­gera de géné­rer un nom de classe, de créer la CSS corres­pon­dante dans le docu­ment, et de lier les deux, comme avec CSS-Modules.

    L’exemple est peu parlant. On a juste l’im­pres­sion d’un CSS-Modules écrit dans le fichier JS.

    L’avan­tage c’est que je ne suis pas limité aux valeurs en dur. Je peux avoir des valeurs dyna­miques venant de mon Javas­cript ou de mon thème, et je n’en limite pas les effets à ce que me permettent les variables CSS.

    Je peux aussi réuti­li­ser, compo­ser ou surchar­ger un élément ou un bloc de styles avec un autre sans risque de conflit de prio­rité.


    Tachyons me donnait l’im­pres­sion de cumu­ler les incon­vé­nients, ici j’ai vrai­ment l’im­pres­sion de cumu­ler les avan­tages.

    La seule contrainte c’est que mon code CSS se retrouve dans mes fichiers JS. C’est moche quand c’est dit ainsi mais pour une app en React, on a de toutes façons un fichier par compo­sant HTML et ça a du sens de grou­per HTML, JS et CSS lié au compo­sant ensemble quand ils sont forte­ment liés. C’est d’ailleurs le choix de VueJS.

    Ce n’est forcé­ment pas adapté à tout, et si vous voulez rester géné­riques les CSS-Modules sont à mon avis l’op­tion la plus saine, mais pour un code React je crois que c’est là que je commen­ce­rai par défaut désor­mais.

  • Une histoire de dépen­dances

    Le main­te­neur d’un paquet NPM n’a plus eu envie et a donné la main à un tiers. Ce tiers a injecté un code mali­cieux dans une version publique et poten­tiel­le­ment infecté pas mal de monde. Ça n’a été détecté qu’au bout de deux mois et demi alors que le paquet est utilisé un peu partout.


    J’en vois qui lancent des blâmes ou qui se moquent sur l’ac­tua­lité du paquet NPM mali­cieux. Ça défoule mais : Faites-vous mieux ? Permet­tez-moi d’en douter très très forte­ment.

    Le moindre projet React, Symfony ou Rails, c’est une centaine de dépen­dances directes et indi­rectes, certaines proviennent de sources dont vous n’avez jamais entendu parler. J’ai listé trois frame­works mais c’est bien la même chose sur les autres langages/tech­nos.

    C’est bien le sujet : Sauf si vous avez la taille d’un Face­book/Google ou la criti­cité d’un Thalès ou d’un état, vous n’avez ni les moyens de passer des années-homme à tout reco­der en interne, ni les moyens d’au­di­ter chaque source à chaque mise à jour (si tant est que ça suffise).

    Même ceux que j’ai nommé, je ne suis pas certains qu’ils le fassent toujours, sur tous les types de projet. Je suis même assez convaincu du contraire. Le ratio béné­fice/risque n’est juste pas assez impor­tant pour ça. Les moyens et les délais ne sont pas dimen­sion­nés pour.


    Alors moquez-vous, de ceux qui utilisent NPM, de ceux qui ne contrôlent pas l’en­semble des dépen­dances, mais vous ne faites proba­ble­ment pas mieux. Il y a pas mal d’hy­po­cri­sie dans les réac­tions que je vois passer.

    Ne blâmez pas non plus le main­te­neur d’ori­gine. Lui ne vous a jamais rien promis. C’est même dit expli­ci­te­ment dans la licence « aucune garan­tie d’au­cune sorte ». Ce n’est pas parce que d’autres utilisent son code gratui­te­ment qu’il aurait magique­ment des comptes à rendre. En fait avoir passé la main est plutôt quelque chose d’en­cou­ragé dans l’open source. S’il n’y avait pas eu cette issue, il aurait plutôt fallu le remer­cier.


    Alors quoi ? Alors rien.

    Le problème a été résolu. Si ça arrive trop souvent alors ça chan­gera le ratio béné­fice/risque et la commu­nauté évaluera le fait d’avoir trop de dépen­dances tierces un (tout petit) peu plus néga­ti­ve­ment, et ainsi de suite.

    La ques­tion inté­res­sante que personne ne semble poser c’est celle de l’hon­nê­teté du main­te­neur d’ori­gine. A-t-il vrai­ment passé la main ? et s’il l’a fait, est-ce qu’il en a tiré un béné­fice tout en soupçon­nant ce qui pouvait se passer ? C’est à peu près la seule chose qui pour­rait à mon sens lui faire porter une quel­conque respon­sa­bi­lité.

  • « PHP 5 avancé » en chiffres

    Je vois les auteurs racon­ter leur histoire, leurs rému­né­ra­tions. Je n’ai pas trop envie de m’y mélan­ger vu que je n’ai jamais été auteur profes­sion­nel ni n’ai jamais cher­ché à l’être. Mes enjeux d’au­teur du dimanche sont bien diffé­rents. Ajou­tez y que j’ai écrit dans à propos de tech­nique infor­ma­tique, très loin des auteurs de romans et de bande dessi­née.

    Pour autant, c’est aussi l’oc­ca­sion parce que je ne crois pas avoir déjà fait un tel bilan. Peut-être que ça inté­res­sera certain d’entre vous. Dites-moi s’il y a des ques­tions auxquelles je ne réponds pas.

    Atten­tion, ce n’est repré­sen­ta­tif de rien d’autre que de mon cas person­nel. J’ai même tendance à penser que mon histoire entre dans l’ex­cep­tion à plus d’un titre. Le fait qu’il y ait des gros chiffres dans la suite ne doit certai­ne­ment pas vous amener à penser que les auteurs roulent habi­tuel­le­ment sur l’or.

    Six éditions et quatre colla­bo­ra­teurs

    Travail à quatre mains avec Cyril Pierre de Geyer. Le premier chapitre a été fait en février 2003 pour une publi­ca­tion de 700 pages en juin 2004.

    PHP a pas mal évolué et le livre serait rapi­de­ment devenu obso­lète. Nous avons du mettre à jour le livre régu­liè­re­ment. Il y a eu une édition par an jusqu’en 2008 puis une sixième de 870 pages en 2012.

    La troi­sième édition a été reti­rée sur un format « best-of » en 2007, en paral­lèle de la vente de la quatrième dans son format d’ori­gine. J’avoue que ça me semble toujours étrange, d’au­tant que si nous en avons fait une quatrième édition plutôt qu’un reti­rage c’est que l’évo­lu­tion de PHP rendait l’an­cienne version moins perti­nente.

    Nous avons été épaulé par Hugo Hamon pour les relec­tures et l’in­dexa­tion de la cinquième édition. La sixième édition a été parta­gée avec un troi­sième auteur, Frédé­ric Hardy. Il est en petit sur la couver­ture, je le regrette aujourd’­hui.

    Les tirages et les ventes

    Le premier tirage était prévu à 3000 exem­plaires. Vus les chiffres de vente je suppose qu’il en a plutôt été tiré 3200 (ou alors on a vendu des livres qui n’exis­taient pas). Les chiffres des éditions suivantes ne tombant même pas proches de multiples de 250, j’ima­gine qu’on en imprime toujours un peu plus au cas où et que le chiffre final n’est pas tota­le­ment maitri­sable.

    La seconde édition a été tirée à envi­ron 3700 exem­plaires, la troi­sième et la quatrième ont toutes les deux fait entre 3200 et 3300 exem­plaires, plus envi­ron 4000 exem­plaires pour la best-off. La cinquième a béné­fi­cié de deux tirages, proba­ble­ment respec­ti­ve­ment 3400 et 2000 exem­plaires. La dernière a été tirée à quelque chose comme 3800 exem­plaires, proba­ble­ment en deux fois.

    Au total j’ai quelque chose comme 26 500 ventes sur les 12 ans de vie du livre.

    Le travail d’écri­ture

    Diffi­cile d’es­ti­mer le temps passé en écri­ture tant il était très frac­tionné, d’au­tant que ce n’était pas mon acti­vité prin­ci­pale. Sur les 16 mois de travail de l’édi­tion initiale, j’ai quand même du y passer une bonne majo­rité des soirs et week-end, et quelques mois quasi­ment à temps plein. À cela il faut bien entendu ajou­ter le travail de mon co-éditeur.

    Chose éton­nante pour moi, nous n’avons pas utilisé de logi­ciel ou de format de fichier spéci­fique à l’édi­tion, juste du Micro­soft Word avec une feuille de styles interne : un fichier par version et par chapitre nommé d’après l’au­teur a avoir créé la version, le tout dans un FTP.

    Les autres éditions ont été un effort variable, plus fort pour les premières que pour les dernières. On parle quand même géné­ra­le­ment de plusieurs mois pendant des soirs et des week-ends.

    Je n’ai aucune idée du travail total en équi­valent temps plein 35h sala­rié. Si je devais donner un chiffre je dirais proba­ble­ment un an équi­valent temps plein sala­rié, mais en réalité ça peut faci­le­ment être la moitié moins ou moitié plus.

    Malgré la moti­va­tion des premiers temps, faire ça en paral­lèle d’un job très prenant n’est pas aisé, surtout au moment des relec­tures. La colla­bo­ra­tion entre auteurs n’a pas toujours été évidente non plus. Ça parait évident après coup mais écrire à deux quand on ne se connait pas vrai­ment et qu’on ne se voit jamais en face à face, c’est forcé­ment un peu diffi­cile.

    La rému­né­ra­tion

    La rému­né­ra­tion est de 10% du hors taxe pour les ventes françaises grand format (4% sur les ventes à l’étran­ger, 5% sur le format poche — l’édi­teur a souhaité en sortir un une année, nous avons refusé), à parta­ger entre les auteurs initiaux, sans aucune avance, sur des livres qui ont varié de 35 à 45 € pour la collec­tion prin­ci­pale, 25 € pour le best-of.

    Même en allant cher­cher dans les archives, je suis encore aujourd’­hui inca­pable de dire combien j’ai gagné que ce soit en net ou en brut. J’ai des comptes de vente, des détails de coti­sa­tions, des avis de paie­ment et des résu­més de sommes à décla­rer au fisc. Rien ne se recoupe vrai­ment, quand je n’ai pas deux docu­ments d’un même type tota­le­ment diffé­rents pour une même année.

    Disons que la somme encais­sée avant impôts sur le revenu doit être entre 40 et 47 000 euros nets depuis le premier verse­ment en 2005. Précis hein ?

    Ramené à un an de travail c’est effec­ti­ve­ment très bien payé, surtout par rapport à ce que je lis à propos de auteurs en litté­ra­ture, en jeunesse ou en bande dessi­née. Même dans la four­chette haute, en comp­tant deux ans de travail en équi­valent temps plein, ça reste bien au dessus du SMIC. Cela dit il était loin d’être dit que ça rému­nè­re­rait autant, et ce que ça m’a apporté a large­ment dépassé le finan­cier. Je ne pensais pas à l’argent. Je ne m’étais en fait même pas fait de prévi­sion quand j’ai dit oui, et je n’au­rais pas su dire si je m’at­ten­dais à 1 000 ou 10 000 euros.

    Cette somme est après paie­ment de la TVA, de la CSG et CRDS, ainsi que d’une coti­sa­tion de 1% à l’Agessa. Tout ça est prelevé pour moi en amont par l’édi­teur. Pas de retraite, pas de prévoyance, et avec dans les 4000€ par an en moyenne je n’au­rais proba­ble­ment eu aucune couver­ture sociale si je n’avais pas eu un emploi sala­rié en paral­lèle.

    Pour l’im­pôt sur le revenu je déclare ce que l’édi­teur me dit en trai­te­ments et salaires. C’est peut-être idiot ou anor­mal, je n’ai jamais su (on m’a donné des réponses diffé­rentes à chaque fois que je deman­dais ce que devait faire un auteur de loisir) mais du coup c’est imposé sur le barème progres­sif.

    Autant Hugo (en relec­teur) que Frédé­ric (en co-auteur sur la dernière mise à jour) ont été rému­né­rés sur une base fixe, payée par l’édi­teur en plus de nos droits d’au­teur.

    L’édi­teur

    J’en­tends beau­coup de choses sur les éditeurs. Person­nel­le­ment moi j’ai plutôt eu une très bonne expé­rience d’Ey­rolles. Muriel, tu as été vrai­ment super, Karine aussi, et j’ou­blie certai­ne­ment des gens. Je n’ai eu à me plaindre de personne, au contraire.

    Si je devais repro­cher quelque chose, c’est le refus total de consi­dé­rer une durée limi­tée pour la version numé­rique du livre. Je crains cepen­dant qu’il en soit de même pour l’es­sen­tiel des éditeurs et mon co-auteur a de toutes façons refusé toute vente numé­rique par peur du pira­tage (qui a tout de même eu lieu, visi­ble­ment par des fuites des PDF internes desti­nés à l’im­pri­meur, avec les marques de découpe). Oh si, si je devais pinailler, il y a briè­ve­ment eu une mise en vente de la quatrième édition sous forme numé­rique malgré le refus expli­cite au contrat, mais ils y ont mis un terme quand on l’a fait remarquer.

    Je ne m’éten­drai pas sur ce point mais on a même eu une diffi­culté de répar­ti­tion des droits entre co-auteurs à un moment. Non seule­ment l’édi­teur a aidé à sa réso­lu­tion mais il a aussi pris le diffé­ren­tiel à sa charge pour solder le passé. Ok, vu les ventes ils pouvaient se le permettre, mais rien ne les y obli­geait non plus.

    PHP 7 avancé

    Aujoud’­hui PHP 5 avancé n’existe plus. Il y a eu réécri­ture partielle pour construire PHP 7 avancé mais consi­dé­rant les diffi­cul­tés de colla­bo­ra­tion, on a décidé de ne pas forcé­ment le refaire ensemble. Je suis toujours sur la couver­ture en grisé mais j’ai passé la main aux excel­lents Pascal Martin et Julien Pauli, au moins pour les deux premières éditions (la seconde arrive parait-il sous peu).

  • Comment on fait de la crypto dans le navi­ga­teur ?

    Faire de la cryp­to­gra­phie dans le navi­ga­teur se révèle bien plus simple que prévu.

    Lais­sez tomber les portages de libso­dium & co. Quasi­ment tous les navi­ga­teurs supportent désor­mais une API native dédiée. Seul IE11 ne le fait pas tota­le­ment mais il a au moins le mini­mum qu’est la géné­ra­tion de nombres réel­le­ment aléa­toires. Ceux qui veulent vrai­ment pour­ront complé­ter l’im­plé­men­ta­tion d’IE11 avec un poly­fill sans risquer de problème de sécu­rité.

    Il y a plein de jolis exemples sur qnimate mais certaines choses datent un peu. J’ai tenté de résu­mer ici pour ceux que ça inté­resse. Ici pour du déchif­fre­ment à partir d’une clef secrète.

    Avant-propos

    Je ne suis pas un expert en chif­fre­ment et ce genre de choses est toujours à manier avec précau­tion. Si vous faites quelque chose de sérieux, ne vous conten­tez pas d’exemples et embau­chez quelqu’un qui sait.

    Rien que choi­sir l’al­go­rithme perti­nent demande de savoir ce qu’on fait. AES-CTR semble perti­nent pour mon cas d’usage où n’ai pas besoin de véri­fier l’au­then­ti­cité du message, où je n’ai pas envie de me colti­ner les ques­tions de padding, et où je serai heureux de profi­ter des multiples cœurs des smart­phones.

    Si l’al­go­rithme choisi ou autre chose vous dérange et que vous en savez plus que moi, n’hé­si­tez pas à commen­ter.

    Récu­pé­rer une clef

    Le plus simple est de récu­pé­rer direc­te­ment une clef au format JSON Web Key (en gros la clef en base64url plus un peu de méta­don­nées). Dans ce cas il suffit de passer par importKey :

    const crypto = window.crypto.subtle;
    
    const jwk = {
      "kty": "oct",
      "use": "enc",
      "k": "SDRSTgdOpUGfgn3iAwiC1cpzsevLM98r_6ehMXlK1Gk",
      "alg": "A256CTR"
    };
    const algo = {name: "AES-CTR"};
    const exportable = false;
    const usage = ["decrypt"];
    
    const key = await crypto.importKey("jwk", jwk, algo, exportable, usage);
    Déri­ver une clef

    Si on veut partir d’une phrase secrète mémo­ri­sable et non d’une clef complète, on commence par créer une clef tempo­raire et on utilise un algo­rithme de déri­va­tion comme PBKDF2.

    Malheu­reu­se­ment pour créer cette première clef il faut passer par un TextEn­co­der et ArrayBuf­fer. peut toujours déri­ver la clef à partir de là. TextEn­co­der n’existe pas sous Edge et IE11, il vous faudra utili­ser une fonc­tion comme uniba­bel qui fait ça pour vous.

    const crypto = window.crypto.subtle;
    const encoder = TextEncoder();
    
    const passphrase = "l'eau ça mouille, le feu ça brûle";
    const buffer = encoder.encode( passphrase );
    const d_algo =  {name: 'PBKDF2'};
    const d_exportable = false;
    const d_usage = ['deriveBits', 'deriveKey'];
    const d_key = await crypto.importKey('raw', buffer, d_algo, d_exportable, d_usage);
    
    const deriv = { 
      name: 'PBKDF2',
      salt: encoder.encode( "c'est le week-end !" ),
      iterations = 25,
      hash: 'SHA-256',
    };
    const algo = {name: "AES-CTR", length: 256}; 
    const exportable = false; 
    const usage = ["decrypt"];
    
    const key = await crypto.deriveKey(deriv, d_key, algo, exportable, usage);

    La sécu­rité de tout ça dépend de la longueur et de l’uni­cité de votre phrase secrète initiale. À vous de trou­ver le bon compro­mis entre la sécu­rité et la puis­sance des smart­phones qui risquent d’uti­li­ser votre code. Le 25 ici est pure­ment arbi­traire et le temps de calcul néces­saire est propor­tion­nel.

    Déchif­frer

    Déchif­frer n’est pas plus diffi­cile.

    Le vecteur d’ini­tia­li­sa­tion (iv) et la donnée chif­frée (encryp­ted) sont atten­dus sous forme d’Ar­rayBuf­fer. Il faudra de nouveau passer par uniba­bel ou une autre solu­tion si vous avez ça sous forme de chaîne binaire ou codé en base64.

    Le résul­tat de decrypt() vous est retourné sous la même forme. S’il est petit le plus simple est d’uti­li­ser TextDe­co­der ou uniba­bel. Si vous avez quelque chose de plus volu­mi­neux vous pouvez aussi passer par un Blob et un FileRea­der.

    const crypto = window.crypto.subtle;
    const decoder = TextDecoder
    
    const key = ...
    const iv = ...
    const encrypted = ...
    
    const algo = { name: 'AES-CTR', iv: iv }
    const buffer = await crypto.decrypt(alg, key, encryted);
  • Donnée confi­den­tielle dans une session de navi­ga­tion.

    Je partage, ça peut servir à d’autres. Je cher­chais à garder confi­den­tiel une infor­ma­tion confi­den­tielle le temps d’une session de navi­ga­tion. En gros je cher­chais un genre de cookie de session mais qui reste côté client sans jamais tran­si­ter sur le réseau.

    Le localS­to­rage est top mais il persiste au delà de la session de navi­ga­tion. Le sessionS­to­rage est top mais il n’est pas partagé entre les onglets.

    Visi­ble­ment certains se sont penchés sur la ques­tion il y a quelques années et sont reve­nus avec une solu­tion toute bête mais effi­cace : Faire dialo­guer les diffé­rents sessionS­to­rage en surveillant les écri­tures dans le localS­to­rage.

    C’est tout con, ça prend juste 20 lignes, mais il fallait y penser.

    Merci Rik