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