Make service worker opt-in in development

pull/1022/head
Jasper van Merle 6 years ago
parent 0cd1527143
commit 576f32dae1

@ -1,6 +1,7 @@
FROM ruby:2.6.0
ENV LANG=C.UTF-8
ENV ENABLE_SERVICE_WORKER=true
WORKDIR /devdocs

@ -1,6 +1,7 @@
FROM ruby:2.6.0-alpine
ENV LANG=C.UTF-8
ENV ENABLE_SERVICE_WORKER=true
WORKDIR /devdocs

@ -14,3 +14,4 @@ app.config =
release: <%= Time.now.utc.httpdate.to_json %>
mathml_stylesheet: '<%= App.cdn_origin %>/mathml.css'
service_worker_path: '/service-worker.js'
service_worker_enabled: <%= App.environment == 'production' || !ENV["ENABLE_SERVICE_WORKER"].nil? %>

@ -2,7 +2,7 @@ class app.ServiceWorker
$.extend @prototype, Events
@isEnabled: ->
!!navigator.serviceWorker
!!navigator.serviceWorker and app.config.service_worker_enabled
constructor: ->
@registration = null

@ -5,7 +5,6 @@ class app.Settings
'manualUpdate'
'fastScroll'
'arrowScroll'
'bypassCache'
'docs'
'dark'
'layout'
@ -92,11 +91,6 @@ class app.Settings
@set 'size', value
return
setBypassCache: (value) ->
@set 'bypassCache', value
app.serviceWorker?.updateInBackground()
return
dump: ->
@store.dump()

@ -44,7 +44,12 @@ canICloseTheTab = ->
if app.ServiceWorker.isEnabled()
""" Yes! Even offline, you can open a new tab, go to <a href="//devdocs.io">devdocs.io</a>, and everything will work as if you were online (provided you installed all the documentations you want to use beforehand). """
else
""" No. Service Workers aren't available in your browser (or are disabled), so loading <a href="//devdocs.io">devdocs.io</a> offline won't work.<br>
reason = "aren't available in your browser (or are disabled)"
if app.config.env != 'production'
reason = "are disabled in your development instance of DevDocs (enable them by setting the ENABLE_SERVICE_WORKERS environment variable)"
""" No. Service Workers #{reason}, so loading <a href="//devdocs.io">devdocs.io</a> offline won't work.<br>
The current tab will continue to function even when you go offline (provided you installed all the documentations beforehand). """
app.templates.offlineDoc = (doc, status) ->

@ -8,7 +8,7 @@ app.templates.intro = """
<p>Thanks for downloading DevDocs. Here are a few things you should know:
<ol class="_intro-list">
<li>Your local version of DevDocs won't self-update. Unless you're modifying the code,
I&nbsp;recommend using the hosted version at <a href="https://devdocs.io">devdocs.io</a>.
we&nbsp;recommend using the hosted version at <a href="https://devdocs.io">devdocs.io</a>.
<li>Run <code>thor docs:list</code> to see all available documentations.
<li>Run <code>thor docs:download &lt;name&gt;</code> to download documentations.
<li>Run <code>thor docs:download --installed</code> to update all downloaded documentations.

@ -15,10 +15,6 @@ app.templates.settingsPage = (settings) -> """
<input type="checkbox" form="settings" name="layout" value="_sidebar-hidden"#{if settings['_sidebar-hidden'] then ' checked' else ''}>Automatically hide and show the sidebar
<small>Tip: drag the edge of the sidebar to resize it.</small>
</label>
<label class="_settings-label">
<input type="checkbox" form="settings" name="bypassCache" value="1"#{if settings.bypassCache then ' checked' else ''}>Bypass Service Worker cache
<small>When this is checked, the Service Worker will always fetch the latest version of requested files. Useful when making changes to the DevDocs source code.</small>
</label>
</div>
</div>

@ -14,7 +14,6 @@ class app.views.SettingsPage extends app.View
settings.dark = app.settings.get('dark')
settings.smoothScroll = !app.settings.get('fastScroll')
settings.arrowScroll = app.settings.get('arrowScroll')
settings.bypassCache = app.settings.get('bypassCache')
settings[layout] = app.settings.hasLayout(layout) for layout in app.settings.LAYOUTS
settings
@ -33,10 +32,6 @@ class app.views.SettingsPage extends app.View
app.settings.set('fastScroll', !enable)
return
toggleBypassCache: (enable) ->
app.settings.setBypassCache(!!enable)
return
toggle: (name, enable) ->
app.settings.set(name, enable)
return
@ -80,8 +75,6 @@ class app.views.SettingsPage extends app.View
@toggleSmoothScroll input.checked
when 'import'
@import input.files[0], input
when 'bypassCache'
@toggleBypassCache input.checked
else
@toggle input.name, input.checked
return

@ -2,8 +2,6 @@ Adding a documentation may look like a daunting task but once you get the hang o
**Note:** please read the [contributing guidelines](../.github/CONTRIBUTING.md) before submitting a new documentation.
**Note:** when editing any of the files in the `assets` directory or the `public` directory, you'll have to bypass the service worker cache. To do this, go to the Preferences page on your local instance of DevDocs, check "Bypass Service Worker cache" and refresh the page.
1. Create a subclass of `Docs::UrlScraper` or `Docs::FileScraper` in the `lib/docs/scrapers/` directory. Its name should be the [PascalCase](http://api.rubyonrails.org/classes/String.html#method-i-camelize) equivalent of the filename (e.g. `my_doc``MyDoc`)
2. Add the appropriate class attributes and filter options (see the [Scraper Reference](./scraper-reference.md) page).
3. Check that the scraper is listed in `thor docs:list`.

@ -205,8 +205,28 @@ class App < Sinatra::Application
].compact
end
def bypass_cache?
!memoized_cookies['bypassCache'].nil?
def service_worker_cache_name
# Returns the digest of the last modified asset
# When a manifest exist, this digest is only calculated once based on the asset manifest because it never changes without a server restart
# If a manifest does not exist, it is calculated every time this method is called because the assets can change while the server is running
if File.exist?(App.assets_manifest_path)
return @@service_worker_cache_name ||=
Sprockets::Manifest
.new(nil, App.assets_manifest_path)
.files
.values
.sort_by {|file| file["mtime"]}
.reverse
.first["digest"]
else
last_modified_file = App.sprockets
.each_file
.to_a
.reject {|file| file.start_with?(App.docs_path)}
.max_by {|file| File.mtime(file)}
return App.sprockets.pack_base64digest(App.sprockets.file_digest(last_modified_file))
end
end
def redirect_via_js(path)

@ -1,6 +1,6 @@
<%# Use the hash of the application.js file as cache name or 'app' if not running in production %>
<%# This ensures that the cache is always updated if the hash of the application.js file changes %>
const cacheName = '<%= javascript_path('application', asset_host: false).scan(/application-([^\.]+)\.js/).last&.first || 'app' %>';
<%# The name of the cache to store responses in %>
<%# If the cache name changes DevDocs is assumed to be updated %>
const cacheName = '<%= service_worker_cache_name %>';
<%# Url's to cache when the service worker is installed %>
const urlsToCache = [
@ -32,9 +32,6 @@ self.addEventListener('activate', event => {
<%# Handle HTTP requests %>
self.addEventListener('fetch', event => {
event.respondWith((async () => {
<% if bypass_cache? %>
return fetch(event.request);
<% else %>
const cachedResponse = await caches.match(event.request);
if (cachedResponse) return cachedResponse;
@ -53,6 +50,5 @@ self.addEventListener('fetch', event => {
throw err;
}
<% end %>
})());
});

Loading…
Cancel
Save