PageSourceSearch

https://cdn.v1v2.io/_next/static/chunks/pages/blog/application-web-offline-cache-manifest-f48cea9c855331b7.js

js v1v2.io collected 2026-09-25 21:06:38 UTC 26,132 bytes, 1 lines download raw bytes

1(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3993],{96292:(e,n,i)=>{(window.__NEXT_P=window.__NEXT_P||[]).push(["/blog/application-web-offline-cache-manifest",function(){return i(81723)}])},46833:(e,n,i)=>{"use strict";i.d(n,{A:()=>r});var s=i(74848),t=i(21055),a=i(53924);let r=e=>{let{src:n,alt:i,...r}=e;return(0,s.jsx)(t.E9,{src:n,alt:i,center:!0,my:a.vU,...r})}},32526:(e,n,i)=>{"use strict";i.d(n,{A:()=>a});var s=i(74848),t=i(21055);let a=e=>{let{year:n,lang:i="fr"}=e;return(0,s.jsx)(t.nC,{className:"deprecation-warning",textAlign:"center",children:(0,s.jsx)("p",{children:"fr"===i?(0,s.jsxs)(s.Fragment,{children:["Cet article a \xe9t\xe9 \xe9crit en ",(0,s.jsx)("strong",{children:n})," et peut contenir des informations obsol\xe8tes !"]}):(0,s.jsxs)(s.Fragment,{children:["This article was written in ",(0,s.jsx)("strong",{children:n})," and may contain outdated information!"]})})})}},85039:(e,n,i)=>{"use strict";i.d(n,{A:()=>a});var s=i(74848),t=i(21055);let a=e=>{let{children:n}=e;return(0,s.jsx)("aside",{children:(0,s.jsx)(t.P,{textAlign:"center",children:(0,s.jsxs)("em",{children:["“",n,"”"]})})})}},81723:(e,n,i)=>{"use strict";i.r(n),i.d(n,{default:()=>m});var s=i(74848),t=i(46833),a=i(77083),r=i(1),l=i(32526),o=i(85039),c=i(21055),u=i(85044);let p={src:"https://cdn.v1v2.io/_next/static/media/folder-earth.bb3a3bc1.png",height:128,width:128,blurDataURL:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAMAAADz0U65AAAAaVBMVEVMaXFoip8FFDINK1oPHCgbLDkABQsAAQUHFSUGEiAzS2dgZ44FEBsBCRMVNVMAAwkqUIkAAACEpL4iW4Bg1fpMlcIADzlkmL17lrMBCyoxcazO1NgACzMEECKEt94CCRiP4PsPNnEjM0skdefOAAAAHXRSTlMA/nSH/fyK/TBk/TCJ0cntZhG1/vz7of37zlP6s/8ZC2wAAAAJcEhZcwAACxMAAAsTAQCanBgAAABDSURBVHicBcGFAcAgEACxo8gjdTdq+w/ZBCClXRfg+2lZ3w3aa3yOeBJqpYb4zZTWZpGs8cZkkbsAVzUiEgA6H5z/AXgBAwzCWUoQAAAAAElFTkSuQmCC",blurWidth:8,blurHeight:8};var d=i(53924);let h=()=>(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("header",{children:[(0,s.jsx)(u.A,{mb:d.vU,children:"Une application web offline HTML5 avec le cache manifest"}),(0,s.jsx)(t.A,{src:p,alt:"Dossier avec une plan\xe8te",imageProps:{quality:100,priority:!0},mb:d.rf}),(0,s.jsx)(l.A,{year:2010}),(0,s.jsxs)("p",{children:["Parmi l'ensemble des nouveaut\xe9s apport\xe9es par l'HTML5, on entend surtout parler des plus \"multim\xe9dia\" d'entre elles, c'est \xe0 dire des balises ",(0,s.jsx)(c.Cy,{children:"audio"}),", ",(0,s.jsx)(c.Cy,{children:"video"}),","," ",(0,s.jsx)(c.Cy,{children:"canvas"}),"... Pourtant, ces fonctionnalit\xe9s ne sont pas vraiment nouvelles pour l'utilisateur final, qui \xe9tait d\xe9j\xe0 habitu\xe9 \xe0 de tels contenus avec Flash. L'une des r\xe9elles r\xe9volutions apport\xe9es par l'HTML5, et une des moins m\xe9diatis\xe9e, est la possibilit\xe9 de cr\xe9er des applications web offline."]})]}),(0,s.jsxs)("section",{children:[(0,s.jsx)(c.H2,{children:"Introduction"}),(0,s.jsx)("p",{children:'Le terme "application offline" doit \xeatre un peu nuanc\xe9 et compris plut\xf4t comme : "Des applications web qui continuent \xe0 fonctionner m\xeame quand la connexion internet se coupe". De plus, le terme "application" a \xe9t\xe9 banalis\xe9 par l\'av\xe8nement des smartphones, mais dans ce cadre, on doit plut\xf4t comprendre des "sites web". Cela dit la diff\xe9rence entre les deux va s\'amoindrir de plus en plus dans les ann\xe9es \xe0 venir...'}),(0,s.jsx)("p",{children:"Ces applications sont donc principalement destin\xe9es aux t\xe9l\xe9phones portables, qui subissent r\xe9guli\xe8rement des d\xe9connexions. Prenons un exemple :"}),(0,s.jsx)("p",{children:"Vous r\xe9digez un mail sur votre iPhone ou votre Android, connect\xe9 \xe0 internet avec la 3G, sur l'application Gmail. Puisque vous \xeates bien entendu quelqu'un de mobile et dynamique (c'est \xe9vident !) vous vous d\xe9placez avec votre smartphone. Puis vous prenez un ascenseur, ou votre m\xe9tro passe dans un tunnel, ce qui coupe votre connexion 3G. Que se passe-t-il ?"}),(0,s.jsx)(o.A,{children:"Hum... Rien ?"}),(0,s.jsx)("p",{children:'Tout \xe0 fait ! L\'application Gmail ne se ferme pas subitement en criant "Alerte ! Je ne capte plus le r\xe9seau 3G, fermeture de l\'application !". Elle continue de fonctionner en "offline". Vous pouvez m\xeame "envoyer" un mail sans avoir d\'acc\xe8s \xe0 internet, et celui-ci sera mis en attente localement, puis r\xe9ellement envoy\xe9 d\xe8s que vous r\xe9cup\xe9rerez votre connexion.'}
1),(0,s.jsx)("p",{children:'On est donc face \xe0 des applications "hybrides" qui fonctionnent \xe0 la fois online et offline.'}),(0,s.jsx)(o.A,{children:"\xc7a me semble bien compliqu\xe9 \xe0 r\xe9aliser..."}),(0,s.jsx)("p",{children:"Bien au contraire, c'est tr\xe8s simple, et vous saurez le faire apr\xe8s avoir lu ce tutoriel !"}),(0,s.jsxs)("section",{children:[(0,s.jsx)(c.H3,{children:"La compatibilit\xe9"}),(0,s.jsx)("p",{children:"Comme toute fonctionnalit\xe9 HTML5, une question importante se pose : la compatibilit\xe9. Qu'en est-il avec les applications offline ? Elles fonctionnent d\xe9j\xe0 sur tous les navigateurs sauf Internet Explorer. Et Internet Explorer 9 ne supportera pas cette fonctionnalit\xe9 non plus."}),(0,s.jsx)(o.A,{children:"Quoi ?! Mais \xe7a n'a aucun int\xe9r\xeat !"}),(0,s.jsx)("p",{children:"Haha du calme... Croyez-vous que votre ordinateur fixe subisse fr\xe9quemment des d\xe9connexions du r\xe9seau 3G...? Non bien entendu. Les applications offline sont principalement destin\xe9es aux smartphones et autres tablettes tactiles, et les navigateurs Android et iPhone, supportent d\xe9j\xe0 cette fonctionnalit\xe9. Aucun probl\xe8me du c\xf4t\xe9 de la compatibilit\xe9 donc !"}),(0,s.jsx)(o.A,{children:"Bon d'accord, on peut l'utiliser alors. Mais attends, il n'y a pas d\xe9j\xe0 un mode hors-ligne dans les navigateurs ?"}),(0,s.jsx)("p",{children:'Effectivement les navigateurs proposent d\xe9j\xe0 depuis plusieurs ann\xe9es des consultations de site "hors ligne", et de la mise en cache de certains fichiers. Mais soyons clairs : ces techniques sont peu fiables et tr\xe8s instables. Si vous actualisez une page en ayant perdu la connexion \xe0 internet, la plupart du temps vous aurez droit \xe0 une belle erreur vous demandant de v\xe9rifier votre connexion...'}),(0,s.jsx)("p",{children:"Allez, tr\xeave de bavardage, on se plonge au coeur du sujet !"})]})]}),(0,s.jsxs)("section",{children:[(0,s.jsx)(c.H2,{children:"Le cache d'application (AppCache)"}),(0,s.jsx)(c.nz,{children:'Les applications offline utilisent "l\'application cache" du navigateur, qui permet :'}),(0,s.jsxs)(c.uQ,{children:[(0,s.jsx)("li",{children:"D'utiliser une application web sans connexion internet,"}),(0,s.jsx)("li",{children:"D'am\xe9liorer la vitesse de chargement des pages en pr\xe9chargeant des fichiers,"}),(0,s.jsx)("li",{children:"De r\xe9duire la charge du serveur, puisqu'en effet, il n'enverra que les fichiers qui auront chang\xe9 depuis le dernier passage de l'utilisateur."})]}),(0,s.jsx)("p",{children:"Notez au passage une petite remarque non n\xe9gligeable : le cache d'une application est limit\xe9 \xe0 5Mo."})]}),(0,s.jsxs)("section",{children:[(0,s.jsx)(c.H2,{children:"La page HTML"}),(0,s.jsx)("p",{children:"L'application cache repose principalement sur l'utilisation d'un fichier \"manifest\" \xe0 ajouter aux pages HTML de votre site. Tout d'abord, cr\xe9ons donc une structure basique de page web :"}),(0,s.jsx)(r.A,{lang:"html",children:'<!DOCTYPE html>\n<html>\n  <head>\n    <style type="text/css">\n      #main {\n        width: 900px;\n        margin: auto;\n      }\n    </style>\n  </head>\n  <body>\n    <div id="main">\n      <h1>Ceci est mon application offline</h1>\n      <img src="earth-folder.png" />\n    </div>\n  </body>\n</html>'}),(0,s.jsxs)("p",{children:["Afin d'utiliser le cache d'application, il va falloir d\xe9clarer un fichier manifest. Ce fichier se d\xe9clare dans la balise ",(0,s.jsx)(c.Cy,{children:"html"})," comme ceci :"]}),(0,s.jsx)(r.A,{children:'<html manifest="site.manifest">'})]}),(0,s.jsxs)("section",{children:[(0,s.jsx)(c.H2,{children:"Le manifest"}),(0,s.jsxs)("p",{children:["Une fois d\xe9clar\xe9, il faut bien s\xfbr cr\xe9er le fichier manifest en question. Appelons le n\xf4tre"," ",(0,s.jsx)(c.Cy,{children:"site.manifest"}),". Dans ce fichier, qui commence obligatoirement par la ligne"," ",(0,s.jsx)(c.Cy,{children:"CACHE MANIFEST"}),", nous allons d\xe9clarer les fichiers qui doivent \xeatre mis en cache :"]}),(0,s.jsx)(r.A,{lang:"sh",children:"CACHE MANIFEST\n\n# Version 0.1\n\nindex.html\nearth-folder.png"}),(0,s.jsxs)("p",{children:["On peut \xe9galement y ajouter des commentaires. Chaque ligne de commentaire doit commencer par"," ",(0,s.jsx)(c.Cy,{children:"#"}),". Il est important de versionner son fichier manifest via un commentaire, afin que le navigateur d\xe9tecte par la suite les changements dans le fichier. Nous y reviendrons plus tard."]}),(0,s.jsx)("p",{children:"Notons qu'il est possible d'utiliser des URL absolues."}),(0,s.jsx)(c.nz,{children:"Il est possible d'ajouter diff\xe9rentes sections \xe0 notre fichier manifest :"}),(0,s.jsxs)(c.uQ,{children:[(0,s.jsxs)("li",{children:[(0,s.jsx)(c.Cy,{children:"CACHE"}),", il s'agit de la section par d\xe9faut qui liste les fichiers \xe0 mettre en cache."]}),(0,s.jsxs)("li",{children:[(0,s.jsx)(c.Cy,{children:"NETWORK"}),", qui liste les fichiers qui n\xe9cessitent obligatoirement une connexion internet."]}),(0,s.jsxs)("li",{children:[(0,s.jsx)(c.Cy,{children:"FALLBACK"}),", qui liste les fichiers qui, au cas o\xf9 ils ne soient pas accessibles en ligne, doivent renvoyer vers d'autres fichiers."]})]}),(0,s.jsxs)("p",{children:["L'exemple suivant repr\xe9sente un site web classique dont la page d'accueil, le CSS et les images sont mises en cache. Si l'utilisateur se connecte \xe0 la page d'accueil en \xe9tant hors ligne, la page ",(0,s.jsx)(c.Cy,{children:"offline.html"})," lui est pr\xe9sent\xe9e au lieu d'",(0,s.jsx)(c.Cy,{children:"index.html"}),". Il est donc inform\xe9 qu'il est d\xe9connect\xe9. Par cons\xe9quent il ne pourra pas acc\xe9der aux autres pages du site, puisque la section ",(0,s.jsx)(c.Cy,{children:"NETWORK"})," sp\xe9cifie via une \xe9toile"," ",(0,s.jsx)(c.Cy,{children:"*"}),", que tous les autres fichiers requi\xe8rent une connexion internet."]}),(0,s.jsx)(r.A,{lang:"sh",children:"\nCACHE MANIFEST\n\n# v0.1\n\nCACHE:\nindex.html\ncss/style.css\nimg/logo.png\n\nFALLBACK:\n/ /offline.html\n\nNETWORK:\n*"})]}),(0,s.jsxs)("section",{children:[(0,s.jsx)(c.H2,{children:"Le .htaccess"}),(0,s.jsxs)("p",{children:["Nous arrivons maintenant au passage (un peu) d\xe9licat. Il va falloir d\xe9clarer le"," ",(0,s.jsx)(c.A,{isExternal:!0,href:"http://fr.wikipedia.org/wiki/Type_MIME",children:"MIME-type"})," ","du fichier manifest. Ceci se fait par l'interm\xe9diaire du fichier de configuration de serveur. Dans la grande majorit\xe9 des cas vous utiliserez un fichier ",(0,s.jsx)(c.Cy,{children:".htaccess"})," ","pour les projets PHP. Cr\xe9ez donc un fichier ",(0,s.jsx)(c.Cy,{children:".htaccess"})," dans le r\xe9pertoire de votre application et ajoutez-y simplement la ligne :"]}),(0,s.jsx)(r.A,{lang:"sh",children:"AddType text/cache-manifest manifest"}),(0,s.jsxs)("p",{children:["Dans cette ligne, on d\xe9clare que tous les fichiers se terminant par ",(0,s.jsx)(c.Cy,{children:"manifest"})," ","ont pour MIME-type ",(0,s.jsx)(c.Cy,{children:"text/cache-manifest"}),"."]})]}),(0,s.jsxs)("section",{children:[(0,s.jsx)(c.H2,{children:"Test de l'application hors ligne"}),(0,s.jsx)("p",{children:"Afin de pouvoir tester localement notre application, nous allons devoir passer par Apache (et oui, faites chauffer vos WAMP / MAMP / LAMP !)."}),(0,s.jsxs)("p",{children:["Pla\xe7ons notre application dans le dossier de votre serveur (www pour WAMP) et rendez-vous sur l'adresse ",(0,s.jsx)(c.Cy,{children:"http://localhost/"}),". Si tout se passe bien, votre page s'affiche. Maintenant stoppez les services de WAMP, puis rafra\xeechissez la page."]}),(0,s.jsx)("p",{children:"Alors qu'une page classique aurait naturellement fait afficher une belle erreur 404... Votre page est toujours l\xe0 ! Ouvrez maintenant la console de votre navigateur si celui-ci en poss\xe8de une (pour Chrome, elle se trouve dans Outils, Outils de d\xe9veloppement, onglet Console). On peut y voir ceci :"}),(0,s.jsx)(r.A,{lang:"sh",children:"Creating Application Cache with manifest http://localhost/le-chemin-vers-votre-manifest\nApplication Cache Checking event\nApplication Cache Downloading event\nApplication Cache Progress event (0 of 3)\n... (1 of 3)\n... (2 of 3)\n... (3 of 3)\nApplication Cache C
1ached event"}),(0,s.jsx)("p",{children:'On y voit en effet tous les \xe9v\xe9nements qui ont lieu lorsque votre navigateur met \xe0 jour son AppCache. Les plus coriaces d\'entre vous souhaiterons pouvoir intercepter ces \xe9v\xe9nements pour pouvoir effectuer des traitements au moment des \xe9v\xe9nements. Ceux-ci seront d\xe9taill\xe9s dans la partie "aller plus loin" de ce tutoriel.'})]}),(0,s.jsxs)("section",{children:[(0,s.jsx)(c.H2,{children:"Mise \xe0 jour du manifest"}),(0,s.jsx)("p",{children:"Attention soyez bien attentif \xe0 pr\xe9sent ! La phrase suivante a de quoi perturber : une fois votre application dans l'AppCache gr\xe2ce au fichier manifest, c'est cette version offline qui a la priorit\xe9 sur la version en ligne ! Pourquoi ? Tout simplement parce que vous lui avez justement dit de le stocker dans le cache ! C'est exactement comme lorsque votre navigateur garde en m\xe9moire une image ou un CSS sur un site, afin de ne pas avoir \xe0 le t\xe9l\xe9charger \xe0 nouveau. Seulement, c'est un peu plus perturbant lorsqu'il est question d'un fichier HTML, je le reconnais... Et donc, comment fait-on pour mettre \xe0 jour le cache avec la version en ligne ?"}),(0,s.jsx)(c.nz,{children:"L'Application Cache sera mis \xe0 jour si :"}),(0,s.jsxs)(c.uQ,{children:[(0,s.jsx)("li",{children:"L'utilisateur vide son cache manuellement,"}),(0,s.jsx)("li",{children:"Le fichier manifest change,"}),(0,s.jsx)("li",{children:"Le cache est mis \xe0 jour avec du code JavaScript."})]}),(0,s.jsx)("p",{children:"Voil\xe0 pourquoi il \xe9tait important d'ins\xe9rer un num\xe9ro de version dans un commentaire ! Il suffit de changer ce num\xe9ro de version pour obliger l'AppCache du client \xe0 se mettre \xe0 jour. Si vous effectuez peu de mises \xe0 jour (dans le cas d'un site vitrine par exemple) c'est la meilleure solution. Par contre, si vous avez besoin que le client soit en permanence \xe0 jour, on pr\xe9f\xe8rera la version JavaScript. Et encore une fois, c'est dans la section \"Aller plus loin\" que \xe7a se passe !"}),(0,s.jsx)(c.nz,{children:"Deux remarques avant de passer \xe0 la suite :"}),(0,s.jsxs)("ul",{children:[(0,s.jsx)("li",{children:"Si le t\xe9l\xe9chargement de l'un des fichiers \xe9choue, alors l'ensemble du t\xe9l\xe9chargement \xe9choue. On peut consid\xe9rer que le manifest liste le contenu d'un \"pack\" non-scindable."}),(0,s.jsx)("li",{children:"Lorsque l'on rafraichit la page apr\xe8s avoir modifi\xe9 le fichier manifest, c'est la page initiale (donc non \xe0 jour) qui s'affiche en premier pendant le t\xe9l\xe9chargement du nouveau manifest. La nouvelle version ne s'affichera qu'au prochain rafraichissement de page (ou si on le fait via JavaScript)."})]})]}),(0,s.jsxs)("section",{children:[(0,s.jsx)(c.H2,{children:"WebApps iPhone et Android"}),(0,s.jsx)(c.nz,{children:"Alors attention, c'est le moment grandiose du tutoriel ! Depuis le d\xe9but on parle d'applications, mais qui sont en fait des sites, mais qui sont quand m\xeame surtout destin\xe9s aux smartphones qui utilisent des applications... Bref c'est plus tr\xe8s clair tout \xe7a ! Alors voil\xe0 qui devrait r\xe9concilier tout le monde : la finalit\xe9 de tout \xe7a est entre autres de transformer un site web en v\xe9ritable application pour mobile. C'est \xe0 dire que notre site-application pourra :"}),(0,s.jsxs)(c.uQ,{children:[(0,s.jsx)("li",{children:"Avoir une icone,"}),(0,s.jsx)("li",{children:"Avoir un \xe9cran de chargement,"}),(0,s.jsx)("li",{children:"S'afficher en plein \xe9cran,"}),(0,s.jsx)("li",{children:"Etre install\xe9e sans passer par l'App Store Apple ni l'Android Market."})]}),(0,s.jsx)("p",{children:"Pas mal non ? Il s'agit en r\xe9alit\xe9 d'un raccourci vers l'URL de votre site web qui sera \xe0 placer sur le bureau du smartphone de l'utilisateur. Un simple favoris devient donc une application \xe0 part enti\xe8re."}),(0,s.jsx)(o.A,{children:"Mais si mes utilisateurs ne passent pas par un App Store, comment vont-ils comprendre qu'il s'agit d'une Web App \xe0 installer via les favoris du navigateur ?"}),(0,s.jsx)("p",{children:"Bien vu. C'est effectivement la grosse faiblesse d'une Web App par rapport \xe0 une application native. Il n'est pas intuitif pour un utilisateur lambda de placer un raccourci web parmi ses ic\xf4nes d'applications habituelles."}),(0,s.jsx)(o.A,{children:"C'est fichu alors ? Les Web Apps ne vont \xeatre destin\xe9es qu'aux geeks de l'HTML5 qui savent faire \xe7a ?"}),(0,s.jsx)("p",{children:"Heureusement \xe7a n'est pas fichu, gr\xe2ce \xe0 plusieurs projets tr\xe8s prometteurs qui permettent de transformer une web app en application native, et donc permettre de les trouver via un App Store et de les installer comme n'importe quelle autre application native. Les plus curieux pourront faire quelques recherches sur Phonegap et Appcelerator Titanium, qui feront l'objet de tutoriels d\xe9di\xe9s sur ce site."}),(0,s.jsx)("p",{children:"Revenons-en \xe0 nos moutons !"}),(0,s.jsxs)("p",{children:["La d\xe9claration des icones, des images de chargement, etc. est contenue dans de
1s balises"," ",(0,s.jsx)(c.Cy,{children:"link"})," et ",(0,s.jsx)(c.Cy,{children:"meta"}),", qui sont \xe0 placer dans le ",(0,s.jsx)(c.Cy,{children:"head"})," du document."]}),(0,s.jsx)("p",{children:"Apple ayant \xe9t\xe9 pionnier dans les Web Apps, il ont choisi de nommer ces param\xe8tres avec des noms propri\xe9taires. Heureusement pour nous, Google a d\xe9cid\xe9 d'utiliser les balises Apple afin de ne pas compliquer encore plus la vie des d\xe9veloppeurs. Par cons\xe9quent, les extraits de code suivants fonctionnent aussi sur Android."}),(0,s.jsx)("p",{children:"Utiliser une icone qui aura un effet de lumi\xe8re sur iPhone :"}),(0,s.jsx)(r.A,{children:'<link rel="apple-touch-icon" href="apple-touch-icon.png" />'}),(0,s.jsx)("p",{children:"D\xe9sactiver l'effet de lumi\xe8re :"}),(0,s.jsx)(r.A,{children:'<link rel="apple-touch-icon-precomposed" href="apple-touch-icon.png" />'}),(0,s.jsx)("p",{children:"Sur iPhone, les icones seront mises au format iPhone, c'est \xe0 dire carr\xe9es aux coins arrondis. Sur Android, il est possible d'utiliser des images transparentes."}),(0,s.jsx)("p",{children:"Afficher son application en plein \xe9cran :"}),(0,s.jsx)(r.A,{children:'<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0" />\n<meta name="apple-mobile-web-app-capable" content="yes" />\n<meta name="apple-touch-fullscreen" content="yes" />'}),(0,s.jsx)("p",{children:"Choisir le style de la barre de statut sur iPhone :"}),(0,s.jsx)(r.A,{children:'<meta name="apple-mobile-web-app-status-bar-style" content="black" />'}),(0,s.jsx)("p",{children:"Utiliser une image de chargement :"}),(0,s.jsx)(r.A,{children:'<link rel="apple-touch-startup-image" href="startup.png" />'}),(0,s.jsx)("p",{children:"Ne poss\xe9dant pas d'iPhone, je ne peux vraiment tester les options sp\xe9cifiques aux iPhones mais je vous invite \xe0 me dire si tout fonctionne bien dans les commentaires. Sur un Android HTC Desire, l'icone (qui est le plus important) s'affiche correctement. Je vous invite d'ailleurs \xe0 nous faire part de vos exp\xe9rimentations sur iPhone via les commentaires sur cette page."})]}),(0,s.jsxs)("section",{children:[(0,s.jsx)(c.H2,{children:"Aller plus loin : le JavaScript"}),(0,s.jsxs)(c.nz,{children:["L'API JavaScript HTML5 poss\xe8de un objet ",(0,s.jsx)(c.Cy,{children:"window.applicationCache"}),". Cet objet permet de :"]}),(0,s.jsxs)(c.uQ,{children:[(0,s.jsx)("li",{children:"Conna\xeetre les \xe9tats du cache,"}),(0,s.jsx)("li",{children:"Attacher des traitements aux \xe9v\xe9nements,"}),(0,s.jsx)("li",{children:"Faire une mise \xe0 jour du cache,"}),(0,s.jsx)("li",{children:"Changer le cache actuel."})]}),(0,s.jsxs)("p",{children:["Voici la classe ",(0,s.jsx)(c.Cy,{children:"ApplicationCache"})," telle qu'elle est donn\xe9e par le WHATWG :"]}),(0,s.jsx)(r.A,{children:"// update status\nconst unsigned short UNCACHED = 0;\nconst unsigned short IDLE = 1;\nconst unsigned short CHECKING = 2;\nconst unsigned short DOWNLOADING = 3;\nconst unsigned short UPDATEREADY = 4;\nconst unsigned short OBSOLETE = 5;\nreadonly attribute unsigned short status;\n\n// updates\nvoid update();\nvoid swapCache();\n\n// events\nattribute Function onchecking;\nattribute Function onerror;\nattribute Function onnoupdate;\nattribute Function ondownloading;\nattribute Function onprogress;\nattribute Function onupdateready;\nattribute Function oncached;\nattribute Function onobsolete;"}),(0,s.jsx)("p",{children:"Ainsi on peut tester le statut actuel :"}),(0,s.jsx)(r.A,{children:"if (webappCache.status == window.applicationCache.UPDATEREADY)"}),(0,s.jsxs)("p",{children:["Ou avec un ",(0,s.jsx)(c.Cy,{children:"switch"})," :"]}),(0,s.jsx)(r.A,{children:"switch (appCache.status) {\n  case appCache.UNCACHED: // UNCACHED == 0\n    return 'UNCACHED'\n    break\n  case appCache.IDLE: // IDLE == 1\n    return 'IDLE'\n    break\n  // ...\n}"}),(0,s.jsx)("p",{children:"Mais il est pr\xe9f\xe9rable de passer par la gestion d'\xe9v\xe9nements pour d\xe9tecter lorsque l'Application Cache change de statut :"}),(0,s.jsx)(r.A,{children:"var webappCache = window.applicationCache\n\nwebappCache.addEventListener('updateready', updateCache, false)\nwebappCache.update(
1)\n\nfunction updateCache() {\n  webappCache.swapCache()\n  alert('Une nouvelle version est disponible.\nVeuillez rafra\xeechir la page pour mettre \xe0 jour.')\n}\n"}),(0,s.jsxs)(c.uQ,{children:[(0,s.jsxs)("li",{children:["La m\xe9thode ",(0,s.jsx)(c.Cy,{children:"update()"})," force le lancement du processus de mise \xe0 jour du cache,"]}),(0,s.jsxs)("li",{children:[(0,s.jsx)(c.Cy,{children:'addEventListener("updateready", updateCache, false)'})," lancera la fonction"," ",(0,s.jsx)(c.Cy,{children:"updateCache"})," d\xe8s que le statut de l'AppCache passera en"," ",(0,s.jsx)(c.Cy,{children:"updateready"}),","]}),(0,s.jsxs)("li",{children:[(0,s.jsx)(c.Cy,{children:"swapCache()"})," permet d'\xe9changer l'ancien cache avec le nouveau cache, ce qui finalise l'op\xe9ration."]})]}),(0,s.jsxs)("p",{children:["Si vous souhaitez trouver de plus amples informations sur le sujet, je vous invite \xe0 vous rendre sur la page"," ",(0,s.jsx)(c.A,{isExternal:!0,href:"http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html#application-cache-api",children:"Application Cache du WHATWG"}),", o\xf9 sont list\xe9s tous les status que peut prendre applicationcache.status, et tous les \xe9v\xe9nements associ\xe9s."]}),(0,s.jsx)("p",{children:"Derni\xe8re petite remarque, il est possible de tester si l'utilisateur est connect\xe9 \xe0 internet ou non avec la propri\xe9t\xe9 :"}),(0,s.jsx)(r.A,{children:"navigator.onLine"}),(0,s.jsxs)("p",{children:["Et voil\xe0 ! Vous avez tous les outils en main pour r\xe9aliser de superbes applications web ! Il y a fort \xe0 parier que ces applications deviendront le standard sur les smartphones d'ici quelques ann\xe9es, puisqu'elles fonctionnent aussi bien sur iPhone qu'Android. Coupl\xe9 avec une balise ",(0,s.jsx)(c.Cy,{children:"canvas"}),", on pourra par exemple jouer \xe0 des jeux vid\xe9os en 3D dans le navigateur, qui seront compatibles avec tous les mobiles ! Plus besoin de s'emb\xeater \xe0 d\xe9velopper plusieurs versions pour chaque OS mobile !"]})]}),(0,s.jsxs)("section",{children:[(0,s.jsx)(c.H2,{children:"Code 
1complet de d\xe9monstration"}),(0,s.jsx)("p",{children:"Cette d\xe9monstration illustre les capacit\xe9 des smartphones (iPhone et Android notamment) \xe0 consid\xe9rer un lien vers une page web comme \xe9tant une application web. En ajoutant cette page en favoris et sur le bureau de votre smartphone, une icone sp\xe9cifique appara\xeetra et vous pourrez acc\xe9der \xe0 la page sans connexion internet si vous l'avez visit\xe9 une fois auparavant."}),(0,s.jsx)(r.A,{lang:"html",children:'<!DOCTYPE html>\n<html manifest="site.manifest">\n  <head>\n    <meta\n      name="viewport"\n      content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"\n    />\n    <meta name="apple-mobile-web-app-capable" content="yes" />\n    <meta name="apple-mobile-web-app-status-bar-style" content="black" />\n    <link rel="apple-touch-icon" href="earth-folder.png" />\n    <link rel="apple-touch-icon-precomposed" href="earth-folder.png" />\n    <link rel="apple-touch-startup-image" href="earth-folder.png" />\n\n    <style type="text/css">\n      #main {\n        width: 900px;\n        margin: auto;\n      }\n    </style>\n  </head>\n  <body>\n    <div id="main">\n      <h1>Cette page est accessible hors ligne</h1>\n      <p>Elle poss\xe8de une icone d\'application pour les smartphones.</p>\n      <img src="earth-folder.png" />\n    </div>\n  </body>\n</html>'}),(0,s.jsxs)("p",{children:["Le fichier ",(0,s.jsx)(c.Cy,{children:"site.manifest"})," :"]}),(0,s.jsx)(r.A,{lang:"sh",children:"CACHE MANIFEST\n\n# Version 0.4\n\nexemple-application-cache-manifest-html5.html\nearth-folder.png"}),(0,s.jsxs)("p",{children:["Le ",(0,s.jsx)(c.Cy,{children:".htaccess"})," :"]}),(0,s.jsx)(r.A,{lang:"sh",children:"AddType text/cache-manifest manifest"})]}),(0,s.jsx)("footer",{children:(0,s.jsx)("p",{children:"Merci d'avoir lu jusqu'ici et \xe0 tr\xe8s bient\xf4t pour de nouveaux tutoriels !"})})]});h.wrappers=e=>(0,s.jsx)(a.A,{children:e});let m=h}},e=>{var n=n=>e(e.s=n);e.O(0,[8916,5422,6379,7351,8593,1940,4339,2503,3526,636,6593,8792],()=>n(96292)),_N_E=e.O()}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.