A place to cache linked articles (think custom and personal wayback machine)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang=fr>
  4. <!-- Has to be within the first 1024 bytes, hence before the <title>
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset=utf-8>
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name=viewport content="width=device-width,minimum-scale=1,initial-scale=1,shrink-to-fit=no">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Le temps avant la première bouchée de confiture (archive) — David Larlet</title>
  13. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  14. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons/apple-touch-icon.png">
  15. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons/favicon-32x32.png">
  16. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons/favicon-16x16.png">
  17. <link rel="manifest" href="/manifest.json">
  18. <link rel="mask-icon" href="/static/david/icons/safari-pinned-tab.svg" color="#5bbad5">
  19. <link rel="shortcut icon" href="/static/david/icons/favicon.ico">
  20. <meta name="apple-mobile-web-app-title" content="David Larlet">
  21. <meta name="application-name" content="David Larlet">
  22. <meta name="msapplication-TileColor" content="#da532c">
  23. <meta name="msapplication-config" content="/static/david/icons/browserconfig.xml">
  24. <meta name="theme-color" content="#f0f0ea">
  25. <!-- That good ol' feed, subscribe :p. -->
  26. <link rel=alternate type="application/atom+xml" title=Feed href="/david/log/">
  27. <meta name="robots" content="noindex, nofollow">
  28. <meta content="origin-when-cross-origin" name="referrer">
  29. <!-- Canonical URL for SEO purposes -->
  30. <link rel="canonical" href="http://www.la-grange.net/2018/03/11/jamstack">
  31. <style>
  32. /* http://meyerweb.com/eric/tools/css/reset/ */
  33. html, body, div, span,
  34. h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  35. a, abbr, address, big, cite, code,
  36. del, dfn, em, img, ins,
  37. small, strike, strong, tt, var,
  38. dl, dt, dd, ol, ul, li,
  39. fieldset, form, label, legend,
  40. table, caption, tbody, tfoot, thead, tr, th, td,
  41. article, aside, canvas, details, embed,
  42. figure, figcaption, footer, header, hgroup,
  43. menu, nav, output, ruby, section, summary,
  44. time, mark, audio, video {
  45. margin: 0;
  46. padding: 0;
  47. border: 0;
  48. font-size: 100%;
  49. font: inherit;
  50. vertical-align: baseline;
  51. }
  52. /* HTML5 display-role reset for older browsers */
  53. article, aside, details, figcaption, figure,
  54. footer, header, hgroup, menu, nav, section { display: block; }
  55. body { line-height: 1; }
  56. blockquote, q { quotes: none; }
  57. blockquote:before, blockquote:after,
  58. q:before, q:after {
  59. content: '';
  60. content: none;
  61. }
  62. table {
  63. border-collapse: collapse;
  64. border-spacing: 0;
  65. }
  66. /* http://practicaltypography.com/equity.html */
  67. /* https://calendar.perfplanet.com/2016/no-font-face-bulletproof-syntax/ */
  68. /* https://www.filamentgroup.com/lab/js-web-fonts.html */
  69. @font-face {
  70. font-family: 'EquityTextB';
  71. src: url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff2') format('woff2'),
  72. url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff') format('woff');
  73. font-weight: 300;
  74. font-style: normal;
  75. font-display: swap;
  76. }
  77. @font-face {
  78. font-family: 'EquityTextB';
  79. src: url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff2') format('woff2'),
  80. url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff') format('woff');
  81. font-weight: 300;
  82. font-style: italic;
  83. font-display: swap;
  84. }
  85. @font-face {
  86. font-family: 'EquityTextB';
  87. src: url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff2') format('woff2'),
  88. url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff') format('woff');
  89. font-weight: 700;
  90. font-style: normal;
  91. font-display: swap;
  92. }
  93. @font-face {
  94. font-family: 'ConcourseT3';
  95. src: url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff2') format('woff2'),
  96. url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff') format('woff');
  97. font-weight: 300;
  98. font-style: normal;
  99. font-display: swap;
  100. }
  101. /* http://practice.typekit.com/lesson/caring-about-opentype-features/ */
  102. body {
  103. /* http://www.cssfontstack.com/ Palatino 99% Win 86% Mac */
  104. font-family: "EquityTextB", Palatino, serif;
  105. background-color: #f0f0ea;
  106. color: #07486c;
  107. font-kerning: normal;
  108. -moz-osx-font-smoothing: grayscale;
  109. -webkit-font-smoothing: subpixel-antialiased;
  110. text-rendering: optimizeLegibility;
  111. font-variant-ligatures: common-ligatures contextual;
  112. font-feature-settings: "kern", "liga", "clig", "calt";
  113. }
  114. pre, code, kbd, samp, var, tt {
  115. font-family: 'TriplicateT4c', monospace;
  116. }
  117. em {
  118. font-style: italic;
  119. color: #323a45;
  120. }
  121. strong {
  122. font-weight: bold;
  123. color: black;
  124. }
  125. nav {
  126. background-color: #323a45;
  127. color: #f0f0ea;
  128. display: flex;
  129. justify-content: space-around;
  130. padding: 1rem .5rem;
  131. }
  132. nav:last-child {
  133. border-bottom: 1vh solid #2d7474;
  134. }
  135. nav a {
  136. color: #f0f0ea;
  137. }
  138. nav abbr {
  139. border-bottom: 1px dotted white;
  140. }
  141. h1 {
  142. border-top: 1vh solid #2d7474;
  143. border-bottom: .2vh dotted #2d7474;
  144. background-color: #e3e1e1;
  145. color: #323a45;
  146. text-align: center;
  147. padding: 5rem 0 4rem 0;
  148. width: 100%;
  149. font-family: 'ConcourseT3';
  150. display: flex;
  151. flex-direction: column;
  152. }
  153. h1.single {
  154. padding-bottom: 10rem;
  155. }
  156. h1 span {
  157. position: absolute;
  158. top: 1vh;
  159. left: 20%;
  160. line-height: 0;
  161. }
  162. h1 span a {
  163. line-height: 1.7;
  164. padding: 1rem 1.2rem .6rem 1.2rem;
  165. border-radius: 0 0 6% 6%;
  166. background: #2d7474;
  167. font-size: 1.3rem;
  168. color: white;
  169. text-decoration: none;
  170. }
  171. h2 {
  172. margin: 4rem 0 1rem;
  173. border-top: .2vh solid #2d7474;
  174. padding-top: 1vh;
  175. }
  176. h3 {
  177. text-align: center;
  178. margin: 3rem 0 .75em;
  179. }
  180. hr {
  181. height: .4rem;
  182. width: .4rem;
  183. border-radius: .4rem;
  184. background: #07486c;
  185. margin: 2.5rem auto;
  186. }
  187. time {
  188. display: bloc;
  189. margin-left: 0 !important;
  190. }
  191. ul, ol {
  192. margin: 2rem;
  193. }
  194. ul {
  195. list-style-type: square;
  196. }
  197. a {
  198. text-decoration-skip-ink: auto;
  199. text-decoration-thickness: 0.05em;
  200. text-underline-offset: 0.09em;
  201. }
  202. article {
  203. max-width: 50rem;
  204. display: flex;
  205. flex-direction: column;
  206. margin: 2rem auto;
  207. }
  208. article.single {
  209. border-top: .2vh dotted #2d7474;
  210. margin: -6rem auto 1rem auto;
  211. background: #f0f0ea;
  212. padding: 2rem;
  213. }
  214. article p:last-child {
  215. margin-bottom: 1rem;
  216. }
  217. p {
  218. padding: 0 .5rem;
  219. margin-left: 3rem;
  220. }
  221. p + p,
  222. figure + p {
  223. margin-top: 2rem;
  224. }
  225. blockquote {
  226. background-color: #e3e1e1;
  227. border-left: .5vw solid #2d7474;
  228. display: flex;
  229. flex-direction: column;
  230. align-items: center;
  231. padding: 1rem;
  232. margin: 1.5rem;
  233. }
  234. blockquote cite {
  235. font-style: italic;
  236. }
  237. blockquote p {
  238. margin-left: 0;
  239. }
  240. figure {
  241. border-top: .2vh solid #2d7474;
  242. background-color: #e3e1e1;
  243. text-align: center;
  244. padding: 1.5rem 0;
  245. margin: 1rem 0 0;
  246. font-size: 1.5rem;
  247. width: 100%;
  248. }
  249. figure img {
  250. max-width: 250px;
  251. max-height: 250px;
  252. border: .5vw solid #323a45;
  253. padding: 1px;
  254. }
  255. figcaption {
  256. padding: 1rem;
  257. line-height: 1.4;
  258. }
  259. aside {
  260. display: flex;
  261. flex-direction: column;
  262. background-color: #e3e1e1;
  263. padding: 1rem 0;
  264. border-bottom: .2vh solid #07486c;
  265. }
  266. aside p {
  267. max-width: 50rem;
  268. margin: 0 auto;
  269. }
  270. /* https://fvsch.com/code/css-locks/ */
  271. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  272. font-size: 1rem;
  273. line-height: calc( 1.5em + 0.2 * 1rem );
  274. }
  275. h1 {
  276. font-size: 1.9rem;
  277. line-height: calc( 1.2em + 0.2 * 1rem );
  278. }
  279. h2 {
  280. font-size: 1.6rem;
  281. line-height: calc( 1.3em + 0.2 * 1rem );
  282. }
  283. h3 {
  284. font-size: 1.35rem;
  285. line-height: calc( 1.4em + 0.2 * 1rem );
  286. }
  287. @media (min-width: 20em) {
  288. /* The (100vw - 20rem) / (50 - 20) part
  289. resolves to 0-1rem, depending on the
  290. viewport width (between 20em and 50em). */
  291. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  292. font-size: calc( 1rem + .6 * (100vw - 20rem) / (50 - 20) );
  293. line-height: calc( 1.5em + 0.2 * (100vw - 50rem) / (20 - 50) );
  294. margin-left: 0;
  295. }
  296. h1 {
  297. font-size: calc( 1.9rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  298. line-height: calc( 1.2em + 0.2 * (100vw - 50rem) / (20 - 50) );
  299. }
  300. h2 {
  301. font-size: calc( 1.5rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  302. line-height: calc( 1.3em + 0.2 * (100vw - 50rem) / (20 - 50) );
  303. }
  304. h3 {
  305. font-size: calc( 1.35rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  306. line-height: calc( 1.4em + 0.2 * (100vw - 50rem) / (20 - 50) );
  307. }
  308. }
  309. @media (min-width: 50em) {
  310. /* The right part of the addition *must* be a
  311. rem value. In this example we *could* change
  312. the whole declaration to font-size:2.5rem,
  313. but if our baseline value was not expressed
  314. in rem we would have to use calc. */
  315. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  316. font-size: calc( 1rem + .6 * 1rem );
  317. line-height: 1.5em;
  318. }
  319. p, li, pre, details {
  320. margin-left: 3rem;
  321. }
  322. h1 {
  323. font-size: calc( 1.9rem + 1.5 * 1rem );
  324. line-height: 1.2em;
  325. }
  326. h2 {
  327. font-size: calc( 1.5rem + 1.5 * 1rem );
  328. line-height: 1.3em;
  329. }
  330. h3 {
  331. font-size: calc( 1.35rem + 1.5 * 1rem );
  332. line-height: 1.4em;
  333. }
  334. figure img {
  335. max-width: 500px;
  336. max-height: 500px;
  337. }
  338. }
  339. figure.unsquared {
  340. margin-bottom: 1.5rem;
  341. }
  342. figure.unsquared img {
  343. height: inherit;
  344. }
  345. @media print {
  346. body { font-size: 100%; }
  347. a:after { content: " (" attr(href) ")"; }
  348. a, a:link, a:visited, a:after {
  349. text-decoration: underline;
  350. text-shadow: none !important;
  351. background-image: none !important;
  352. background: white;
  353. color: black;
  354. }
  355. abbr[title] { border-bottom: 0; }
  356. abbr[title]:after { content: " (" attr(title) ")"; }
  357. img { page-break-inside: avoid; }
  358. @page { margin: 2cm .5cm; }
  359. h1, h2, h3 { page-break-after: avoid; }
  360. p3 { orphans: 3; widows: 3; }
  361. img {
  362. max-width: 250px !important;
  363. max-height: 250px !important;
  364. }
  365. nav, aside { display: none; }
  366. }
  367. ul.with_columns {
  368. column-count: 1;
  369. }
  370. @media (min-width: 20em) {
  371. ul.with_columns {
  372. column-count: 2;
  373. }
  374. }
  375. @media (min-width: 50em) {
  376. ul.with_columns {
  377. column-count: 3;
  378. }
  379. }
  380. ul.with_two_columns {
  381. column-count: 1;
  382. }
  383. @media (min-width: 20em) {
  384. ul.with_two_columns {
  385. column-count: 1;
  386. }
  387. }
  388. @media (min-width: 50em) {
  389. ul.with_two_columns {
  390. column-count: 2;
  391. }
  392. }
  393. .gallery {
  394. display: flex;
  395. flex-wrap: wrap;
  396. justify-content: space-around;
  397. }
  398. .gallery figure img {
  399. margin-left: 1rem;
  400. margin-right: 1rem;
  401. }
  402. .gallery figure figcaption {
  403. font-family: 'ConcourseT3'
  404. }
  405. footer {
  406. font-family: 'ConcourseT3';
  407. display: flex;
  408. flex-direction: column;
  409. border-top: 3px solid white;
  410. padding: 4rem 0;
  411. background-color: #07486c;
  412. color: white;
  413. }
  414. footer > * {
  415. max-width: 50rem;
  416. margin: 0 auto;
  417. }
  418. footer a {
  419. color: #f1c40f;
  420. }
  421. footer .avatar {
  422. width: 200px;
  423. height: 200px;
  424. border-radius: 50%;
  425. float: left;
  426. -webkit-shape-outside: circle();
  427. shape-outside: circle();
  428. margin-right: 2rem;
  429. padding: 2px 5px 5px 2px;
  430. background: white;
  431. border-left: 1px solid #f1c40f;
  432. border-top: 1px solid #f1c40f;
  433. border-right: 5px solid #f1c40f;
  434. border-bottom: 5px solid #f1c40f;
  435. }
  436. </style>
  437. <h1>
  438. <span><a id="jumper" href="#jumpto" title="Un peu perdu ?">?</a></span>
  439. Le temps avant la première bouchée de confiture (archive)
  440. <time>Pour la pérennité des contenus liés. Non-indexé, retrait sur simple email.</time>
  441. </h1>
  442. <section>
  443. <article>
  444. <h3><a href="http://www.la-grange.net/2018/03/11/jamstack">Source originale du contenu</a></h3>
  445. <p>Mon <a href="http://www.la-grange.net/2018/02/27/statique-vide">billet</a> (vite fait et pas très sérieux) sur « Une page blanche performante » a été pris un peu trop au sérieux. Donc revenons dessus un peu plus en détail. En se concentrant sur la définition des mots, il sera plus facile de cirsconcrire ma position sur le sujet.<br/>
  446. <a href="http://www.la-grange.net/2018/02/27/statique-vide">http://www.la-grange.net/2018/02/27/statique-vide</a></p>
  447. <h2 id="time-to-first-byte-ttfb">Time To First Byte (TTFB)</h2>
  448. <p><a href="https://www.dareboost.com/en/glossary#ttfb">Time To First Byte</a> (TTFB) (pointé par le <a href="https://borisschapira.com//2018/02/site-statique-performance-web/">billet de Boris Schapira</a>) donne la définition. </p>
  449. <blockquote>
  450. <p>Time elapsed between the sending of the request requiring the web page and the reception of the first data by the user. The TTFB is particularly impacted by the latency.</p>
  451. </blockquote>
  452. <p>D’ailleurs ironie de notre situation, la page glossaire en question n’affiche pas les définitions sans JavaScript et CSS. <a href="https://en.wikipedia.org/wiki/Time_to_first_byte">Le temps avant la première bouchée</a> (byte → bite → bouchée) est également définie sur Wikipedia.</p>
  453. <h2 id="requete-et-reponse-http">Requête et réponse HTTP</h2>
  454. <p>Pour les néophytes, lorsque vous cliquez un lien, le navigateur Web crée une requête HTTP à un temps <var>t0</var> vers un URL sous la forme <code>GET /miammiam</code>. Le message passe dans l’ordinateur, le réseau comprenant de nombreux routeurs, hubs, etc afin d’atteindre une autre machine physique située quelque part dans le monde. L’instruction <code>GET /miammiam</code> est reçue par la machine distante. Elle le transmet au serveur Web, qui analyse la requête et donne toutes les commandes nécessaires pour composer une réponse (un autre message). Ce message de réponse refait le voyage inverse jusqu’à votre ordinateur qui finalement le transmet au navigateur Web. Le premier « byte » (ou multiplet en français) arrive à un temps <var>t1</var> dans le navigateur Web. Ainsi <code>TTFB = t1 - t0</code>.</p>
  455. <p>En fait, si nous analysons bien ce que nous venons d’écrire, nous pouvons dégager trois phases.</p>
  456. <ul>
  457. <li>Phase 1 : Du click jusqu'au serveur (temps réseau)</li>
  458. <li>Phase 2 : De l'analyse à la composition du message (temps serveur)</li>
  459. <li>Phase 3 : Le voyage de retour (temps réseau)</li>
  460. </ul>
  461. <h2 id="site-statique">Site statique</h2>
  462. <p>Les phases 1 et 3 sont plus ou moins incontrôlables. Elles dépendent des infrastructures réseaux et de la configuration des serveurs de non de domaines. De quelques millisecondes à parfois quelques centaines de millisecondes. Nous entrons donc dans la <strong>phase 2 : la composition de la réponse</strong> et tout le débat sur les sites Web statiques ou dynamiques. <strong>Un site statique est un site où l’on minimise le temps de composition de la réponse</strong>.</p>
  463. <p>Nous appellons <strong>message</strong> tout ce qui est relatif au code HTTP et HTML envoyé par le serveur Web. Et nous appelons <strong>information</strong> tout ce qui est la notion de contenu présente dans le message. La réponse d’un serveur Web à une requête HTTP s’accompagne de la résolution de l’URL pour envoyer le message. Dans cette phase 2, le serveur peut simplement associer <code>GET /miammiam</code> à un fichier sur le disque de l’ordinateur ou bien à l’extraction du message déjà prêt en mémoire ou bien à la fabrication du message par nombre de scripts et requêtes à des bases de données. Quand les personnes mentionnent le mot statique, ils entendent souvent la pré-génération des pages qui seront directement livrées depuis le disque de l’ordinateur plutôt que générées à la volée. En évitant le temps des requêtes à la base de données, le temps de CPU des scripts, on permet au serveur Web de <strong>renvoyer le message plus rapidement</strong>.</p>
  464. <p>Cela s’accompagne d’une contrainte essentielle, <strong>toute information dynamique et vivante devient dépendante d’un message statique</strong>. Si vous désirez par exemple avoir la température de la ville de Rouen, si le message contenant l’information a été générée le jour précédent l’information n’est pas à jour bien que le serveur soit très performant dans sa réponse.</p>
  465. <h2 id="apres-la-reponse-le-rendu-de-la-page">Après la réponse, le rendu de la page</h2>
  466. <p>Ensuite il faudra pour le navigateur Web traiter le message, l’interpréter afin de l’afficher à l’utilisateur. Le navigateur téléchargera d’autres ressources images, CSS et JavaScript, la plupart du temps. Et puis il devra calculer l’affichage de la page, plus ou moins complexe en fonction du CSS et du JavaScript. C’est une fois cette affichage réalisée que les personnes peuvent interagir avec l’information contenue dans la réponse. Ainsi « le temps avant la première bouchée » n’est qu’une partie du processus et ne définit pas vraiment l’interaction.</p>
  467. <h2 id="le-cache-et-la-fraicheur">Le cache et la fraîcheur</h2>
  468. <p>Les <strong>systèmes de cache</strong> accompagnent ces processus : cache au niveau applicatif, au niveau DB, au niveau du réseau et au niveau du navigateur lui-même. Ces caches évitent de répéter une opération déjà réalisée précédemment et où l’information n’aurait pas changé. Nous remplaçons dans ce cas le temps de fabrication de la page par le temps de vérification de fraîcheur du cache.</p>
  469. <p>Un site statique (dont les pages ont été générées à l’avance) est en quelque sorte un système de cache qui s’appuie sur le système de fichiers. Dans une période donnée, nous pourrions calculer :</p>
  470. <pre><code>Nb(générations) / Nb(requêtes) = Ratio(dynamique/statique)
  471. </code></pre>
  472. <p>Plus le ratio tends vers la valeur 0 et plus le site est statique. À noter que la plupart des générateurs de sites statiques sont aussi des négations d’un véritable site statique en régénérant toutes les pages à chaque mise à jour (pour la majorité des systèmes) sans aucun changement du contenu de la page.</p>
  473. <h2 id="tas-de-confiture-jamstack">Tas de confiture (JAMStack)</h2>
  474. <p>Boris présente dans son billet la <a href="https://jamstack.org/">JAMStack</a>, qui a un site Web dédié, où on peut lire :</p>
  475. <blockquote>
  476. <p>The JAMstack is not about specific technologies. It’s a new way of building websites and apps that delivers better performance, higher security, lower cost of scaling, and a better developer experience.</p>
  477. </blockquote>
  478. <p>le « <strong>better developer experience</strong> » est pour moi un petit grincement de dents. Les <a href="https://jamstack.org/best-practices/">bonnes pratiques</a> pour réaliser un site JAMStack sont plus intéressantes que les verbiages du début. Voyons comment <a href="http://www.la-grange.net/">La Grange</a>, ce site même, se place dans leurs contraintes.</p>
  479. <ul>
  480. <li>✅ « <strong>Entire Project on a CDN</strong>. » La Grange ne dépend pas de code serveur et peut-être hébergé partout. (à part bien sûr la négotiation de contenu qui dépend de HTTP.)</li>
  481. <li>✅ « <strong>Everything Lives in Git</strong>. » La Grange pourrait être entièrement sous git, mais sincèrement, je n’en ai pas l’utilité puisque je suis tout seul et installer un serveur git pour moi tout seul semble disproportionné.</li>
  482. <li>💣 « <strong>Modern Build Tools</strong>. (And that currently means Babel, PostCSS, Webpack, and friends.) » J’ai ri. Comme si le fait d’utiliser les technologies modernes aient un sens quelconque dans le déploiement d’un site. La Grange est en ce moment généré en utilisant un script python et déployé en utilisant… <code>rsync + ssh</code></li>
  483. <li>✅ <strong>Automated Builds</strong>. Je ne suis pas sûr ce que cela signifie mais comme dit au point d’avant. Le build est automatiquement lancé à la main par un script en python. Moderne ! Une ligne de code : <code>ymir billet-blog.html</code></li>
  484. <li>✅ <strong>Atomic Deploys</strong>. Là aussi, j’ai ri. <code>rsync + ssh</code> fait exactement ce qui est décrit comme un déploiement atomique. Les fichiers uniquement modifiés sont chargés sur le serveur. Ah oui… une seule ligne de bash. </li>
  485. <li>✅ <strong>Instant Cache Invalidation</strong>. Pas nécessaire dans mon cas, mais fourni par défaut dans un site Web bien configuré. </li>
  486. </ul>
  487. <p>Tout cela me fait penser que bien souvent les développeurs ajoutent des couches complexes pour une meilleure « expérience de développeurs » mais en perdant de vue la simplicité initiale. Plus l’abstraction est grande et plus la complexité des outils viennent au final résoudre des problèmes inexistants au départ.</p>
  488. <p>Bien sûr, La Grange est un site très simple mais le sont également les <a href="https://jamstack.org/examples/">sites donnés en example</a> dans le site JAMStack.</p>
  489. <h2 id="avant-deploiement-apres-deploiement">Avant déploiement - Après déploiement</h2>
  490. <p>L’ambiguité du billet de Boris tient en partie dans la non-séparation de l’après et l’avant déploiement. Et le site JAMStack semble en quelque sorte passer à côté également. Les bonnes pratiques sont pour la plupart trop proches d’une forme de mode plutôt que de principes généraux Web. Elles ne tiennent pas vraiment compte de l’utilisateur. D’ailleurs l’utilisateur n’est pas mentionné dans le site à l’exception d’une seule fois dans la page des bonnes pratiques : « The more of your app you can push to the edge, the better the user experience. » D’ailleurs poussé l’application à sa limite ne permet en rien de donner une meilleure ergonomie du site.</p>
  491. <p>Insérer par exemple un script vers Disqus afin de créer un système de commentaires qui doit injecter un nœud dans le DOM et donc affecter le rendu, télécharger ses propres images et CSS et avec une dépendance à une latence propre qui dépend de ses propres requêtes n’améliore pas le rendu complet de la page en un temps record.</p>
  492. <p>Il y a probablement une bonne volonté derrière les acteurs de ce site/méthode. Si je compris bien l’analogie de la confiture. On mets les fruits et tous les ingrédients nécessaire dans sa gamelle, on cuisine, on met dans un pot et on range le pot sur l’étagère (le avant-déploiement) jusqu’à sa consommation potentielle (le après déploiement). Tous ces appels à des APIs sont utiles, s’ils sont réalisés en amont du déploiement, générant tout le code nécessaire aux pages statiques, figées pour un instant <var>t</var>. La JAMStack est une mise en cache en fichier de tous les éléments d’un site Web.</p>
  493. </article>
  494. </section>
  495. <nav id="jumpto">
  496. <p>
  497. <a href="/david/blog/">Accueil du blog</a> |
  498. <a href="http://www.la-grange.net/2018/03/11/jamstack">Source originale</a> |
  499. <a href="/david/stream/2019/">Accueil du flux</a>
  500. </p>
  501. </nav>
  502. <footer>
  503. <div>
  504. <img src="/static/david/david-larlet-avatar.jpg" loading="lazy" class="avatar" width="200" height="200">
  505. <p>
  506. Bonjour/Hi!
  507. Je suis <a href="/david/" title="Profil public">David&nbsp;Larlet</a>, je vis actuellement à Montréal et j’alimente cet espace depuis 15 ans. <br>
  508. Si tu as apprécié cette lecture, n’hésite pas à poursuivre ton exploration. Par exemple via les <a href="/david/blog/" title="Expériences bienveillantes">réflexions bimestrielles</a>, la <a href="/david/stream/2019/" title="Pensées (dés)articulées">veille hebdomadaire</a> ou en t’abonnant au <a href="/david/log/" title="S’abonner aux publications via RSS">flux RSS</a> (<a href="/david/blog/2019/flux-rss/" title="Tiens c’est quoi un flux RSS ?">so 2005</a>).
  509. </p>
  510. <p>
  511. Je m’intéresse à la place que je peux avoir dans ce monde. En tant qu’humain, en tant que membre d’une famille et en tant qu’associé d’une coopérative. De temps en temps, je fais aussi des <a href="https://github.com/davidbgk" title="Principalement sur Github mais aussi ailleurs">trucs techniques</a>. Et encore plus rarement, <a href="/david/talks/" title="En ce moment je laisse plutôt la place aux autres">j’en parle</a>.
  512. </p>
  513. <p>
  514. Voici quelques articles choisis :
  515. <a href="/david/blog/2019/faire-equipe/" title="Accéder à l’article complet">Faire équipe</a>,
  516. <a href="/david/blog/2018/bivouac-automnal/" title="Accéder à l’article complet">Bivouac automnal</a>,
  517. <a href="/david/blog/2018/commodite-effondrement/" title="Accéder à l’article complet">Commodité et effondrement</a>,
  518. <a href="/david/blog/2017/donnees-communs/" title="Accéder à l’article complet">Des données aux communs</a>,
  519. <a href="/david/blog/2016/accompagner-enfant/" title="Accéder à l’article complet">Accompagner un enfant</a>,
  520. <a href="/david/blog/2016/senior-developer/" title="Accéder à l’article complet">Senior developer</a>,
  521. <a href="/david/blog/2016/illusion-sociale/" title="Accéder à l’article complet">L’illusion sociale</a>,
  522. <a href="/david/blog/2016/instantane-scopyleft/" title="Accéder à l’article complet">Instantané Scopyleft</a>,
  523. <a href="/david/blog/2016/enseigner-web/" title="Accéder à l’article complet">Enseigner le Web</a>,
  524. <a href="/david/blog/2016/simplicite-defaut/" title="Accéder à l’article complet">Simplicité par défaut</a>,
  525. <a href="/david/blog/2016/minimalisme-esthetique/" title="Accéder à l’article complet">Minimalisme et esthétique</a>,
  526. <a href="/david/blog/2014/un-web-omni-present/" title="Accéder à l’article complet">Un web omni-présent</a>,
  527. <a href="/david/blog/2014/manifeste-developpeur/" title="Accéder à l’article complet">Manifeste de développeur</a>,
  528. <a href="/david/blog/2013/confort-convivialite/" title="Accéder à l’article complet">Confort et convivialité</a>,
  529. <a href="/david/blog/2013/testament-numerique/" title="Accéder à l’article complet">Testament numérique</a>,
  530. et <a href="/david/blog/" title="Accéder aux archives">bien d’autres…</a>
  531. </p>
  532. <p>
  533. On peut <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">échanger par courriel</a>. Si éventuellement tu souhaites que l’on travaille ensemble, tu devrais commencer par consulter le <a href="http://larlet.com">profil dédié à mon activité professionnelle</a> et/ou contacter directement <a href="http://scopyleft.fr/">scopyleft</a>, la <abbr title="Société coopérative et participative">SCOP</abbr> dont je fais partie depuis six ans. Je recommande au préalable de lire <a href="/david/blog/2018/cout-site/" title="Attention ce qui va suivre peut vous choquer">combien coûte un site</a> et pourquoi je suis plutôt favorable à une <a href="/david/pro/devis/" title="Discutons-en !">non-demande de devis</a>.
  534. </p>
  535. <p>
  536. Je ne traque pas ta navigation mais mon
  537. <abbr title="Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33.184162340">hébergeur</abbr>
  538. conserve des logs d’accès.
  539. </p>
  540. </div>
  541. </footer>
  542. <script type="text/javascript">
  543. ;(_ => {
  544. const jumper = document.getElementById('jumper')
  545. jumper.addEventListener('click', e => {
  546. e.preventDefault()
  547. const anchor = e.target.getAttribute('href')
  548. const targetEl = document.getElementById(anchor.substring(1))
  549. targetEl.scrollIntoView({behavior: 'smooth'})
  550. })
  551. })()
  552. </script>