| OLD | NEW |
| (Empty) | |
| 1 <h1 class="page_title">Offline First</h1> |
| 2 <div id="pageData-showTOC" class="pageData">true</div> |
| 3 <p> |
| 4 Because internet connections can be flakey or non-existent, |
| 5 you need to consider <em>offline first</em>: |
| 6 write your app as if it has no internet connection. |
| 7 Once your app works offline, |
| 8 add whatever network functionality you need |
| 9 for your app to do more when it’s online. |
| 10 Read on for tips on implementing your offline-enabled app. |
| 11 </p> |
| 12 <h2 id="overview"> Overview </h2> |
| 13 <p> |
| 14 Packaged apps get the following for free: |
| 15 </p> |
| 16 <ul> |
| 17 <li> Your app’s files—all of its JavaScript, |
| 18 CSS, and fonts, plus other resources it needs |
| 19 (such as images)—are <b>already downloaded</b>. </li> |
| 20 <li> Your app can <b>save and optionally sync</b> |
| 21 small amounts of data using the |
| 22 <a href="storage.html">Chrome Storage API</a>. </li> |
| 23 <li> Your app can <b>detect changes in connectivity</b> |
| 24 by listening for |
| 25 <a href="https://developer.mozilla.org/en/Online_and_offline_events">online
and offline events</a>. </li> |
| 26 </ul> |
| 27 <p> |
| 28 But those abilities aren't enough to guarantee that your app |
| 29 will work offline. |
| 30 Your offline-enabled app should follow these rules: |
| 31 </p> |
| 32 <dl> |
| 33 <dt> Use local data whenever possible. </dt> |
| 34 <dd> When using resources from the internet, |
| 35 use <code>XMLHttpRequest</code> to get it, |
| 36 and then save the data locally. |
| 37 You can use the Chrome Storage API, |
| 38 IndexedDB, or |
| 39 Filesystem API to save data locally. </dd> |
| 40 <dt> Separate your app’s UI from its data. </dt> |
| 41 <dd> |
| 42 Separating the UI and data not only |
| 43 improves your app's design and |
| 44 eases the task of enabling offline usage, |
| 45 but also lets you provide other views of the user's data. |
| 46 An MVC framework can help you keep the UI and data separate. |
| 47 </dd> |
| 48 <dt> Assume your app can be closed at any time. </dt> |
| 49 <dd> Save application state |
| 50 (both locally and remotely, when possible) |
| 51 so that users can pick up |
| 52 wherever they left off. </dd> |
| 53 <dt> Test your app thoroughly. </dt> |
| 54 <dd> Make sure your app works well in both |
| 55 <a href="#testing">common and tricky scenarios</a>. </dd> |
| 56 </dl> |
| 57 <h2 id="possibilities"> Security restrictions </h2> |
| 58 <p> |
| 59 Packaged apps are limited |
| 60 in where they can place their resources: |
| 61 </p> |
| 62 <ul> |
| 63 <li> |
| 64 Because local data |
| 65 is visible on the user's machine |
| 66 and can't be securely encrypted, |
| 67 <b>sensitive data must stay on the server</b>. |
| 68 For example, don't store passwords or credit card numbers locally. |
| 69 </li> |
| 70 <li> All <b>JavaScript</b> that the app executes |
| 71 must be in the app's package. |
| 72 It <b>cannot</b> be inline. |
| 73 <br /> |
| 74 <span class="comment"> |
| 75 {PENDING: Should "JavaScript" be "executable code"? |
| 76 What about NaCl and Dart? Anything else -- shaders, e.g.?} |
| 77 </span> |
| 78 </li> |
| 79 <li> All <b>CSS styles</b>, <b>images</b>, and <b>fonts</b> |
| 80 can be initially located |
| 81 either in the app's package |
| 82 or at a remote URL. |
| 83 If the resource is remote, |
| 84 you can't specify it in your HTML. |
| 85 Instead, get the data using <code>XMLHttpRequest</code> |
| 86 (see <a href="app_external.html#external">Referencing external resources</a>
). |
| 87 Then either refer to the data with a blob URL |
| 88 or (better yet) save and then load the data using the |
| 89 <a href="app_storage.html">Filesystem API</a>. |
| 90 <p class="note"> |
| 91 <b>Note:</b> |
| 92 Styles can be inline or in separate <code>.css</code> files. |
| 93 </p> |
| 94 </li> |
| 95 </ul> |
| 96 <p> |
| 97 You can, however, |
| 98 load large media resources such as videos and sounds |
| 99 from external sites. |
| 100 One reason for this exception to the rule |
| 101 is that the <video> and <audio> elements |
| 102 have good fallback behavior when an app |
| 103 has limited or no connectivity. |
| 104 Another reason is that fetching and serving media |
| 105 with <code>XMLHttpRequest</code> and blob URLs |
| 106 currently does not allow |
| 107 streaming or partial buffering. |
| 108 </p> |
| 109 <p> |
| 110 To provide a sandboxed iframe, |
| 111 you can create an <object> tag. |
| 112 Its contents can be remote, |
| 113 but it has no direct access to the Chrome app APIs |
| 114 (see <a href="app_external.html#objecttag">Embed external web pages</a>). |
| 115 </p> |
| 116 <p> |
| 117 Some of the restrictions on packaged apps are enforced by the |
| 118 <a href="app_csp.html">Content Security Policy (CSP)</a> |
| 119 which is always the following and cannot be changed for packaged apps: |
| 120 </p> |
| 121 <pre> |
| 122 default-src 'self'; |
| 123 connect-src *; |
| 124 style-src 'self' blob: data: filesystem: 'unsafe-inline'; |
| 125 img-src 'self' blob: data: filesystem:; |
| 126 frame-src 'self' blob: data: filesystem:; |
| 127 font-src 'self' blob: data: filesystem:; |
| 128 media-src *; |
| 129 </pre> |
| 130 <h2 id="manifest"> Specifying offline_enabled </h2> |
| 131 <p> |
| 132 It is assumed that your app behaves well offline. If it doesn't, you should |
| 133 advertise that fact, so that its launch icon is dimmed when the user is offline. |
| 134 To do so, set <code>offline_enabled</code> to <code>false</code> in the |
| 135 <a href="manifest.html">app manifest file</a>: |
| 136 </p> |
| 137 <pre> |
| 138 { |
| 139 "name": "My app", |
| 140 ... |
| 141 <b>"offline_enabled": false,</b> |
| 142 "manifest_version": 2, |
| 143 ... |
| 144 } |
| 145 </pre> |
| 146 <p class="comment"> |
| 147 {PENDING: should we link to <a href="https://chrome.google.com/webstore/category
/collection/offline_enabled">Offline Apps collection</a>? |
| 148 show a screenshot of how offline apps are highlighted? |
| 149 anything else?} |
| 150 </p> |
| 151 <h2 id="saving-locally"> Saving data locally </h2> |
| 152 <p> |
| 153 The following table shows your options for saving data locally |
| 154 (see also <a href="app_storage.html">Manage Data</a>). |
| 155 </p> |
| 156 <table> |
| 157 <tr> |
| 158 <th> API </th> <th> Best use </th> <th> Notes </th> |
| 159 </tr> |
| 160 <tr> |
| 161 <td> Chrome Storage API </td> |
| 162 <td> Small amounts of string data </td> |
| 163 <td> Great for settings and state. |
| 164 Easy to sync remotely (but you don't have to). |
| 165 Not good for larger amounts of data, |
| 166 due to quotas. |
| 167 </td> |
| 168 </tr> |
| 169 <tr> |
| 170 <td> IndexedDB API </td> |
| 171 <td> Structured data </td> |
| 172 <td> Enables fast searches on data. |
| 173 Use with the |
| 174 <a href="manifest.html#permissions">unlimitedStorage permission</a>. </td
> |
| 175 </tr> |
| 176 <tr> |
| 177 <td> Filesystem API </td> |
| 178 <td> Anything else </td> |
| 179 <td> Provides a sandboxed area where you can store files. |
| 180 Use with the |
| 181 <a href="manifest.html#permissions">unlimitedStorage permission</a>. </td
> |
| 182 </tr> |
| 183 </table> |
| 184 <p class="note"> |
| 185 <b>Note:</b> |
| 186 Packaged apps cannot use Web SQL Database or localStorage. |
| 187 The WebSQL specification has been deprecated for awhile now, |
| 188 and localStorage handles data synchronously |
| 189 (which means it can be slow). |
| 190 The Storage API handles data asynchronously. |
| 191 </p> |
| 192 <h2 id="saving-remotely"> Saving data remotely </h2> |
| 193 <p> |
| 194 In general, how you save data remotely is up to you, |
| 195 but some frameworks and APIs can help |
| 196 (see <a href="app_frameworks.html">MVC Architecture</a>). |
| 197 If you use the Chrome Storage API, |
| 198 then all syncable data |
| 199 is automatically synced |
| 200 whenever the app is online |
| 201 and the user is signed in to Chrome. |
| 202 If the user isn't signed in, |
| 203 they'll be prompted to sign in. |
| 204 However, note that the user's synced data |
| 205 is deleted if the user uninstalls your app. |
| 206 <span class="comment"> |
| 207 {QUESTION: true?} |
| 208 </span> |
| 209 </p> |
| 210 <p> |
| 211 Consider saving users' data for at least |
| 212 30 days after your app is uninstalled, |
| 213 so that users will have a good experience |
| 214 if they reinstall your app. |
| 215 </p> |
| 216 <h2 id="mvc"> Separating UI from data </h2> |
| 217 <p> |
| 218 Using an MVC framework can help you design and implement your app |
| 219 so that the data is completely separate from the app's |
| 220 view on the data. |
| 221 See <a href="app_frameworks.html">MVC Architecture</a> |
| 222 for a list of MVC frameworks. |
| 223 </p> |
| 224 <p> |
| 225 If your app talks to a custom server, |
| 226 the server should give you data, |
| 227 not chunks of HTML. |
| 228 Think in terms of RESTful APIs. |
| 229 </p> |
| 230 <p> |
| 231 Once your data is separate from your app, |
| 232 it's much easier to provide alternate views of the data. |
| 233 For example, |
| 234 you might provide a website view of any public data. |
| 235 Not only can a website view |
| 236 be useful when your user is away from Chrome, |
| 237 but it can enable search engines to find the data. |
| 238 </p> |
| 239 <h2 id="testing"> Testing </h2> |
| 240 <p> |
| 241 Make sure your app works well under the following circumstances: |
| 242 </p> |
| 243 <ul> |
| 244 <li> |
| 245 The app is installed, and then immediately goes offline. |
| 246 In other words, the first use of the app is offline. |
| 247 </li> |
| 248 <li> |
| 249 The app is installed on one computer |
| 250 and then synced to another. |
| 251 </li> |
| 252 <li> |
| 253 The app is uninstalled and then immediately installed again. |
| 254 </li> |
| 255 <li> |
| 256 The app is running on two computers at the same time, |
| 257 with the same profile. |
| 258 The app must behave reasonably |
| 259 when one computer goes offline, |
| 260 the user does a bunch of stuff on that computer, |
| 261 and then the computer comes online again. |
| 262 </li> |
| 263 <li> |
| 264 The app has intermittent connectivity, |
| 265 switching often between online and offline. |
| 266 </li> |
| 267 </ul> |
| 268 <p> |
| 269 Also make sure that the app saves <b>no sensitive user data</b> |
| 270 (such as passwords) on the user's machine. |
| 271 </p> |
| 272 <p class="backtotop"><a href="#top">Back to top</a></p> |
| OLD | NEW |