vite.config.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import { mkdir, writeFile } from 'node:fs/promises';
  2. import { resolve } from 'node:path';
  3. import { sveltekit } from '@sveltejs/kit/vite';
  4. import { SvelteKitPWA } from '@vite-pwa/sveltekit';
  5. import { defineConfig } from 'vite';
  6. function ensurePrerenderedGlob() {
  7. return {
  8. name: 'ensure-prerendered-glob',
  9. apply: 'build',
  10. async writeBundle() {
  11. const dir = resolve('.svelte-kit/output/prerendered');
  12. await mkdir(dir, { recursive: true });
  13. await writeFile(resolve(dir, '.keep.json'), '{}\n');
  14. }
  15. };
  16. }
  17. export default defineConfig({
  18. plugins: [
  19. sveltekit(),
  20. ensurePrerenderedGlob(),
  21. SvelteKitPWA({
  22. registerType: 'autoUpdate',
  23. injectRegister: null,
  24. strategies: 'generateSW',
  25. scope: '/',
  26. base: '/',
  27. manifest: {
  28. id: '/',
  29. name: 'Recipes',
  30. short_name: 'Recipes',
  31. description: 'Save, browse, and cook your recipes on any device.',
  32. lang: 'en',
  33. dir: 'ltr',
  34. start_url: '/',
  35. scope: '/',
  36. display: 'standalone',
  37. display_override: ['window-controls-overlay', 'standalone', 'minimal-ui', 'browser'],
  38. orientation: 'any',
  39. background_color: '#121212',
  40. theme_color: '#121212',
  41. categories: ['food', 'lifestyle', 'utilities'],
  42. prefer_related_applications: false,
  43. // Lets Chromium/Brave report an existing install via getInstalledRelatedApps().
  44. related_applications: [
  45. {
  46. platform: 'webapp',
  47. url: '/manifest.webmanifest'
  48. }
  49. ],
  50. icons: [
  51. {
  52. src: '/icon-72x72.png',
  53. sizes: '72x72',
  54. type: 'image/png',
  55. purpose: 'any'
  56. },
  57. {
  58. src: '/icon-96x96.png',
  59. sizes: '96x96',
  60. type: 'image/png',
  61. purpose: 'any'
  62. },
  63. {
  64. src: '/icon-128x128.png',
  65. sizes: '128x128',
  66. type: 'image/png',
  67. purpose: 'any'
  68. },
  69. {
  70. src: '/icon-144x144.png',
  71. sizes: '144x144',
  72. type: 'image/png',
  73. purpose: 'any'
  74. },
  75. {
  76. src: '/icon-152x152.png',
  77. sizes: '152x152',
  78. type: 'image/png',
  79. purpose: 'any'
  80. },
  81. {
  82. src: '/icon-192x192.png',
  83. sizes: '192x192',
  84. type: 'image/png',
  85. purpose: 'any'
  86. },
  87. {
  88. src: '/icon-384x384.png',
  89. sizes: '384x384',
  90. type: 'image/png',
  91. purpose: 'any'
  92. },
  93. {
  94. src: '/icon-512x512.png',
  95. sizes: '512x512',
  96. type: 'image/png',
  97. purpose: 'any'
  98. },
  99. {
  100. src: '/maskable-icon-192x192.png',
  101. sizes: '192x192',
  102. type: 'image/png',
  103. purpose: 'maskable'
  104. },
  105. {
  106. src: '/maskable-icon-512x512.png',
  107. sizes: '512x512',
  108. type: 'image/png',
  109. purpose: 'maskable'
  110. }
  111. ],
  112. shortcuts: [
  113. {
  114. name: 'Dashboard',
  115. short_name: 'Dashboard',
  116. description: 'View your recipes',
  117. url: '/dashboard',
  118. icons: [{ src: '/icon-192x192.png', sizes: '192x192', type: 'image/png' }]
  119. },
  120. {
  121. name: 'New recipe',
  122. short_name: 'New',
  123. description: 'Create a new recipe',
  124. url: '/recipe/new',
  125. icons: [{ src: '/icon-192x192.png', sizes: '192x192', type: 'image/png' }]
  126. }
  127. ]
  128. },
  129. workbox: {
  130. navigateFallback: null,
  131. globPatterns: [
  132. 'client/**/*.{js,css,ico,png,svg,webp,webmanifest,woff,woff2}',
  133. 'prerendered/.keep.json'
  134. ],
  135. cleanupOutdatedCaches: true,
  136. clientsClaim: true,
  137. skipWaiting: false,
  138. runtimeCaching: [
  139. {
  140. urlPattern: ({ request }) => request.mode === 'navigate',
  141. handler: 'NetworkFirst',
  142. options: {
  143. cacheName: 'pages',
  144. networkTimeoutSeconds: 3,
  145. expiration: {
  146. maxEntries: 64,
  147. maxAgeSeconds: 60 * 60 * 24
  148. },
  149. cacheableResponse: {
  150. statuses: [0, 200]
  151. }
  152. }
  153. },
  154. {
  155. urlPattern: ({ request }) =>
  156. request.destination === 'image' ||
  157. request.destination === 'font' ||
  158. request.destination === 'style' ||
  159. request.destination === 'script',
  160. handler: 'StaleWhileRevalidate',
  161. options: {
  162. cacheName: 'assets',
  163. expiration: {
  164. maxEntries: 128,
  165. maxAgeSeconds: 60 * 60 * 24 * 30
  166. },
  167. cacheableResponse: {
  168. statuses: [0, 200]
  169. }
  170. }
  171. }
  172. ]
  173. },
  174. devOptions: {
  175. enabled: false,
  176. suppressWarnings: true,
  177. type: 'module'
  178. },
  179. kit: {
  180. includeVersionFile: true
  181. }
  182. })
  183. ]
  184. });