| OLD | NEW |
| 1 <h1>Offline First</h1> | 1 <h1>Offline First</h1> |
| 2 | 2 |
| 3 | 3 |
| 4 <p> | 4 <p> |
| 5 Because internet connections can be flakey or non-existent, | 5 Because internet connections can be flakey or non-existent, |
| 6 you need to consider <em>offline first</em>: | 6 you need to consider <em>offline first</em>: |
| 7 write your app as if it has no internet connection. | 7 write your app as if it has no internet connection. |
| 8 Once your app works offline, | 8 Once your app works offline, |
| 9 add whatever network functionality you need | 9 add whatever network functionality you need |
| 10 for your app to do more when it’s online. | 10 for your app to do more when it’s online. |
| 11 Read on for tips on implementing your offline-enabled app. | 11 Read on for tips on implementing your offline-enabled app. |
| 12 </p> | 12 </p> |
| 13 | 13 |
| 14 <h2 id="overview"> Overview </h2> | 14 <h2 id="overview"> Overview </h2> |
| 15 | 15 |
| 16 <p> | 16 <p> |
| 17 Chrome Apps get the following for free: | 17 Chrome Apps get the following for free: |
| 18 </p> | 18 </p> |
| 19 | 19 |
| 20 <ul> | 20 <ul> |
| 21 <li> Your app’s files—all of its JavaScript, | 21 <li> Your app’s files—all of its JavaScript, |
| 22 CSS, and fonts, plus other resources it needs | 22 CSS, and fonts, plus other resources it needs |
| 23 (such as images)—are <b>already downloaded</b>. </li> | 23 (such as images)—are <b>already downloaded</b>. </li> |
| 24 <li> Your app can <b>save and optionally sync</b> | 24 <li> Your app can <b>save and optionally sync</b> |
| 25 small amounts of data using the | 25 small amounts of data using the |
| 26 <a href="storage.html">Chrome Storage API</a>. </li> | 26 <a href="storage">Chrome Storage API</a>. </li> |
| 27 <li> Your app can <b>detect changes in connectivity</b> | 27 <li> Your app can <b>detect changes in connectivity</b> |
| 28 by listening for | 28 by listening for |
| 29 <a href="https://developer.mozilla.org/en/Online_and_offline_events">online
and offline events</a>. </li> | 29 <a href="https://developer.mozilla.org/en/Online_and_offline_events">online
and offline events</a>. </li> |
| 30 </ul> | 30 </ul> |
| 31 | 31 |
| 32 <p> | 32 <p> |
| 33 But those abilities aren't enough to guarantee that your app | 33 But those abilities aren't enough to guarantee that your app |
| 34 will work offline. | 34 will work offline. |
| 35 Your offline-enabled app should follow these rules: | 35 Your offline-enabled app should follow these rules: |
| 36 </p> | 36 </p> |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 It <b>cannot</b> be inline. | 85 It <b>cannot</b> be inline. |
| 86 <br /> | 86 <br /> |
| 87 </li> | 87 </li> |
| 88 <li> All <b>CSS styles</b>, <b>images</b>, and <b>fonts</b> | 88 <li> All <b>CSS styles</b>, <b>images</b>, and <b>fonts</b> |
| 89 can be initially located | 89 can be initially located |
| 90 either in the app's package | 90 either in the app's package |
| 91 or at a remote URL. | 91 or at a remote URL. |
| 92 If the resource is remote, | 92 If the resource is remote, |
| 93 you can't specify it in your HTML. | 93 you can't specify it in your HTML. |
| 94 Instead, get the data using <code>XMLHttpRequest</code> | 94 Instead, get the data using <code>XMLHttpRequest</code> |
| 95 (see <a href="app_external.html#external">Referencing external resources</a>
). | 95 (see <a href="app_external#external">Referencing external resources</a>). |
| 96 Then either refer to the data with a blob URL | 96 Then either refer to the data with a blob URL |
| 97 or (better yet) save and then load the data using the | 97 or (better yet) save and then load the data using the |
| 98 <a href="app_storage.html">Filesystem API</a>. | 98 <a href="app_storage">Filesystem API</a>. |
| 99 | 99 |
| 100 <p class="note"> | 100 <p class="note"> |
| 101 <b>Note:</b> | 101 <b>Note:</b> |
| 102 Styles can be inline or in separate <code>.css</code> files. | 102 Styles can be inline or in separate <code>.css</code> files. |
| 103 </p> | 103 </p> |
| 104 | 104 |
| 105 </li> | 105 </li> |
| 106 </ul> | 106 </ul> |
| 107 | 107 |
| 108 <p> | 108 <p> |
| 109 You can, however, | 109 You can, however, |
| 110 load large media resources such as videos and sounds | 110 load large media resources such as videos and sounds |
| 111 from external sites. | 111 from external sites. |
| 112 One reason for this exception to the rule | 112 One reason for this exception to the rule |
| 113 is that the <video> and <audio> elements | 113 is that the <video> and <audio> elements |
| 114 have good fallback behavior when an app | 114 have good fallback behavior when an app |
| 115 has limited or no connectivity. | 115 has limited or no connectivity. |
| 116 Another reason is that fetching and serving media | 116 Another reason is that fetching and serving media |
| 117 with <code>XMLHttpRequest</code> and blob URLs | 117 with <code>XMLHttpRequest</code> and blob URLs |
| 118 currently does not allow | 118 currently does not allow |
| 119 streaming or partial buffering. | 119 streaming or partial buffering. |
| 120 </p> | 120 </p> |
| 121 | 121 |
| 122 <p> | 122 <p> |
| 123 To provide a sandboxed iframe, | 123 To provide a sandboxed iframe, |
| 124 you can create an <webview> tag. | 124 you can create an <webview> tag. |
| 125 Its contents can be remote, | 125 Its contents can be remote, |
| 126 but it has no direct access to the Chrome app APIs | 126 but it has no direct access to the Chrome app APIs |
| 127 (see <a href="app_external.html#webview">Embed external web pages</a>). | 127 (see <a href="app_external#webview">Embed external web pages</a>). |
| 128 </p> | 128 </p> |
| 129 | 129 |
| 130 <p> | 130 <p> |
| 131 Some of the restrictions on Chrome Apps are enforced by the | 131 Some of the restrictions on Chrome Apps are enforced by the |
| 132 <a href="contentSecurityPolicy.html">Content Security Policy (CSP)</a> | 132 <a href="contentSecurityPolicy">Content Security Policy (CSP)</a> |
| 133 which is always the following and cannot be changed for Chrome Apps: | 133 which is always the following and cannot be changed for Chrome Apps: |
| 134 </p> | 134 </p> |
| 135 | 135 |
| 136 <pre> | 136 <pre> |
| 137 default-src 'self'; | 137 default-src 'self'; |
| 138 connect-src *; | 138 connect-src *; |
| 139 style-src 'self' blob: data: filesystem: 'unsafe-inline'; | 139 style-src 'self' blob: data: filesystem: 'unsafe-inline'; |
| 140 img-src 'self' blob: data: filesystem:; | 140 img-src 'self' blob: data: filesystem:; |
| 141 frame-src 'self' blob: data: filesystem:; | 141 frame-src 'self' blob: data: filesystem:; |
| 142 font-src 'self' blob: data: filesystem:; | 142 font-src 'self' blob: data: filesystem:; |
| 143 media-src *; | 143 media-src *; |
| 144 </pre> | 144 </pre> |
| 145 | 145 |
| 146 <h2 id="manifest"> Specifying offline_enabled </h2> | 146 <h2 id="manifest"> Specifying offline_enabled </h2> |
| 147 | 147 |
| 148 <p> | 148 <p> |
| 149 It is assumed that your app behaves well offline. If it doesn't, you should | 149 It is assumed that your app behaves well offline. If it doesn't, you should |
| 150 advertise that fact, so that its launch icon is dimmed when the user is offline. | 150 advertise that fact, so that its launch icon is dimmed when the user is offline. |
| 151 To do so, set <code>offline_enabled</code> to <code>false</code> in the | 151 To do so, set <code>offline_enabled</code> to <code>false</code> in the |
| 152 <a href="manifest.html">app manifest file</a>: | 152 <a href="manifest">app manifest file</a>: |
| 153 </p> | 153 </p> |
| 154 | 154 |
| 155 <pre data-filename="manifest.json"> | 155 <pre data-filename="manifest.json"> |
| 156 { | 156 { |
| 157 "name": "My app", | 157 "name": "My app", |
| 158 ... | 158 ... |
| 159 <b>"offline_enabled": false,</b> | 159 <b>"offline_enabled": false,</b> |
| 160 ... | 160 ... |
| 161 } | 161 } |
| 162 </pre> | 162 </pre> |
| 163 | 163 |
| 164 <h2 id="saving-locally"> Saving data locally </h2> | 164 <h2 id="saving-locally"> Saving data locally </h2> |
| 165 | 165 |
| 166 <p> | 166 <p> |
| 167 The following table shows your options for saving data locally | 167 The following table shows your options for saving data locally |
| 168 (see also <a href="app_storage.html">Manage Data</a>). | 168 (see also <a href="app_storage">Manage Data</a>). |
| 169 </p> | 169 </p> |
| 170 | 170 |
| 171 <table class="simple"> | 171 <table class="simple"> |
| 172 <tr> | 172 <tr> |
| 173 <th> API </th> <th> Best use </th> <th> Notes </th> | 173 <th> API </th> <th> Best use </th> <th> Notes </th> |
| 174 </tr> | 174 </tr> |
| 175 <tr> | 175 <tr> |
| 176 <td> Chrome Storage API </td> | 176 <td> Chrome Storage API </td> |
| 177 <td> Small amounts of string data </td> | 177 <td> Small amounts of string data </td> |
| 178 <td> Great for settings and state. | 178 <td> Great for settings and state. |
| 179 Easy to sync remotely (but you don't have to). | 179 Easy to sync remotely (but you don't have to). |
| 180 Not good for larger amounts of data, | 180 Not good for larger amounts of data, |
| 181 due to quotas. | 181 due to quotas. |
| 182 </td> | 182 </td> |
| 183 </tr> | 183 </tr> |
| 184 <tr> | 184 <tr> |
| 185 <td> IndexedDB API </td> | 185 <td> IndexedDB API </td> |
| 186 <td> Structured data </td> | 186 <td> Structured data </td> |
| 187 <td> Enables fast searches on data. | 187 <td> Enables fast searches on data. |
| 188 Use with the | 188 Use with the |
| 189 <a href="declare_permissions.html">unlimitedStorage permission</a>. </td> | 189 <a href="declare_permissions">unlimitedStorage permission</a>. </td> |
| 190 </tr> | 190 </tr> |
| 191 <tr> | 191 <tr> |
| 192 <td> Filesystem API </td> | 192 <td> Filesystem API </td> |
| 193 <td> Anything else </td> | 193 <td> Anything else </td> |
| 194 <td> Provides a sandboxed area where you can store files. | 194 <td> Provides a sandboxed area where you can store files. |
| 195 Use with the | 195 Use with the |
| 196 <a href="declare_permissions.html">unlimitedStorage permission</a>. </td> | 196 <a href="declare_permissions">unlimitedStorage permission</a>. </td> |
| 197 </tr> | 197 </tr> |
| 198 </table> | 198 </table> |
| 199 | 199 |
| 200 <p class="note"> | 200 <p class="note"> |
| 201 <b>Note:</b> | 201 <b>Note:</b> |
| 202 Packaged apps cannot use Web SQL Database or localStorage. | 202 Packaged apps cannot use Web SQL Database or localStorage. |
| 203 The WebSQL specification has been deprecated for awhile now, | 203 The WebSQL specification has been deprecated for awhile now, |
| 204 and localStorage handles data synchronously | 204 and localStorage handles data synchronously |
| 205 (which means it can be slow). | 205 (which means it can be slow). |
| 206 The Storage API handles data asynchronously. | 206 The Storage API handles data asynchronously. |
| 207 </p> | 207 </p> |
| 208 | 208 |
| 209 | 209 |
| 210 <h2 id="saving-remotely"> Saving data remotely </h2> | 210 <h2 id="saving-remotely"> Saving data remotely </h2> |
| 211 | 211 |
| 212 <p> | 212 <p> |
| 213 In general, how you save data remotely is up to you, | 213 In general, how you save data remotely is up to you, |
| 214 but some frameworks and APIs can help | 214 but some frameworks and APIs can help |
| 215 (see <a href="app_frameworks.html">MVC Architecture</a>). | 215 (see <a href="app_frameworks">MVC Architecture</a>). |
| 216 If you use the Chrome Storage API, | 216 If you use the Chrome Storage API, |
| 217 then all syncable data | 217 then all syncable data |
| 218 is automatically synced | 218 is automatically synced |
| 219 whenever the app is online | 219 whenever the app is online |
| 220 and the user is signed in to Chrome. | 220 and the user is signed in to Chrome. |
| 221 If the user isn't signed in, | 221 If the user isn't signed in, |
| 222 they'll be prompted to sign in. | 222 they'll be prompted to sign in. |
| 223 However, note that the user's synced data | 223 However, note that the user's synced data |
| 224 is deleted if the user uninstalls your app. | 224 is deleted if the user uninstalls your app. |
| 225 <span class="comment"> | 225 <span class="comment"> |
| 226 {QUESTION: true?} | 226 {QUESTION: true?} |
| 227 </span> | 227 </span> |
| 228 </p> | 228 </p> |
| 229 | 229 |
| 230 <p> | 230 <p> |
| 231 Consider saving users' data for at least | 231 Consider saving users' data for at least |
| 232 30 days after your app is uninstalled, | 232 30 days after your app is uninstalled, |
| 233 so that users will have a good experience | 233 so that users will have a good experience |
| 234 if they reinstall your app. | 234 if they reinstall your app. |
| 235 </p> | 235 </p> |
| 236 | 236 |
| 237 | 237 |
| 238 <h2 id="mvc"> Separating UI from data </h2> | 238 <h2 id="mvc"> Separating UI from data </h2> |
| 239 | 239 |
| 240 <p> | 240 <p> |
| 241 Using an MVC framework can help you design and implement your app | 241 Using an MVC framework can help you design and implement your app |
| 242 so that the data is completely separate from the app's | 242 so that the data is completely separate from the app's |
| 243 view on the data. | 243 view on the data. |
| 244 See <a href="app_frameworks.html">MVC Architecture</a> | 244 See <a href="app_frameworks">MVC Architecture</a> |
| 245 for a list of MVC frameworks. | 245 for a list of MVC frameworks. |
| 246 </p> | 246 </p> |
| 247 | 247 |
| 248 <p> | 248 <p> |
| 249 If your app talks to a custom server, | 249 If your app talks to a custom server, |
| 250 the server should give you data, | 250 the server should give you data, |
| 251 not chunks of HTML. | 251 not chunks of HTML. |
| 252 Think in terms of RESTful APIs. | 252 Think in terms of RESTful APIs. |
| 253 </p> | 253 </p> |
| 254 | 254 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 294 switching often between online and offline. | 294 switching often between online and offline. |
| 295 </li> | 295 </li> |
| 296 </ul> | 296 </ul> |
| 297 | 297 |
| 298 <p> | 298 <p> |
| 299 Also make sure that the app saves <b>no sensitive user data</b> | 299 Also make sure that the app saves <b>no sensitive user data</b> |
| 300 (such as passwords) on the user's machine. | 300 (such as passwords) on the user's machine. |
| 301 </p> | 301 </p> |
| 302 | 302 |
| 303 <p class="backtotop"><a href="#top">Back to top</a></p> | 303 <p class="backtotop"><a href="#top">Back to top</a></p> |
| OLD | NEW |