-
Notifications
You must be signed in to change notification settings - Fork 1.7k
WIP: Make available offline using Service Worker #571
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This also opens up the possibility of implementing search in a different way than #472 does it. Since all the pages are in the cache, we can implement it client-side only, though we would have to see what impact that would have on the memory and CPU usage. The rough idea would be to run the following steps lazily (e.g. when the search field is focused, after the chapters are precached, inside a
|
I've looked into how much space will the chapters occupy in cache:
|
This is great! The only thing I've found is the clipboard seems broken in offline mode. |
Oh, another thing I am seeing is on this branch, every time I click on a sidebar chapter, the sidebar closes. |
I have a couple questions regarding caching and how long the service worker persists for:
|
When you visit again, you will receive a new
Yes. I've just published this over at https://sorin-davidoi.github.io/mdBook/ for easier testing. Load the page, refresh and then go offline (Chrome Dev Tools -> Network tab -> Offline). You should be able to see all the content. |
I just had a look at Chrome's audit tool and it mentioned something about the "service worker does not serve the manifest's start_url". Other than that it seems to work quite well.
@sorin-davidoi is @projektir's problem something to do with local storage not persisting the sidebar's state properly? |
Yes, we should also have a
Not sure, since I can't replicate it. Maybe his browser window was not wide enough? |
@Michael-F-Bryan I'm trying to refactor this to solve the following:
This would mean that we will have a guarantee - if the Service Worker is installed, everything is cached, and we can display that to the user (something we can't do right now). This requires that we need to insert the assets into the Service Worker the same way we insert the chapters (with revision information). My idea is to store all the assets in Rust and inject them in the page like we do with const MATHJAX_URL: &'static str = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML";
const CLIPBOARD_URL: &'static str = "https://cdn.jsdelivr.net/clipboard.js/1.6.1/clipboard.min.js";
const GOOGLE_ANALYTICS_URL: &'static str = "https://www.google-analytics.com/analytics.js";
const INITIAL_CSS:[&'static str; 7] = [
"book.css",
"https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800",
"https://fonts.googleapis.com/css?family=Source+Code+Pro:500",
"https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css",
"highlight.css",
"tomorrow-night.css",
"ayu-highlight.css",
];
const INITIAL_JS:[&'static str; 2] = [
"highlight.js",
"book.js",
];
const PLAYPEN_EDITOR_JS:[&'static str; 5] = [
"editor.js",
"ace.js",
"mode-rust.js",
"theme-dawn.js",
"theme-tomorrow_night.js",
]; This way, we can compute their revision (checksum) when building the book. However, we can't compute the revision information of remote assets (we don't need it for files which are versioned, like What is your opinion on not relying on CDNs and serving the assets locally? Looking at #511 it seems like the main reason for using them is caching, which would be resolved with the Service Worker. |
Yes please! A lot of people have asked about serving all assets locally and making it possible to view when not connected to the internet. Making the entire thing self-contained is also pretty important for people who want to package I really want to go through the HTML renderer and rewrite large chunks of the internals. Over time that section of the codebase has "grown organically" as new features get added and different people work on it, and the technical debt is starting to make things brittle and hard to maintain. A better dependency and asset management system will probably just "fall out" when we go through and restructure everything. |
@Michael-F-Bryan Perfect, what about I split this PR into three?
|
How were you planning to move the assets? As well as the standard use case when someone doesn't have access to the internet, you may want to skim through #46 and #271 to give you a better idea for what Debian (and other organisations with similar requirements) are looking for. In particular, @tjis mentioned:
|
So, our external dependencies are (as far as I can tell):
My first thought was to hard-code the paths, but it seems that reading them from the environment (falling back to the local assets) might be a better solution? |
I had something similar in mind. Cargo lets a build script set environment variables during the compilation process, which you can pair with the This approach lets the people packaging Ideally all dependencies should be embedded in the |
Closing for now. Will probably open PRs with the issues mentioned above before taking another shot at this. |
@Michael-F-Bryan Does this mean that the build script pulls all those external deps from the CDNs when building? Or do we manually fetch the assets and put them in some folder? |
@sorin-davidoi is this because you need to actually hit the (chapter) page for those assets to load and go into the cache? So you won't actually cache a chapter until you visit it? |
To be honest I don't remember 😞 |
I believe the current state of affairs is that we've vendored a copy of the files in the
That sounds about right. It's been a while since the original PR though, so there's a good chance the story around service workers has changed or this could be implemented differently. |
nice. |
There’s still a couple of bugs with #1000 but I believe it’s getting there. |
Help Needed! #1000 seems to be working pretty well from what i can see so far, I just need some feedback now. The PR allows the rust book to be read offline, new changes will still take affect. You can just navigate to https://jason-williams.co.uk/book/ and try it out, then leave any feedback in the issue above. |
This PR introduces a Service Worker in order to dynamically cache the assets (only what the page requests, so respecting all the flags) and statically precache the chapters. The end result is that the resulting book would be available offline in supported browsers - Chrome (desktop and Android), Opera and Firefox (desktop and Android), for now, Edge and Safari later. As a bonus, if the book is used while offline, Google Analytics events are also cached and sent out when the user is back online.
Things intentionally left unaddressed (waiting for feedback):
A small caveat is that the book is not available offline after the first-page load, but only after the second one. This is because on first load we precache the chapters, but the assets will be cached only when they are requested the second time.
Alongside supporting offline usage, this will also introduce a massive performance boost on second visits, since there is no need to hit the network for any of the assets.
The Service Worker is not installed during development (same procedure as for Google Analytics).
If you want to test this:
offline-support = true
to the[output.html]
sectionbook.js
Closes #546.