A place to cache linked articles (think custom and personal wayback machine)
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  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>Don’t Wait for ServiceWorker: Adding Offline Support with One-Line (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="https://davidwalsh.name/dont-wait-serviceworker-adding-offline-support-oneline">
  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. Don’t Wait for ServiceWorker: Adding Offline Support with One-Line (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="https://davidwalsh.name/dont-wait-serviceworker-adding-offline-support-oneline">Source originale du contenu</a></h3>
  445. <p><img alt="" src="https://davidwalsh.name/demo/service-workers-1.png"></p>
  446. <p>The HTML5 Application Cache should make building offline-friendly web apps possible. In practice, its unforgiving nature makes it very challenging to use at all, giving it a <a href="http://alistapart.com/article/application-cache-is-a-douchebag">uniquely negative reputation</a> among front-end developers.</p>
  447. <p>It's expected that apps continue to work offline&acirc;&#128;&#148;most users don't won't care about the implementation details, as long as their task isn't interrupted. This experience can be the same for apps built using web technologies, in a browser or a web view using PhoneGap/Cordova.</p>
  448. <p><a href="http://offlinefirst.org/">Offline-first applications</a> have the added benefit of feeling faster, providing available information effectively even when a network connection isn't available.</p>
  449. <p>It's not just apps that benefit from offline support: web-based <a href="https://github.com/FormidableLabs/spectacle">slide frameworks</a> need to run when the conference centre Wifi inevitably drops. Likewise, any travellers on spotty connections will appreciate (or, hopefully, not notice) when any articles or documentation they were expecting to have access to continue to work.</p>
  450. <h2 id="the-future-of-offline-support">The future of offline-support</h2>
  451. <p>How do front-end developers actually go about building applications with offline support? The future appears to be ServiceWorker, but as Lyza Danger Gardner points out, ServiceWorker is only,</p>
  452. <blockquote>
  453. <p><em>partially</em> implemented in about 45 percent of the world's browsers&acirc;&#128;&#148;newer Chrome, Android, Opera browsers. That seems substantial; however, there is <a href="https://jakearchibald.github.io/isserviceworkerready/">no official word that Safari will ever implement it</a>.
  454. </p><p><em>Lyza Danger Gardner, <a href="http://alistapart.com/column/how-do-we-get-it-done-now">How do we get it done, now?</a></em></p>
  455. </blockquote>
  456. <p>Lyza points out three possible ways to overcome this technical challenge, all less than ideal:</p>
  457. <ol><li>Only use ServiceWorker, meaning offline support will not work in most browsers, including on iOS</li>
  458. <li>Use the HTML5 Application Cache, and re-write offline support using ServiceWorker too</li>
  459. <li>Use only the HTML5 Application Cache</li>
  460. </ol>
  461. <p>While the first option will work for some specific applications and audiences, most developers will need to choose one of the wider-reaching alternatives. Unfortunately, when a decision like this needs to be made, another option seems even more appealing:</p>
  462. <ul><li>Do nothing, and continue to ignore offline support.</li>
  463. </ul>
  464. <p>It's sadly a reasonable conclusion, given those options. Often, web technologies are chosen precisely for their ability to deliver a cross-platform experience with a single codebase, yet two approaches are needed to deliver an wide-reaching, yet also forward-thinking, approach to offline support. </p>
  465. <p>Falling back to the Application Cache requires generating an <code>.appcache</code> file and referencing it in the <code>html</code> attribute. Linking to it is easy; generating the file properly is complex.</p>
  466. <h2 id="apathycache">ApathyCache</h2>
  467. <p>We think one way to improve offline support on the web is to make doing <em>something</em>&acirc;&#128;&#148;including basic offline support&acirc;&#128;&#148;easier by default. Offline support should be approachable, even if the HTML5 Application Cache is far from a flawless solution. With that in mind, we added an <code>auto.appcache</code> file to every project published on <a href="https://surge.sh">Surge</a>, static web publishing for front-end developers.</p>
  468. <p>Today, for every project on Surge, we automatically build an appropriate <code>.appcache</code> file, each time you publish your static site or client-side web app. To use it, you just have to opt-in by referencing it your <code>html</code> tag:</p>
  469. <pre class="html">&lt;html manifest="/auto.appcache"&gt;</pre>
  470. <p>This gives front-end developers the option of ignoring the challenging parts of using the AppCache manifest, instead buying them time to work on the satisfying parts: getting you app or static site to running offline, and working with newer technology like ServiceWorker.</p>
  471. <h2 id="publishing-to-surge">Publishing to Surge</h2>
  472. <p>To install and publish a site on Surge, first install it through <a href="http://npmjs.org">npm</a>:</p>
  473. <pre>npm install --global surge</pre>
  474. <p>Next, run the command <code>surge</code> and pass in the directory of static files you'd like to publish to the web:</p>
  475. <pre>surge /path/to/my-project</pre>
  476. <p>This can be the compiled <code>_site</code> directory of a Jekyll project, the <code>build</code> directory of a React project, or a folder with an <code>index.html</code> file inside. Or, just run the command <code>surge</code> on its own, within the folder you want to publish.</p>
  477. <p>Either way, you'll have the option of using a randomly generated subdomain, or specifying your own:</p>
  478. <p><img alt="A gif showing the interface for the Surge command line tool, when you publish a project of flat files." src="https://davidwalsh.name/demo/service-workers-2.gif"></p>
  479. <p>After this, your project will be published and live on the web. (You can also <a href="https://surge.sh/help/adding-a-custom-domain">add a custom domain</a>, if you'd like.)</p>
  480. <h2 id="visit-your-autoappcache-file">Visit your <code>auto.appcache</code> file</h2>
  481. <p>This example was published to <code>example-autoappcache.surge.sh</code>. The <code>auto.appcache</code> will always be in the root of the project: <a href="https://example-autoappcache.surge.sh/auto.appcache">example-autoappcache.surge.sh/auto.appcache</a>.</p>
  482. <p>The Automatic AppCache manifest file built on Surge is just an automatically formatted and maintained AppCache manifest file. It starts simply enough, with a simple declaration that is, in fact, a manifest file:</p>
  483. <pre>CACHE MANIFEST</pre>
  484. <p>From here, however, things begin to get more complex.</p>
  485. <h2 id="the-cache-section">The cache section</h2>
  486. <p>In the first section, each static file in your project is automatically listed with two kinds of hashes. These hashes change when the contents of the file change&acirc;&#128;&#148;when you publish updated versions&acirc;&#128;&#148;but otherwise the application cache will continue to serve the old version.</p>
  487. <pre>CACHE:
  488. /about.html
  489. # b6bdb311c874fa38b7e6e57a24f875ee 1233
  490. /css/main.css
  491. # c7823b8fcc98bdf437ca00d7fefe3b3a 103
  492. /index.html
  493. # 1ef88ed5ba3b2645b6efad32530a4681 3009
  494. /newsletter.html
  495. # 4122172c8cfea3014425f322c82bc17a 980</pre>
  496. <p>This is normally one of the more complicated aspects of AppCache to deal with, and maintaining this file manually is completely impractical. There are some tools, <a href="#">like this Gulp plugin</a>, that make maintaining this file locally much easier, but it is dependent on the toolchain you use to build your static site and client site app.</p>
  497. <p>When you publish your site on Surge, we already do these checks to see if you have updated a file and we should propagate it across the Surge CDN, or if it remained unchanged since your last deploy. We're able to re-use that information as part of the manifest file to determine definitively if a more recent version of that resource is available or not.</p>
  498. <h2 id="the-network-section">The network section</h2>
  499. <p>Following the <code>CACHE</code> section is the network section. This combats a counter-intuitive part of how AppCache works: by default, only content in the cache section is available, online and offline. External resources are re-enabled with this section of the Auto AppCache manifest file:</p>
  500. <pre>NETWORK:
  501. *</pre>
  502. <h2 id="the-fallback-section">The fallback section</h2>
  503. <p>One part of Surge we're particularly proud of are the <a href="https://surge.sh/help/using-clean-urls-automatically">built-in clean URLs</a>, and we found a way to maintain this behaviour through the <code>FALLBACK</code> section of the AppCache manifest file. This is also automatically generated for you in Surge's <code>auto.appcache</code> file, giving you clean URLs by default:</p>
  504. <pre>FALLBACK:
  505. /about /about.html
  506. / /index.html
  507. /newsletter /newsletter.html</pre>
  508. <h2 id="opting-into-offline-support">Opting into offline support</h2>
  509. <p>While this file is generated for every project published to on Surge, developers still get to decide whether or not they'd like to opt-into using it.</p>
  510. <p>To automatically cache your application or static site using the <code>auto.appcache</code> file, reference it in the <code>manifest</code> attribute in the <code>&lt;html&gt;</code> tag:</p>
  511. <pre class="html">&lt;html manifest="/auto.appcache"&gt;</pre>
  512. <p>By omitting the full URL, the file will 404 when you are developing your project locally, preventing any potentially confusing caching there.</p>
  513. <h2 id="layering-on-serviceworker-support">Layering on ServiceWorker support</h2>
  514. <p>The automatically generated AppCache file won't work for every single project; as <a href="http://alistapart.com/article/application-cache-is-a-douchebag#section8">Jake Archibald points out</a>, you can't put all of a site of Wikipedia's size into an <code>.appcache</code> file, for example. What the <code>auto.appcache</code> file <em>does</em> do, is make it significantly easier for people with web apps, blogs, documentation sites, or client-side applications getting wrapped up in Cordova, to easily opt-into basic offline support.</p>
  515. <p>Hopefully, this buys developers the time they need to turn their focus to the more future-friendly and versatile technologies like ServiceWorker, secure in the knowledge that they have a fallback in place with much wider browser support.</p>
  516. <h2 id="further-reading">Further reading</h2>
  517. <ul><li>An example based on this article is <a href="https://github.com/surge-sh/example-autoappcache">available on GitHub</a></li>
  518. <li>Gregor Martynus's <a href="https://github.com/gr2m/appcache-nanny">AppCache Nanny</a> adds further client-side automatic updates to offline first applications, and provides finder control of how the cache is used</li>
  519. <li><a href="https://github.com/HenrikJoreteg/appcache-serviceworker-generator">Henrik Joreteg</a> and <a href="https://github.com/NekR/offline-plugin">Arthur Stolyar</a> are both independently experimenting with generating AppCache manifest files as fallbacks for ServiceWorker</li>
  520. <li>Jake Archibald's <a href="https://jakearchibald.com/2014/offline-cookbook/">Offline Cookbook</a> is a great resource on ServiceWorker</li>
  521. <li><a href="https://github.com/TalAter/UpUp">UpUp</a> is a relatively new, but promising looking, wrapper around ServiceWorker</li>
  522. <li>ServiceWorker requires a valid SSL certificate, which all projects published to <em><a href="https://surge.sh">surge.sh</a></em> subdomains receive for free. Surge also support <a href="https://surge.sh/help/securing-your-custom-domain-with-ssl">SSL for custom domains</a>.</li>
  523. </ul>
  524. </article>
  525. </section>
  526. <nav id="jumpto">
  527. <p>
  528. <a href="/david/blog/">Accueil du blog</a> |
  529. <a href="https://davidwalsh.name/dont-wait-serviceworker-adding-offline-support-oneline">Source originale</a> |
  530. <a href="/david/stream/2019/">Accueil du flux</a>
  531. </p>
  532. </nav>
  533. <footer>
  534. <div>
  535. <img src="/static/david/david-larlet-avatar.jpg" loading="lazy" class="avatar" width="200" height="200">
  536. <p>
  537. Bonjour/Hi!
  538. 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>
  539. 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>).
  540. </p>
  541. <p>
  542. 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>.
  543. </p>
  544. <p>
  545. Voici quelques articles choisis :
  546. <a href="/david/blog/2019/faire-equipe/" title="Accéder à l’article complet">Faire équipe</a>,
  547. <a href="/david/blog/2018/bivouac-automnal/" title="Accéder à l’article complet">Bivouac automnal</a>,
  548. <a href="/david/blog/2018/commodite-effondrement/" title="Accéder à l’article complet">Commodité et effondrement</a>,
  549. <a href="/david/blog/2017/donnees-communs/" title="Accéder à l’article complet">Des données aux communs</a>,
  550. <a href="/david/blog/2016/accompagner-enfant/" title="Accéder à l’article complet">Accompagner un enfant</a>,
  551. <a href="/david/blog/2016/senior-developer/" title="Accéder à l’article complet">Senior developer</a>,
  552. <a href="/david/blog/2016/illusion-sociale/" title="Accéder à l’article complet">L’illusion sociale</a>,
  553. <a href="/david/blog/2016/instantane-scopyleft/" title="Accéder à l’article complet">Instantané Scopyleft</a>,
  554. <a href="/david/blog/2016/enseigner-web/" title="Accéder à l’article complet">Enseigner le Web</a>,
  555. <a href="/david/blog/2016/simplicite-defaut/" title="Accéder à l’article complet">Simplicité par défaut</a>,
  556. <a href="/david/blog/2016/minimalisme-esthetique/" title="Accéder à l’article complet">Minimalisme et esthétique</a>,
  557. <a href="/david/blog/2014/un-web-omni-present/" title="Accéder à l’article complet">Un web omni-présent</a>,
  558. <a href="/david/blog/2014/manifeste-developpeur/" title="Accéder à l’article complet">Manifeste de développeur</a>,
  559. <a href="/david/blog/2013/confort-convivialite/" title="Accéder à l’article complet">Confort et convivialité</a>,
  560. <a href="/david/blog/2013/testament-numerique/" title="Accéder à l’article complet">Testament numérique</a>,
  561. et <a href="/david/blog/" title="Accéder aux archives">bien d’autres…</a>
  562. </p>
  563. <p>
  564. 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>.
  565. </p>
  566. <p>
  567. Je ne traque pas ta navigation mais mon
  568. <abbr title="Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33.184162340">hébergeur</abbr>
  569. conserve des logs d’accès.
  570. </p>
  571. </div>
  572. </footer>
  573. <script type="text/javascript">
  574. ;(_ => {
  575. const jumper = document.getElementById('jumper')
  576. jumper.addEventListener('click', e => {
  577. e.preventDefault()
  578. const anchor = e.target.getAttribute('href')
  579. const targetEl = document.getElementById(anchor.substring(1))
  580. targetEl.scrollIntoView({behavior: 'smooth'})
  581. })
  582. })()
  583. </script>