Skip to content
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

PWA cache auto updater #104

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
edition = "2021"
rust-version = "1.71"


[dependencies]
egui = "0.22.0"
eframe = { version = "0.22.0", default-features = false, features = [
Expand All @@ -28,6 +27,10 @@ env_logger = "0.10"
wasm-bindgen-futures = "0.4"


[build-dependencies]
toml = "0.7.6"
regex = "1.9.4"

[profile.release]
opt-level = 2 # fast and small wasm

Expand Down
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ Change the name of the crate: Chose a good name for your project, and change the
* Change `eframe_template::TemplateApp` to `your_crate::TemplateApp`
* `index.html`
* Change the `<title>eframe template</title>` to `<title>your_crate</title>`. optional.
* `assets/sw.js`
* Change the `'./eframe_template.js'` to `./your_crate.js` (in `filesToCache` array)
* Change the `'./eframe_template_bg.wasm'` to `./your_crate_bg.wasm` (in `filesToCache` array)

### Learning about egui

Expand Down Expand Up @@ -59,7 +56,7 @@ We use [Trunk](https://trunkrs.dev/) to build for web target.
> appending `#dev` to `index.html` will skip this caching, allowing us to load the latest builds during development.

### Web Deploy
1. Just run `trunk build --release`.
1. Just run `sh build.sh`.
2. It will generate a `dist` directory as a "static html" website
3. Upload the `dist` directory to any of the numerous free hosting websites including [GitHub Pages](https://docs.github.com/en/free-pro-team@latest/github/working-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site).
4. we already provide a workflow that auto-deploys our app to GitHub pages if you enable it.
Expand Down
35 changes: 35 additions & 0 deletions assets/sw.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,38 @@ self.addEventListener('fetch', function (e) {
})
);
});

/* Clear cache on version updates */
self.addEventListener("activate", function(e) {
e.waitUntil(
caches.open(cacheName)
.then(cache => {
return cache.match("/version"); // Try to find the stored version in the cache
})
.then(response => {
if (response) {
return response.text();
} else {
return null; // No stored version found in the cache
}
})
.then(storedVersion => {
return fetch("/version")
.then(response => response.text())
.then(backendVersion => {
if (backendVersion !== storedVersion) {
return caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
return caches.delete(cacheName);
})
);
});
}
});
})
.catch(error => {
console.error("Error: ", error);
})
);
});
98 changes: 98 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use regex::Regex;
use std::{
fs::{read_to_string, File},
io::Write,
};
use toml::Value;

fn main() {
let cargo_toml_raw = include_str!("Cargo.toml");
let cargo_toml: Value = toml::from_str(cargo_toml_raw).unwrap();
let name = cargo_toml["package"]["name"].as_str().unwrap();
let version = cargo_toml["package"]["version"].as_str().unwrap();

let old_version = read_to_string("assets/version").ok();

if Some(version.to_string()) != old_version {
write_version(version).unwrap();

let mut assets = get_assets();

let index = insert_files_into_index(&assets);
write_index(&index).unwrap();

assets.append(&mut vec![
"".to_string(),
"index.html".to_string(),
format!("{}.js", name.replace('-', "_")),
format!("{}_bg.wasm", name.replace('-', "_")),
]);

let cache_files = assets
.iter()
.map(|v| format!("'./{}'", v))
.collect::<Vec<String>>();

let sw = replace_sw_cache_files(cache_files);
let sw = replace_cache_name(&sw, name);
write_sw(&sw).unwrap();
}
}

fn get_assets() -> Vec<String> {
std::fs::read_dir("assets")
.unwrap()
.map(|v| v.unwrap().file_name().to_str().unwrap().to_string())
.collect()
}

fn insert_files_into_index(files: &[String]) -> String {
let indexhtml = include_str!("index.html");
let insert_pos = "<!-- Insert assets here -->";
let mut lines: Vec<_> = files
.iter()
.filter(|v| !is_in_index(indexhtml, v))
.map(|v| {
format!(
" <link data-trunk rel=\"copy-file\" href=\"assets/{}\" />",
v
)
})
.collect();
lines.insert(0, insert_pos.to_string());
indexhtml.replace(insert_pos, &lines.join("\n"))
}

fn is_in_index(text: &str, file: &str) -> bool {
let pattern = format!("<link data-trunk rel=\".+?\" href=\"assets/{}\"", file);
Regex::new(&pattern).unwrap().is_match(text)
}

fn replace_sw_cache_files(items: Vec<String>) -> String {
let regex = Regex::new(r"\s+filesToCache\s*=\s*\[[^\]]*\];").unwrap();
let replacement_files = format!(" filesToCache = [ {} ];", items.join(", "));
regex
.replace(include_str!("assets/sw.js"), replacement_files)
.to_string()
}

fn replace_cache_name(text: &str, name: &str) -> String {
let replacement_cache_name = format!(" cacheName = '{}-pwa';", name.replace('_', "-"));
let regex = Regex::new("( cacheName = )(\"|').+?(\"|');").unwrap();
regex.replace(text, replacement_cache_name).to_string()
}

fn write_version(text: &str) -> std::io::Result<()> {
let mut ver = File::create("assets/version").unwrap();
ver.write_all(text.as_bytes())
}

fn write_sw(text: &str) -> std::io::Result<()> {
let mut sw = File::create("assets/sw.js").unwrap();
sw.write_all(text.as_bytes())
}

fn write_index(text: &str) -> std::io::Result<()> {
let mut index = File::create("index.html").unwrap();
index.write_all(text.as_bytes())
}
2 changes: 2 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cargo build --release --target wasm32-unknown-unknown
trunk build --release
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

<link data-trunk rel="icon" href="assets/favicon.ico">


<!-- Insert assets here -->
<link data-trunk rel="copy-file" href="assets/sw.js" />
<link data-trunk rel="copy-file" href="assets/manifest.json" />
<link data-trunk rel="copy-file" href="assets/icon-1024.png" />
Expand Down
Loading