workboxで簡単にprecacheする
はじめに
今回はworkboxを利用したprecacheをフレームワークやworkbox-webpack-plugin
などを利用せずに行いたいと思います。
目標は「シンプルに」実装していきます。
環境
Server
今回はgo言語のwebフレームワークであるginを利用します。
goには標準ライブラリとしてnet/http
などありますが、ginによる恩恵が大きいのでこちらを利用。
DBなども用いないので単純なhtmlなどを返すサーバーになります。
Client
こちらは純粋なhtml + jsのみで作成します。precacheする内容は
- /index.html
- *.js
とします。
ディレクトリ構成
. ├── build │ └── main ├── go.mod ├── go.sum ├── main.go ├── refresh.yml ├── static │ ├── image │ │ └── react.png │ └── js │ ├── service-worker.js │ └── workbox.js └── view └── index.html
コード
Server
サーバーサイドはmain.go
だけになります。
package main import ( "fmt" "log" "net/http" "os" "path/filepath" "github.com/gin-gonic/gin" ) func main() { router := gin.Default() router.GET("/", func(ctx *gin.Context) { ctx.File("./view/index.html") }) router.GET("/:file", func(ctx *gin.Context) { file := ctx.Param("file") fp, err := filepath.Glob("./static/**/" + file) if err != nil || len(fp) == 0 { ctx.Status(http.StatusNotFound) return } ctx.File(fp[0]) }) host := os.Getenv("HOST") if host == "" { host = "localhost" } port := os.Getenv("PORT") if port == "" { port = "8081" } baseUrl := fmt.Sprintf("%s:%s", host, port) log.Println("Listening on", baseUrl) log.Fatal(router.Run(baseUrl)) }
service-workerにはスコープの概念があり、/service-worker.js
とリクエストできるように/:file
では`filepath.Glob
を用いてstaticファイルを返すようにしています。
が、ここはもっと綺麗に書ると思います。直してないけど
Client
まずはindex.html
から。
<!DOCTYPE html> <html lang="en"> <head> <title>Service-worker</title> <meta charset="UTF-8"> <script type="module"> import { unregister, register } from "/service-worker.js" register() </script> </head> <body> <img src="/react.png" alt="react icon" style="width: 400px; height: 300px;"/> </body> <html>
こちらは
/react.png
を表示/service-worker.js
のregister関数を実行する
上記2点を行っているシンプルなhtmlです。
それではその/service-worker.js
が以下です。
const swKey = "serviceWorker"; function registerServiceWorker(sw) { navigator.serviceWorker .register(sw) .then(() => { console.log("Register service worker"); }) .catch((err) => { console.error(err); }); } export function unregister() { if (!swKey in navigator) { return; } navigator.serviceWorker.ready .then((registration) => { registration.unregister(); }) .catch((err) => { console.log(err); }); } export function register() { if (!swKey in navigator) { return; } window.addEventListener("load", () => { const swUrl = `/workbox.js`; registerServiceWorker(swUrl); }); }
こちらはservice-worker
を登録/登録解除するjsを記述しています。/service-worker.js
が存在しているかどうかなどの確認は行わず、簡潔に記述しています。
そして重要なworkboxを利用したprecacheを行っている/workbox.js
はこちらです。
importScripts( "https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js" ); const cacheTargets = [ { url: "/", revision: null }, { url: "/react.png", revision: null }, ]; workbox.core.clientsClaim(); workbox.precaching.precacheAndRoute(cacheTargets, {}); const handler = workbox.precaching.createHandlerBoundToURL("/"); const navigationRoute = new workbox.routing.NavigationRoute(handler); workbox.routing.registerRoute(navigationRoute);
上記で行っていることは
です。
これでサーバーを立ち上げ、http://localhost:8081/にhttpリクエストすることでservice-workerがprecacheを行ってくれます。
precache後はオフラインでもコンテンツを表示することができるようになりました。
まとめ
今回は完結にworkboxを用いてprecacheしてみました。
service-workerはまだ理解できていない部分があるのでこまめに学習したいです。
以上です。