Created
October 21, 2024 05:04
-
-
Save yapus/8912047d624cbcd5774be03c4cc65d3b to your computer and use it in GitHub Desktop.
rails7-vite - vite-plugin-pwa
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// file: app/frontend/entrypoints/app.jsx | |
import { render } from 'solid-js/web' | |
import App from '@/components/App' | |
import '@/utils/pwa' | |
const app = document.getElementById('app') | |
if (app) { | |
render( | |
() => <App />, | |
app | |
) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "<%= t('app.name') %>", | |
"icons": [ | |
{ | |
"src": "/icon.png", | |
"type": "image/png", | |
"sizes": "512x512" | |
}, | |
{ | |
"src": "/icon.png", | |
"type": "image/png", | |
"sizes": "512x512", | |
"purpose": "maskable" | |
} | |
], | |
"start_url": "/", | |
"display": "standalone", | |
"scope": "/", | |
"description": "<%= t('app.description') %>", | |
"theme_color": "#f5f5f5", | |
"background_color": "#17212b" | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// file: app/frontend/utils/pwa.js | |
import { useRegisterSW } from 'virtual:pwa-register/solid' | |
// import { pwaInfo } from 'virtual:pwa-info' | |
// console.log(pwaInfo) | |
const reloadSW = true | |
const { needRefresh, offlineReady, updateServiceWorker } = useRegisterSW({ | |
immediate: true, | |
onRegisteredSW(swUrl, r) { | |
console.log(`Service Worker at: ${swUrl}`) | |
if (reloadSW === 'true') { | |
r && | |
setInterval(() => { | |
console.log('Checking for sw update') | |
r.update() | |
}, 60 * 60 * 1000 /* 1h */) | |
} else { | |
console.log(`SW Registered: ${r}`) | |
} | |
}, | |
onRegisterError(error) { | |
console.error('SW registration error', error) | |
} | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# file: config/routes.rb | |
Rails.application.routes.draw do | |
# ... | |
get "manifest" => "rails/pwa#manifest", as: :pwa_manifest | |
# ... | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// file: app/frontend/pwa/sw.ts | |
import { cleanupOutdatedCaches, precacheAndRoute } from 'workbox-precaching' | |
import { clientsClaim } from 'workbox-core' | |
import { NavigationRoute, registerRoute } from 'workbox-routing' | |
import { NetworkFirst } from 'workbox-strategies' | |
declare let self: ServiceWorkerGlobalScope | |
// self.__WB_MANIFEST is default injection point | |
const manifest = self.__WB_MANIFEST || []; | |
precacheAndRoute(manifest); | |
// clean old assets | |
cleanupOutdatedCaches() | |
let allowlist: undefined | RegExp[] | |
if (import.meta.env.DEV) | |
allowlist = [/^\/$/] | |
// Handle the offline page with a Network First strategy | |
const offlineHandler = new NetworkFirst({ | |
cacheName: 'offline-page', | |
}); | |
// to allow work offline | |
registerRoute( | |
new NavigationRoute(async (context) => { | |
try { | |
// Try to get the response from the network | |
return await offlineHandler.handle(context); | |
} catch (error) { | |
// If offline, return the cached offline page | |
return await caches.match('/offline.html'); | |
} | |
}, { allowlist }), | |
) | |
self.skipWaiting() | |
clientsClaim() | |
// Log the precache manifest for debugging | |
console.log('Precache manifest:', manifest); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { resolve } from 'path' | |
import { defineConfig } from 'vite' | |
import RubyPlugin from 'vite-plugin-ruby' | |
import Environment from 'vite-plugin-environment' | |
import FullReload from 'vite-plugin-full-reload' | |
import solidPlugin from 'vite-plugin-solid' | |
import ViteRestart from 'vite-plugin-restart' | |
import { VitePWA, VitePWAOptions, ManifestOptions } from 'vite-plugin-pwa'; | |
const pwaOptions: Partial<VitePWAOptions> = { | |
injectRegister: null, | |
manifest: false, | |
mode: process.env.SW_DEV === 'true' ? 'development' : 'production', | |
base: process.env.SW_DEV === 'true' ? '/vite-dev/' : '/vite/', | |
includeAssets: ['icon.png', 'icon.svg', 'favicon.ico'], | |
workbox: { | |
globPatterns: ['**/*.{js,css,html,ico,png,svg}'], | |
navigateFallbackDenylist: [/^\/admin/], | |
runtimeCaching: [ | |
{ | |
urlPattern: /^https:\/\/lh3\.googleusercontent\.com\/d/i, | |
handler: 'CacheFirst', | |
options: { | |
cacheName: 'google-drive-images-cache', | |
expiration: { | |
maxEntries: 10, | |
maxAgeSeconds: 60 * 60 * 24 * 365 // <== 365 days | |
}, | |
cacheableResponse: { | |
statuses: [0, 200] | |
} | |
} | |
}, | |
{ | |
urlPattern: '/offline.html', | |
handler: 'NetworkFirst', | |
options: { | |
cacheName: 'offline-page', | |
expiration: { | |
maxEntries: 1, | |
maxAgeSeconds: 60 * 60 * 24 * 7 // 1 week | |
} | |
} | |
} | |
] | |
}, | |
devOptions: { | |
enabled: process.env.SW_DEV === 'true', | |
type: 'module', | |
navigateFallback: '/offline.html', | |
}, | |
} | |
const selfDestroying = process.env.SW_DESTROY === 'true' | |
if (process.env.SW === 'true') { | |
pwaOptions.srcDir = 'pwa' | |
pwaOptions.filename = 'sw.ts' | |
pwaOptions.strategies = 'injectManifest' | |
pwaOptions.injectManifest = { | |
swSrc: `app/frontend/pwa/${pwaOptions.filename}`, | |
swDest: 'sw.js', | |
injectionPoint: undefined, | |
rollupFormat: 'iife', | |
minify: true | |
} | |
} | |
pwaOptions.registerType = 'autoUpdate' | |
if (selfDestroying) | |
pwaOptions.selfDestroying = selfDestroying | |
export default defineConfig({ | |
resolve: { | |
alias: { | |
'@': resolve(__dirname, "app/frontend") | |
}, | |
}, | |
plugins: [ | |
RubyPlugin(), | |
Environment(['NODE_ENV']), | |
FullReload([ | |
'config/routes.rb', | |
'app/views/**/*', | |
'app/assets/**/*', | |
// => add paths you want to watch | |
], {delay: 200}), | |
solidPlugin(), | |
VitePWA(pwaOptions), | |
ViteRestart({ | |
restart: [ | |
'tmp/restart.vite.txt', | |
] | |
}) | |
], | |
build: { | |
manifest: true, | |
rollupOptions: {} | |
} | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment