reloadOnChunkError.ts 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import type { Router } from 'vue-router'
  2. const RELOAD_STORAGE_KEY = 'app:chunk-load-reload'
  3. const RELOAD_INTERVAL = 30 * 1000
  4. const chunkLoadErrorPatterns = [
  5. 'Failed to fetch dynamically imported module',
  6. 'Importing a module script failed',
  7. 'Loading CSS chunk',
  8. 'Unable to preload CSS',
  9. 'ChunkLoadError',
  10. 'CSS_CHUNK_LOAD_FAILED'
  11. ]
  12. const getErrorMessage = (error: unknown): string => {
  13. if (typeof error === 'string') return error
  14. if (error instanceof Error) return error.message
  15. const maybeError = error as { message?: unknown; reason?: unknown }
  16. if (typeof maybeError?.message === 'string') return maybeError.message
  17. if (typeof maybeError?.reason === 'string') return maybeError.reason
  18. if (maybeError?.reason instanceof Error) return maybeError.reason.message
  19. return ''
  20. }
  21. const isChunkLoadError = (error: unknown): boolean => {
  22. const message = getErrorMessage(error)
  23. return chunkLoadErrorPatterns.some((pattern) => message.includes(pattern))
  24. }
  25. const reloadPageOnce = () => {
  26. const now = Date.now()
  27. const lastReloadAt = Number(sessionStorage.getItem(RELOAD_STORAGE_KEY) || 0)
  28. if (now - lastReloadAt < RELOAD_INTERVAL) return
  29. sessionStorage.setItem(RELOAD_STORAGE_KEY, String(now))
  30. console.log('222', 222)
  31. window.location.reload()
  32. }
  33. export const setupReloadOnChunkError = (router: Router) => {
  34. window.addEventListener('vite:preloadError', (event) => {
  35. event.preventDefault()
  36. reloadPageOnce()
  37. })
  38. router.onError((error) => {
  39. if (isChunkLoadError(error)) {
  40. reloadPageOnce()
  41. }
  42. })
  43. }