Skip to content

Commit 6138f05

Browse files
authored
Merge pull request #1022 from jmerle/service-worker
Replace the App Cache with a Service Worker
2 parents 22d78b5 + 876d9a4 commit 6138f05

28 files changed

+218
-232
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.DS_Store
22
.bundle
3+
log
34
tmp
45
public/assets
56
public/fonts

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
FROM ruby:2.6.0
22

33
ENV LANG=C.UTF-8
4+
ENV ENABLE_SERVICE_WORKER=true
45

56
WORKDIR /devdocs
67

Dockerfile-alpine

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
FROM ruby:2.6.0-alpine
22

33
ENV LANG=C.UTF-8
4+
ENV ENABLE_SERVICE_WORKER=true
45

56
WORKDIR /devdocs
67

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ The web app is all client-side JavaScript, written in [CoffeeScript](http://coff
5959

6060
Many of the code's design decisions were driven by the fact that the app uses XHR to load content directly into the main frame. This includes stripping the original documents of most of their HTML markup (e.g. scripts and stylesheets) to avoid polluting the main frame, and prefixing all CSS class names with an underscore to prevent conflicts.
6161

62-
Another driving factor is performance and the fact that everything happens in the browser. `applicationCache` (which comes with its own set of constraints) and `localStorage` are used to speed up the boot time, while memory consumption is kept in check by allowing the user to pick his/her own set of documentations. The search algorithm is kept simple because it needs to be fast even searching through 100,000 strings.
62+
Another driving factor is performance and the fact that everything happens in the browser. A service worker (which comes with its own set of constraints) and `localStorage` are used to speed up the boot time, while memory consumption is kept in check by allowing the user to pick his/her own set of documentations. The search algorithm is kept simple because it needs to be fast even searching through 100,000 strings.
6363

6464
DevDocs being a developer tool, the browser requirements are high:
6565

6666
* Recent versions of Firefox, Chrome, or Opera
67-
* Safari 9.1+
68-
* Edge 16+
69-
* iOS 10+
67+
* Safari 11.1+
68+
* Edge 17+
69+
* iOS 11.3+
7070

7171
This allows the code to take advantage of the latest DOM and HTML5 APIs and make developing DevDocs a lot more fun!
7272

@@ -156,7 +156,7 @@ Contributions are welcome. Please read the [contributing guidelines](./.github/C
156156
* [Doc Browser](https://github.com/qwfy/doc-browser) is a native Linux app that supports DevDocs docsets
157157
* [GNOME Application](https://github.com/hardpixel/devdocs-desktop) GTK3 application with search integrated in headerbar
158158
* [macOS Application](https://github.com/dteoh/devdocs-macos)
159-
* [Android Application](https://github.com/Merith-TK/devdocs_webapp_kotlin) is a fully working, advanced WebView with AppCache enabled
159+
* [Android Application](https://github.com/Merith-TK/devdocs_webapp_kotlin) is a fully working, advanced WebView
160160

161161
## Copyright / License
162162

assets/javascripts/app/app.coffee

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313

1414
@el = $('._app')
1515
@localStorage = new LocalStorageStore
16-
@appCache = new app.AppCache if app.AppCache.isEnabled()
16+
@serviceWorker = new app.ServiceWorker if app.ServiceWorker.isEnabled()
1717
@settings = new app.Settings
1818
@db = new app.DB()
1919

20+
@settings.initLayout()
21+
2022
@docs = new app.collections.Docs
2123
@disabledDocs = new app.collections.Docs
2224
@entries = new app.collections.Entries
@@ -147,7 +149,7 @@
147149
saveDocs: ->
148150
@settings.setDocs(doc.slug for doc in @docs.all())
149151
@db.migrate()
150-
@appCache?.updateInBackground()
152+
@serviceWorker?.updateInBackground()
151153

152154
welcomeBack: ->
153155
visitCount = @settings.get('count')
@@ -167,14 +169,14 @@
167169
reload: ->
168170
@docs.clearCache()
169171
@disabledDocs.clearCache()
170-
if @appCache then @appCache.reload() else @reboot()
172+
if @serviceWorker then @serviceWorker.reload() else @reboot()
171173
return
172174

173175
reset: ->
174176
@localStorage.reset()
175177
@settings.reset()
176178
@db?.reset()
177-
@appCache?.update()
179+
@serviceWorker?.update()
178180
window.location = '/'
179181
return
180182

@@ -193,9 +195,9 @@
193195
return
194196

195197
indexHost: ->
196-
# Can't load the index files from the host/CDN when applicationCache is
198+
# Can't load the index files from the host/CDN when service worker is
197199
# enabled because it doesn't support caching URLs that use CORS.
198-
@config[if @appCache and @settings.hasDocs() then 'index_path' else 'docs_origin']
200+
@config[if @serviceWorker and @settings.hasDocs() then 'index_path' else 'docs_origin']
199201

200202
onBootError: (args...) ->
201203
@trigger 'bootError'

assets/javascripts/app/appcache.coffee

Lines changed: 0 additions & 42 deletions
This file was deleted.

assets/javascripts/app/config.coffee.erb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ app.config =
1313
version: <%= Time.now.to_i %>
1414
release: <%= Time.now.utc.httpdate.to_json %>
1515
mathml_stylesheet: '<%= App.cdn_origin %>/mathml.css'
16+
service_worker_path: '/service-worker.js'
17+
service_worker_enabled: <%= App.environment == 'production' || ENV['ENABLE_SERVICE_WORKER'] == 'true' %>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
class app.ServiceWorker
2+
$.extend @prototype, Events
3+
4+
@isEnabled: ->
5+
!!navigator.serviceWorker and app.config.service_worker_enabled
6+
7+
constructor: ->
8+
@registration = null
9+
@notifyUpdate = true
10+
11+
navigator.serviceWorker.register(app.config.service_worker_path, {scope: '/'})
12+
.then(
13+
(registration) => @updateRegistration(registration),
14+
(error) -> console.error('Could not register service worker:', error)
15+
)
16+
17+
update: ->
18+
return unless @registration
19+
@notifyUpdate = true
20+
return @registration.update().catch(->)
21+
22+
updateInBackground: ->
23+
return unless @registration
24+
@notifyUpdate = false
25+
return @registration.update().catch(->)
26+
27+
reload: ->
28+
return @updateInBackground().then(() -> app.reboot())
29+
30+
updateRegistration: (registration) ->
31+
@registration = registration
32+
$.on @registration, 'updatefound', @onUpdateFound
33+
return
34+
35+
onUpdateFound: =>
36+
$.off @installingRegistration, 'statechange', @onStateChange() if @installingRegistration
37+
@installingRegistration = @registration.installing
38+
$.on @installingRegistration, 'statechange', @onStateChange
39+
return
40+
41+
onStateChange: =>
42+
if @installingRegistration and @installingRegistration.state == 'installed' and navigator.serviceWorker.controller
43+
@installingRegistration = null
44+
@onUpdateReady()
45+
return
46+
47+
onUpdateReady: ->
48+
@trigger 'updateready' if @notifyUpdate
49+
return

assets/javascripts/app/settings.coffee

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ class app.Settings
1919
'news'
2020
]
2121

22+
LAYOUTS: ['_max-width', '_sidebar-hidden', '_native-scrollbars']
23+
2224
@defaults:
2325
count: 0
2426
hideDisabled: false
@@ -38,6 +40,7 @@ class app.Settings
3840
set: (key, value) ->
3941
@store.set(key, value)
4042
delete @cache[key]
43+
@toggleDark(value) if key == 'dark'
4144
return
4245

4346
del: (key) ->
@@ -63,6 +66,8 @@ class app.Settings
6366
return
6467

6568
setLayout: (name, enable) ->
69+
@toggleLayout(name, enable)
70+
6671
layout = (@store.get('layout') || '').split(' ')
6772
$.arrayDelete(layout, '')
6873

@@ -104,3 +109,28 @@ class app.Settings
104109
@store.reset()
105110
@cache = {}
106111
return
112+
113+
initLayout: ->
114+
@toggleDark(@get('dark') is 1)
115+
@toggleLayout(layout, @hasLayout(layout)) for layout in @LAYOUTS
116+
@initSidebarWidth()
117+
return
118+
119+
toggleDark: (enable) ->
120+
classList = document.documentElement.classList
121+
classList.toggle('_theme-default', !enable)
122+
classList.toggle('_theme-dark', enable)
123+
color = getComputedStyle(document.documentElement).getPropertyValue('--headerBackground').trim()
124+
$('meta[name=theme-color]').setAttribute('content', color)
125+
return
126+
127+
toggleLayout: (layout, enable) ->
128+
classList = document.body.classList
129+
classList.toggle(layout, enable) unless layout is '_sidebar-hidden'
130+
classList.toggle('_overlay-scrollbars', $.overlayScrollbarsEnabled())
131+
return
132+
133+
initSidebarWidth: ->
134+
size = @get('size')
135+
document.documentElement.style.setProperty('--sidebarWidth', size + 'px') if size
136+
return

assets/javascripts/app/update_checker.coffee

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ class app.UpdateChecker
33
@lastCheck = Date.now()
44

55
$.on window, 'focus', @onFocus
6-
app.appCache.on 'updateready', @onUpdateReady if app.appCache
6+
app.serviceWorker?.on 'updateready', @onUpdateReady
77

88
setTimeout @checkDocs, 0
99

1010
check: ->
11-
if app.appCache
12-
app.appCache.update()
11+
if app.serviceWorker
12+
app.serviceWorker.update()
1313
else
1414
ajax
1515
url: $('script[src*="application"]').getAttribute('src')

0 commit comments

Comments
 (0)