Skip to content

Commit

Permalink
feat(PWA): ✨ Blogs Service Worker Test
Browse files Browse the repository at this point in the history
  • Loading branch information
bKoZii committed Sep 19, 2024
1 parent a1d742a commit f0195d5
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 32 deletions.
11 changes: 10 additions & 1 deletion nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,22 @@ export default defineNuxtConfig({
}
},
pwa: {
strategies: 'injectManifest',
srcDir: 'service-worker',
filename: 'sw.ts',
mode: 'production',
manifest: {
name: 'Konkamon Sion - Portfolio & Blogs',
theme_color: '#379777',
categories: ['portfolio', 'blogs'],
description: 'เว็บไซต์ Portfolio & Blogs ของนาย กรกมล ศรีอ่อน - สร้างด้วย Nuxt 3 + TailwindCSS.',
lang: 'th',
}
},
workbox: {
globPatterns: ['**/*.{js,css,html,png,svg,ico}'],
},
injectManifest: {
globPatterns: ['**/*.{js,css,html,png,svg,ico}'],
},
}
})
77 changes: 46 additions & 31 deletions pages/blog/[slug].vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,42 +29,47 @@
import type { RouteLocationNormalized } from 'vue-router'
import type { StrapiBlogSlug } from '~/types/StrapiBlogSlug'
const { findOne } = useStrapi()
const route: RouteLocationNormalized = useRoute()
const nuxt = useNuxtApp()
const { data: blogSlug } = useNuxtData('blogSlug')
const { data } = await useAsyncData(
'blogSlug',
() =>
findOne<StrapiBlogSlug>('blogs', route.params.slug as string, {
fields: ['title', 'subtitle', 'publishedAt', 'slug', 'content', 'updatedAt', 'createdAt'],
populate: {
mainImage: {
fields: ['url']
},
categories: {
fields: ['name']
}
const fetchBlogSlug = async () => {
const cache = await caches.open('api-cache')
const cachedResponse = await cache.match(`/api/blogs/${route.params.slug}`)
if (cachedResponse) {
return cachedResponse.json()
}
const response = await findOne<StrapiBlogSlug>('blogs', route.params.slug as string, {
fields: ['title', 'subtitle', 'publishedAt', 'slug', 'content', 'updatedAt', 'createdAt'],
populate: {
mainImage: {
fields: ['url']
},
categories: {
fields: ['name']
}
}).then((data) => data.data.attributes),
{
default(){
return blogSlug.value
},
watch: false,
deep: false,
getCachedData: (key) => {
}
})
cache.put(`/api/blogs/${route.params.slug}`, new Response(JSON.stringify(response.data.attributes)))
return response.data.attributes
}
const { data } = await useAsyncData('blogSlug', fetchBlogSlug, {
default() {
return blogSlug.value
},
watch: false,
deep: false,
getCachedData: (key) => {
if (nuxt.isHydrating && nuxt.payload.data[key]) {
return nuxt.payload.data[key]
}
if (nuxt.static.data[key]) {
return nuxt.static.data[key]
}
return null
},
}
)
})
useSeoMeta({
title: blogSlug.value?.title,
Expand All @@ -79,8 +84,24 @@ useSeoMeta({
definePageMeta({
middleware: ['check-blog-post']
})
const { data: ast } = useNuxtData('markdown')
const { status } = await useAsyncData('markdown', () => parseMarkdown(blogSlug.value?.content as string), {
const fetchMarkdown = async () => {
const mdCache = await caches.open('markdown-cache')
const cachedMdResponse = await mdCache.match(`/api/markdown/${route.params.slug}`)
if (cachedMdResponse) {
return cachedMdResponse.json()
}
const response = await parseMarkdown(blogSlug.value?.content as string)
mdCache.put(`/api/markdown/${route.params.slug}`, new Response(JSON.stringify(response)))
return response
}
const { status } = await useAsyncData('markdown', fetchMarkdown, {
default() {
return ast.value
},
watch: false,
deep: false,
getCachedData: (key) => {
if (nuxt.isHydrating && nuxt.payload.data[key]) {
return nuxt.payload.data[key]
Expand All @@ -89,12 +110,6 @@ const { status } = await useAsyncData('markdown', () => parseMarkdown(blogSlug.v
return nuxt.static.data[key]
}
return null
},
default(){
return ast.value
},
watch: false,
deep: false,
lazy: true
}
})
</script>
63 changes: 63 additions & 0 deletions service-worker/sw.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/// <reference lib="WebWorker" />
/// <reference types="vite/client" />
import { precacheAndRoute } from 'workbox-precaching'
import { registerRoute } from 'workbox-routing'
import { StaleWhileRevalidate } from 'workbox-strategies'
import { CacheFirst } from 'workbox-strategies'
import { clientsClaim } from 'workbox-core'
import { skipWaiting } from 'workbox-core'

declare let self: ServiceWorkerGlobalScope

precacheAndRoute(self.__WB_MANIFEST)

clientsClaim()
skipWaiting()

registerRoute(
({ url }) => url.pathname.startsWith('/api/'),
new StaleWhileRevalidate({
cacheName: 'api-cache'
})
)

registerRoute(
({ request }) => request.destination === 'script' || request.destination === 'style',
new CacheFirst({
cacheName: 'static-resources'
})
)

self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url)
if (url.pathname === '/api/blogs/search') {
event.respondWith(
caches.open('api-cache').then(async (cache) => {
const cachedResponse = await cache.match(event.request)
if (cachedResponse) {
return cachedResponse
}
const response = await fetch(event.request)
cache.put(event.request, response.clone())
return response
})
)
}
})

self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url)
if (url.pathname.startsWith('/api/markdown')) {
event.respondWith(
caches.open('markdown-cache').then(async (cache) => {
const cachedResponse = await cache.match(event.request)
if (cachedResponse) {
return cachedResponse
}
const response = await fetch(event.request)
cache.put(event.request, response.clone())
return response
})
)
}
})

0 comments on commit f0195d5

Please sign in to comment.