diff --git a/assets/bun.lockb b/assets/bun.lockb index e0cd4ca..5ffcd96 100755 Binary files a/assets/bun.lockb and b/assets/bun.lockb differ diff --git a/assets/js/serviceworker.js b/assets/js/serviceworker.js index 6961ca8..cce1dc1 100644 --- a/assets/js/serviceworker.js +++ b/assets/js/serviceworker.js @@ -1,14 +1,17 @@ -"use strict"; +// Make imported functions be considered macros +// They're executed at bundle time and only their results are emited in the resulting bundle. +// Not sure how data is handled, but it likely is inlined as is. +// Supports async functions, where results are awaited on. +// https://bun.sh/docs/bundler/macros +import { cacheMacro } from "./serviceworker/cache_manifest.js" with { type: "macro" }; -const version = "20241231"; -const staticCacheName = "static-" + version; +const cache = cacheMacro(); +const staticCacheName = "static-" + cache.hash; const cacheList = [staticCacheName]; async function updateStaticCache() { - let response = await fetch("/cache"); - let json = await response.json(); let staticCache = await caches.open(staticCacheName); - staticCache.addAll(json.static); + staticCache.addAll(cache.cache); } async function clearOldCaches() { diff --git a/assets/js/serviceworker/cache_manifest.js b/assets/js/serviceworker/cache_manifest.js new file mode 100644 index 0000000..14da887 --- /dev/null +++ b/assets/js/serviceworker/cache_manifest.js @@ -0,0 +1,52 @@ +export async function cacheMacro() { + let manifest = await cache_manifest_or_default(); + + console.log(manifest); + + let base = [ + "assets/video.js", + "assets/app.css", + "assets/app.js", + "images/signee.png", + "images/pfeil.png", + "images/avatar.jpg", + "font/noway-regular-webfont.woff", + "font/noway-regular-webfont.woff2", + "font/Virgil.woff2", + ]; + + let cache = base.map((key) => { + let digested = manifest.latest[key]; + if (!digested) + return { + key: key, + sha512: null, + path: "/" + key, + }; + return { + key: digested, + sha512: manifest.digests[key]?.sha512, + path: "/" + digested + "?vsn=d", + }; + }); + + let hash = cache + .flatMap((entry) => { + if (!entry.sha512) return []; + return [entry.sha512]; + }) + .reduce((hasher, sha) => hasher.update(sha), new Bun.CryptoHasher("sha512")) + .digest("base64"); + + return { + cache: cache.map((entry) => entry.path), + hash: hash, + }; +} + +async function cache_manifest_or_default() { + return import("./../../../priv/static/cache_manifest.json").catch((_err) => ({ + latest: [], + digests: [], + })); +} diff --git a/config/config.exs b/config/config.exs index 43a3e00..ea622e3 100644 --- a/config/config.exs +++ b/config/config.exs @@ -37,11 +37,18 @@ config :bun, default: [ # Use --format=iife to prevent overlaps in global state (variables/functions) args: - ~w(build js/app.js js/storybook.js js/video.js js/serviceworker.js) ++ + ~w(build js/app.js js/storybook.js js/video.js) ++ ~w(--format=iife --outdir=../priv/static/assets --external /fonts/* --external /images/*), cd: Path.expand("../assets", __DIR__), env: %{} ], + serviceworker: [ + args: + ~w(build js/serviceworker.js) ++ + ~w(--outdir=../priv/static/assets --external /fonts/* --external /images/*), + cd: Path.expand("../assets", __DIR__), + env: %{} + ], css: [ args: ~w(run tailwindcss --input=css/app.css --output=../priv/static/assets/app.css), cd: Path.expand("../assets", __DIR__), diff --git a/config/dev.exs b/config/dev.exs index 5cc33cb..2fdb6e8 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -23,6 +23,7 @@ config :kobrakai, KobrakaiWeb.Endpoint, secret_key_base: "5x0q0Y1j1FKgBNGfJmjjOY6qj/GEX7U8EsZWtonVrXIfVaFhcNk4Fg54oXHdX9R2", watchers: [ bun: {Bun, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]}, + serviceworker: {Bun, :install_and_run, [:serviceworker, ~w(--sourcemap=inline --watch)]}, bun_css: {Bun, :install_and_run, [:css, ~w(--watch)]}, bun_storybook: {Bun, :install_and_run, [:storybook, ~w(--watch)]} ] diff --git a/lib/kobrakai_web/controllers/cache_controller.ex b/lib/kobrakai_web/controllers/cache_controller.ex deleted file mode 100644 index e52f1b2..0000000 --- a/lib/kobrakai_web/controllers/cache_controller.ex +++ /dev/null @@ -1,19 +0,0 @@ -defmodule KobrakaiWeb.CacheController do - use KobrakaiWeb, :controller - - def show(conn, _) do - json(conn, %{ - static: [ - ~p"/assets/video.js", - ~p"/assets/app.css", - ~p"/assets/app.js", - ~p"/images/signee.png", - ~p"/images/pfeil.png", - ~p"/images/avatar.jpg", - ~p"/font/noway-regular-webfont.woff", - ~p"/font/noway-regular-webfont.woff2", - ~p"/font/Virgil.woff2" - ] - }) - end -end diff --git a/lib/kobrakai_web/router.ex b/lib/kobrakai_web/router.ex index 55a0194..11aa093 100644 --- a/lib/kobrakai_web/router.ex +++ b/lib/kobrakai_web/router.ex @@ -74,12 +74,6 @@ defmodule KobrakaiWeb.Router do end end - scope "/", KobrakaiWeb do - pipe_through :api - - get "/cache", CacheController, :show - end - scope "/", KobrakaiWeb do pipe_through :rss diff --git a/mix.exs b/mix.exs index 5ec4ae9..a1c271d 100644 --- a/mix.exs +++ b/mix.exs @@ -88,13 +88,14 @@ defmodule Kobrakai.MixProject do [ setup: ["deps.get", "assets.setup", "assets.build"], "assets.setup": ["bun.install --if-missing", "bun install"], - "assets.build": ["bun default", "bun css", "bun storybook"], + "assets.build": ["bun default", "bun css", "bun storybook", "bun serviceworker"], "assets.deploy": [ "images.compile", "bun default --minify", "bun css --minify", "bun storybook --minify", - "phx.digest" + "phx.digest", + "bun serviceworker --minify" ] ] end