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