@julien-lin/universal-pwa-templates 1.3.13 → 1.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +673 -21
- package/dist/index.d.cts +57 -5
- package/dist/index.d.ts +57 -5
- package/dist/index.js +669 -21
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -30,11 +30,15 @@ __export(index_exports, {
|
|
|
30
30
|
laravelApiServiceWorkerTemplate: () => laravelApiServiceWorkerTemplate,
|
|
31
31
|
laravelSpaServiceWorkerTemplate: () => laravelSpaServiceWorkerTemplate,
|
|
32
32
|
laravelSsrServiceWorkerTemplate: () => laravelSsrServiceWorkerTemplate,
|
|
33
|
+
nextSsrServiceWorkerTemplate: () => nextSsrServiceWorkerTemplate,
|
|
34
|
+
nuxtSsrServiceWorkerTemplate: () => nuxtSsrServiceWorkerTemplate,
|
|
33
35
|
phpServiceWorkerTemplate: () => phpServiceWorkerTemplate,
|
|
34
36
|
placeholder: () => placeholder,
|
|
37
|
+
remixSsrServiceWorkerTemplate: () => remixSsrServiceWorkerTemplate,
|
|
35
38
|
spaServiceWorkerTemplate: () => spaServiceWorkerTemplate,
|
|
36
39
|
ssrServiceWorkerTemplate: () => ssrServiceWorkerTemplate,
|
|
37
40
|
staticServiceWorkerTemplate: () => staticServiceWorkerTemplate,
|
|
41
|
+
svelteKitSsrServiceWorkerTemplate: () => svelteKitSsrServiceWorkerTemplate,
|
|
38
42
|
symfonyApiServiceWorkerTemplate: () => symfonyApiServiceWorkerTemplate,
|
|
39
43
|
symfonySpaServiceWorkerTemplate: () => symfonySpaServiceWorkerTemplate,
|
|
40
44
|
wordpressServiceWorkerTemplate: () => wordpressServiceWorkerTemplate
|
|
@@ -1547,6 +1551,644 @@ if (typeof workbox !== 'undefined') {
|
|
|
1547
1551
|
}
|
|
1548
1552
|
`;
|
|
1549
1553
|
|
|
1554
|
+
// src/service-worker/next-ssr.ts
|
|
1555
|
+
var nextSsrServiceWorkerTemplate = `
|
|
1556
|
+
// Load Workbox from CDN
|
|
1557
|
+
importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.4.0/workbox-sw.js')
|
|
1558
|
+
|
|
1559
|
+
// Ensure Workbox is loaded
|
|
1560
|
+
if (typeof workbox !== 'undefined') {
|
|
1561
|
+
// Precache des assets statiques critiques
|
|
1562
|
+
workbox.precaching.precacheAndRoute(self.__WB_MANIFEST)
|
|
1563
|
+
|
|
1564
|
+
// ====== STATIQUES FINGERPRINTED (_next/static) ======
|
|
1565
|
+
// CacheFirst - Les assets fingerprints ne changent jamais
|
|
1566
|
+
workbox.routing.registerRoute(
|
|
1567
|
+
({ url }) => url.pathname.startsWith('/_next/static/'),
|
|
1568
|
+
new workbox.strategies.CacheFirst({
|
|
1569
|
+
cacheName: 'next-static-cache',
|
|
1570
|
+
plugins: [
|
|
1571
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1572
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1573
|
+
maxEntries: 100,
|
|
1574
|
+
maxAgeSeconds: 365 * 24 * 60 * 60, // 1 an
|
|
1575
|
+
}),
|
|
1576
|
+
],
|
|
1577
|
+
})
|
|
1578
|
+
)
|
|
1579
|
+
|
|
1580
|
+
// ====== PAGES HTML (SSR DYNAMIQUE) ======
|
|
1581
|
+
// NetworkFirst avec fallback pour les pages
|
|
1582
|
+
workbox.routing.registerRoute(
|
|
1583
|
+
({ request }) => request.mode === 'navigate',
|
|
1584
|
+
new workbox.strategies.NetworkFirst({
|
|
1585
|
+
cacheName: 'next-pages-cache',
|
|
1586
|
+
plugins: [
|
|
1587
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1588
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1589
|
+
maxEntries: 50,
|
|
1590
|
+
maxAgeSeconds: 24 * 60 * 60, // 24h
|
|
1591
|
+
}),
|
|
1592
|
+
],
|
|
1593
|
+
networkTimeoutSeconds: 5,
|
|
1594
|
+
})
|
|
1595
|
+
)
|
|
1596
|
+
|
|
1597
|
+
// ====== ISR (Incremental Static Regeneration) ======
|
|
1598
|
+
// Aussi NetworkFirst pour /_next/data/** (API ISR)
|
|
1599
|
+
workbox.routing.registerRoute(
|
|
1600
|
+
({ url }) => url.pathname.startsWith('/_next/data/'),
|
|
1601
|
+
new workbox.strategies.NetworkFirst({
|
|
1602
|
+
cacheName: 'next-isr-cache',
|
|
1603
|
+
plugins: [
|
|
1604
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1605
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1606
|
+
maxEntries: 50,
|
|
1607
|
+
maxAgeSeconds: 60 * 60, // 1h
|
|
1608
|
+
}),
|
|
1609
|
+
],
|
|
1610
|
+
networkTimeoutSeconds: 3,
|
|
1611
|
+
})
|
|
1612
|
+
)
|
|
1613
|
+
|
|
1614
|
+
// ====== IMAGES OPTIMIS\xC9ES (Next.js Image Optimization) ======
|
|
1615
|
+
workbox.routing.registerRoute(
|
|
1616
|
+
({ request, url }) =>
|
|
1617
|
+
request.destination === 'image' || url.pathname.startsWith('/_next/image'),
|
|
1618
|
+
new workbox.strategies.CacheFirst({
|
|
1619
|
+
cacheName: 'next-images-cache',
|
|
1620
|
+
plugins: [
|
|
1621
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1622
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1623
|
+
maxEntries: 100,
|
|
1624
|
+
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 jours
|
|
1625
|
+
}),
|
|
1626
|
+
],
|
|
1627
|
+
})
|
|
1628
|
+
)
|
|
1629
|
+
|
|
1630
|
+
// ====== FONTS ======
|
|
1631
|
+
workbox.routing.registerRoute(
|
|
1632
|
+
({ request }) => request.destination === 'font',
|
|
1633
|
+
new workbox.strategies.CacheFirst({
|
|
1634
|
+
cacheName: 'next-fonts-cache',
|
|
1635
|
+
plugins: [
|
|
1636
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1637
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1638
|
+
maxEntries: 30,
|
|
1639
|
+
maxAgeSeconds: 365 * 24 * 60 * 60, // 1 an
|
|
1640
|
+
}),
|
|
1641
|
+
],
|
|
1642
|
+
})
|
|
1643
|
+
)
|
|
1644
|
+
|
|
1645
|
+
// ====== STYLES & SCRIPTS (Non-fingerprinted) ======
|
|
1646
|
+
workbox.routing.registerRoute(
|
|
1647
|
+
({ request }) =>
|
|
1648
|
+
request.destination === 'style' || request.destination === 'script',
|
|
1649
|
+
new workbox.strategies.StaleWhileRevalidate({
|
|
1650
|
+
cacheName: 'next-assets-cache',
|
|
1651
|
+
plugins: [
|
|
1652
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1653
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1654
|
+
maxEntries: 60,
|
|
1655
|
+
maxAgeSeconds: 7 * 24 * 60 * 60, // 7 jours
|
|
1656
|
+
}),
|
|
1657
|
+
],
|
|
1658
|
+
})
|
|
1659
|
+
)
|
|
1660
|
+
|
|
1661
|
+
// ====== API ROUTES (/api/**) ======
|
|
1662
|
+
workbox.routing.registerRoute(
|
|
1663
|
+
({ url, request }) =>
|
|
1664
|
+
request.method === 'GET' && url.pathname.startsWith('/api/'),
|
|
1665
|
+
new workbox.strategies.NetworkFirst({
|
|
1666
|
+
cacheName: 'next-api-cache',
|
|
1667
|
+
plugins: [
|
|
1668
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1669
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1670
|
+
maxEntries: 50,
|
|
1671
|
+
maxAgeSeconds: 10 * 60, // 10 mins
|
|
1672
|
+
}),
|
|
1673
|
+
],
|
|
1674
|
+
networkTimeoutSeconds: 5,
|
|
1675
|
+
})
|
|
1676
|
+
)
|
|
1677
|
+
|
|
1678
|
+
// ====== GRAPHQL ======
|
|
1679
|
+
workbox.routing.registerRoute(
|
|
1680
|
+
({ url }) => url.pathname === '/graphql',
|
|
1681
|
+
new workbox.strategies.NetworkFirst({
|
|
1682
|
+
cacheName: 'next-graphql-cache',
|
|
1683
|
+
plugins: [
|
|
1684
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1685
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1686
|
+
maxEntries: 30,
|
|
1687
|
+
maxAgeSeconds: 5 * 60, // 5 mins
|
|
1688
|
+
}),
|
|
1689
|
+
],
|
|
1690
|
+
networkTimeoutSeconds: 4,
|
|
1691
|
+
})
|
|
1692
|
+
)
|
|
1693
|
+
|
|
1694
|
+
// ====== OFFLINE FALLBACK ======
|
|
1695
|
+
// Fallback pour pages non trouv\xE9es en offline
|
|
1696
|
+
const offlineFallbackPage = '/offline.html'
|
|
1697
|
+
workbox.routing.setCatchHandler(async ({ event }) => {
|
|
1698
|
+
if (event.request.destination === 'document') {
|
|
1699
|
+
return caches.match(offlineFallbackPage)
|
|
1700
|
+
}
|
|
1701
|
+
return Response.error()
|
|
1702
|
+
})
|
|
1703
|
+
|
|
1704
|
+
// ====== BROADCAST CACHE UPDATE ======
|
|
1705
|
+
// Notifier le client quand le cache est mis \xE0 jour
|
|
1706
|
+
workbox.core.clientsClaim()
|
|
1707
|
+
self.skipWaiting()
|
|
1708
|
+
}
|
|
1709
|
+
`;
|
|
1710
|
+
|
|
1711
|
+
// src/service-worker/nuxt-ssr.ts
|
|
1712
|
+
var nuxtSsrServiceWorkerTemplate = `
|
|
1713
|
+
// Load Workbox from CDN
|
|
1714
|
+
importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.4.0/workbox-sw.js')
|
|
1715
|
+
|
|
1716
|
+
// Ensure Workbox is loaded
|
|
1717
|
+
if (typeof workbox !== 'undefined') {
|
|
1718
|
+
// Precache des assets statiques critiques
|
|
1719
|
+
workbox.precaching.precacheAndRoute(self.__WB_MANIFEST)
|
|
1720
|
+
|
|
1721
|
+
// ====== NUXT STATIQUES (_nuxt/dist) ======
|
|
1722
|
+
// CacheFirst - Assets fingerprinted
|
|
1723
|
+
workbox.routing.registerRoute(
|
|
1724
|
+
({ url }) => url.pathname.startsWith('/_nuxt/'),
|
|
1725
|
+
new workbox.strategies.CacheFirst({
|
|
1726
|
+
cacheName: 'nuxt-static-cache',
|
|
1727
|
+
plugins: [
|
|
1728
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1729
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1730
|
+
maxEntries: 100,
|
|
1731
|
+
maxAgeSeconds: 365 * 24 * 60 * 60, // 1 an
|
|
1732
|
+
}),
|
|
1733
|
+
],
|
|
1734
|
+
})
|
|
1735
|
+
)
|
|
1736
|
+
|
|
1737
|
+
// ====== PAGES HTML (SSR DYNAMIQUE) ======
|
|
1738
|
+
workbox.routing.registerRoute(
|
|
1739
|
+
({ request }) => request.mode === 'navigate',
|
|
1740
|
+
new workbox.strategies.NetworkFirst({
|
|
1741
|
+
cacheName: 'nuxt-pages-cache',
|
|
1742
|
+
plugins: [
|
|
1743
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1744
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1745
|
+
maxEntries: 50,
|
|
1746
|
+
maxAgeSeconds: 24 * 60 * 60, // 24h
|
|
1747
|
+
}),
|
|
1748
|
+
],
|
|
1749
|
+
networkTimeoutSeconds: 5,
|
|
1750
|
+
})
|
|
1751
|
+
)
|
|
1752
|
+
|
|
1753
|
+
// ====== PAYLOAD EXTRACTION (Nuxt content/data API) ======
|
|
1754
|
+
// Pour Nuxt Content ou endpoints g\xE9n\xE9r\xE9s
|
|
1755
|
+
workbox.routing.registerRoute(
|
|
1756
|
+
({ url }) =>
|
|
1757
|
+
url.pathname.startsWith('/__payload') ||
|
|
1758
|
+
url.pathname.startsWith('/_payload'),
|
|
1759
|
+
new workbox.strategies.NetworkFirst({
|
|
1760
|
+
cacheName: 'nuxt-payload-cache',
|
|
1761
|
+
plugins: [
|
|
1762
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1763
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1764
|
+
maxEntries: 50,
|
|
1765
|
+
maxAgeSeconds: 60 * 60, // 1h
|
|
1766
|
+
}),
|
|
1767
|
+
],
|
|
1768
|
+
networkTimeoutSeconds: 3,
|
|
1769
|
+
})
|
|
1770
|
+
)
|
|
1771
|
+
|
|
1772
|
+
// ====== HYBRID RENDERING (Nuxt Islands) ======
|
|
1773
|
+
// Pour les composants islands isomorphes
|
|
1774
|
+
workbox.routing.registerRoute(
|
|
1775
|
+
({ url }) => url.pathname.startsWith('/__nuxt_island'),
|
|
1776
|
+
new workbox.strategies.NetworkFirst({
|
|
1777
|
+
cacheName: 'nuxt-islands-cache',
|
|
1778
|
+
plugins: [
|
|
1779
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1780
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1781
|
+
maxEntries: 60,
|
|
1782
|
+
maxAgeSeconds: 30 * 60, // 30 mins
|
|
1783
|
+
}),
|
|
1784
|
+
],
|
|
1785
|
+
networkTimeoutSeconds: 4,
|
|
1786
|
+
})
|
|
1787
|
+
)
|
|
1788
|
+
|
|
1789
|
+
// ====== IMAGES ======
|
|
1790
|
+
workbox.routing.registerRoute(
|
|
1791
|
+
({ request, url }) =>
|
|
1792
|
+
request.destination === 'image' || url.pathname.startsWith('/_image'),
|
|
1793
|
+
new workbox.strategies.CacheFirst({
|
|
1794
|
+
cacheName: 'nuxt-images-cache',
|
|
1795
|
+
plugins: [
|
|
1796
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1797
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1798
|
+
maxEntries: 100,
|
|
1799
|
+
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 jours
|
|
1800
|
+
}),
|
|
1801
|
+
],
|
|
1802
|
+
})
|
|
1803
|
+
)
|
|
1804
|
+
|
|
1805
|
+
// ====== FONTS ======
|
|
1806
|
+
workbox.routing.registerRoute(
|
|
1807
|
+
({ request }) => request.destination === 'font',
|
|
1808
|
+
new workbox.strategies.CacheFirst({
|
|
1809
|
+
cacheName: 'nuxt-fonts-cache',
|
|
1810
|
+
plugins: [
|
|
1811
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1812
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1813
|
+
maxEntries: 30,
|
|
1814
|
+
maxAgeSeconds: 365 * 24 * 60 * 60, // 1 an
|
|
1815
|
+
}),
|
|
1816
|
+
],
|
|
1817
|
+
})
|
|
1818
|
+
)
|
|
1819
|
+
|
|
1820
|
+
// ====== STYLES & SCRIPTS ======
|
|
1821
|
+
workbox.routing.registerRoute(
|
|
1822
|
+
({ request }) =>
|
|
1823
|
+
request.destination === 'style' || request.destination === 'script',
|
|
1824
|
+
new workbox.strategies.StaleWhileRevalidate({
|
|
1825
|
+
cacheName: 'nuxt-assets-cache',
|
|
1826
|
+
plugins: [
|
|
1827
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1828
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1829
|
+
maxEntries: 60,
|
|
1830
|
+
maxAgeSeconds: 7 * 24 * 60 * 60, // 7 jours
|
|
1831
|
+
}),
|
|
1832
|
+
],
|
|
1833
|
+
})
|
|
1834
|
+
)
|
|
1835
|
+
|
|
1836
|
+
// ====== API ROUTES (/api/**) ======
|
|
1837
|
+
workbox.routing.registerRoute(
|
|
1838
|
+
({ url, request }) =>
|
|
1839
|
+
request.method === 'GET' && url.pathname.startsWith('/api/'),
|
|
1840
|
+
new workbox.strategies.NetworkFirst({
|
|
1841
|
+
cacheName: 'nuxt-api-cache',
|
|
1842
|
+
plugins: [
|
|
1843
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1844
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1845
|
+
maxEntries: 50,
|
|
1846
|
+
maxAgeSeconds: 10 * 60, // 10 mins
|
|
1847
|
+
}),
|
|
1848
|
+
],
|
|
1849
|
+
networkTimeoutSeconds: 5,
|
|
1850
|
+
})
|
|
1851
|
+
)
|
|
1852
|
+
|
|
1853
|
+
// ====== GRAPHQL ======
|
|
1854
|
+
workbox.routing.registerRoute(
|
|
1855
|
+
({ url }) => url.pathname === '/graphql',
|
|
1856
|
+
new workbox.strategies.NetworkFirst({
|
|
1857
|
+
cacheName: 'nuxt-graphql-cache',
|
|
1858
|
+
plugins: [
|
|
1859
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1860
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1861
|
+
maxEntries: 30,
|
|
1862
|
+
maxAgeSeconds: 5 * 60, // 5 mins
|
|
1863
|
+
}),
|
|
1864
|
+
],
|
|
1865
|
+
networkTimeoutSeconds: 4,
|
|
1866
|
+
})
|
|
1867
|
+
)
|
|
1868
|
+
|
|
1869
|
+
// ====== OFFLINE FALLBACK ======
|
|
1870
|
+
const offlineFallbackPage = '/offline.html'
|
|
1871
|
+
workbox.routing.setCatchHandler(async ({ event }) => {
|
|
1872
|
+
if (event.request.destination === 'document') {
|
|
1873
|
+
return caches.match(offlineFallbackPage)
|
|
1874
|
+
}
|
|
1875
|
+
return Response.error()
|
|
1876
|
+
})
|
|
1877
|
+
|
|
1878
|
+
// ====== BROADCAST CACHE UPDATE ======
|
|
1879
|
+
workbox.core.clientsClaim()
|
|
1880
|
+
self.skipWaiting()
|
|
1881
|
+
}
|
|
1882
|
+
`;
|
|
1883
|
+
|
|
1884
|
+
// src/service-worker/remix-ssr.ts
|
|
1885
|
+
var remixSsrServiceWorkerTemplate = `
|
|
1886
|
+
// Load Workbox from CDN
|
|
1887
|
+
importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.4.0/workbox-sw.js')
|
|
1888
|
+
|
|
1889
|
+
// Ensure Workbox is loaded
|
|
1890
|
+
if (typeof workbox !== 'undefined') {
|
|
1891
|
+
// Precache des assets statiques critiques
|
|
1892
|
+
workbox.precaching.precacheAndRoute(self.__WB_MANIFEST)
|
|
1893
|
+
|
|
1894
|
+
// ====== REMIX STATIQUES (/build) ======
|
|
1895
|
+
// CacheFirst - Assets fingerprinted
|
|
1896
|
+
workbox.routing.registerRoute(
|
|
1897
|
+
({ url }) => url.pathname.startsWith('/build/'),
|
|
1898
|
+
new workbox.strategies.CacheFirst({
|
|
1899
|
+
cacheName: 'remix-static-cache',
|
|
1900
|
+
plugins: [
|
|
1901
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1902
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1903
|
+
maxEntries: 100,
|
|
1904
|
+
maxAgeSeconds: 365 * 24 * 60 * 60, // 1 an
|
|
1905
|
+
}),
|
|
1906
|
+
],
|
|
1907
|
+
})
|
|
1908
|
+
)
|
|
1909
|
+
|
|
1910
|
+
// ====== PAGES HTML (SSR DYNAMIQUE) ======
|
|
1911
|
+
workbox.routing.registerRoute(
|
|
1912
|
+
({ request }) => request.mode === 'navigate',
|
|
1913
|
+
new workbox.strategies.NetworkFirst({
|
|
1914
|
+
cacheName: 'remix-pages-cache',
|
|
1915
|
+
plugins: [
|
|
1916
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1917
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1918
|
+
maxEntries: 50,
|
|
1919
|
+
maxAgeSeconds: 24 * 60 * 60, // 24h
|
|
1920
|
+
}),
|
|
1921
|
+
],
|
|
1922
|
+
networkTimeoutSeconds: 5,
|
|
1923
|
+
})
|
|
1924
|
+
)
|
|
1925
|
+
|
|
1926
|
+
// ====== REMIX RESOURCE ROUTES (/resource/**) ======
|
|
1927
|
+
workbox.routing.registerRoute(
|
|
1928
|
+
({ url }) => url.pathname.startsWith('/resource/'),
|
|
1929
|
+
new workbox.strategies.NetworkFirst({
|
|
1930
|
+
cacheName: 'remix-resources-cache',
|
|
1931
|
+
plugins: [
|
|
1932
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1933
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1934
|
+
maxEntries: 50,
|
|
1935
|
+
maxAgeSeconds: 60 * 60, // 1h
|
|
1936
|
+
}),
|
|
1937
|
+
],
|
|
1938
|
+
networkTimeoutSeconds: 4,
|
|
1939
|
+
})
|
|
1940
|
+
)
|
|
1941
|
+
|
|
1942
|
+
// ====== IMAGES ======
|
|
1943
|
+
workbox.routing.registerRoute(
|
|
1944
|
+
({ request, url }) =>
|
|
1945
|
+
request.destination === 'image',
|
|
1946
|
+
new workbox.strategies.CacheFirst({
|
|
1947
|
+
cacheName: 'remix-images-cache',
|
|
1948
|
+
plugins: [
|
|
1949
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1950
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1951
|
+
maxEntries: 100,
|
|
1952
|
+
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 jours
|
|
1953
|
+
}),
|
|
1954
|
+
],
|
|
1955
|
+
})
|
|
1956
|
+
)
|
|
1957
|
+
|
|
1958
|
+
// ====== FONTS ======
|
|
1959
|
+
workbox.routing.registerRoute(
|
|
1960
|
+
({ request }) => request.destination === 'font',
|
|
1961
|
+
new workbox.strategies.CacheFirst({
|
|
1962
|
+
cacheName: 'remix-fonts-cache',
|
|
1963
|
+
plugins: [
|
|
1964
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1965
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1966
|
+
maxEntries: 30,
|
|
1967
|
+
maxAgeSeconds: 365 * 24 * 60 * 60, // 1 an
|
|
1968
|
+
}),
|
|
1969
|
+
],
|
|
1970
|
+
})
|
|
1971
|
+
)
|
|
1972
|
+
|
|
1973
|
+
// ====== STYLES & SCRIPTS ======
|
|
1974
|
+
workbox.routing.registerRoute(
|
|
1975
|
+
({ request }) =>
|
|
1976
|
+
request.destination === 'style' || request.destination === 'script',
|
|
1977
|
+
new workbox.strategies.StaleWhileRevalidate({
|
|
1978
|
+
cacheName: 'remix-assets-cache',
|
|
1979
|
+
plugins: [
|
|
1980
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1981
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1982
|
+
maxEntries: 60,
|
|
1983
|
+
maxAgeSeconds: 7 * 24 * 60 * 60, // 7 jours
|
|
1984
|
+
}),
|
|
1985
|
+
],
|
|
1986
|
+
})
|
|
1987
|
+
)
|
|
1988
|
+
|
|
1989
|
+
// ====== API ROUTES (/api/**) ======
|
|
1990
|
+
workbox.routing.registerRoute(
|
|
1991
|
+
({ url, request }) =>
|
|
1992
|
+
request.method === 'GET' && url.pathname.startsWith('/api/'),
|
|
1993
|
+
new workbox.strategies.NetworkFirst({
|
|
1994
|
+
cacheName: 'remix-api-cache',
|
|
1995
|
+
plugins: [
|
|
1996
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
1997
|
+
new workbox.expiration.ExpirationPlugin({
|
|
1998
|
+
maxEntries: 50,
|
|
1999
|
+
maxAgeSeconds: 10 * 60, // 10 mins
|
|
2000
|
+
}),
|
|
2001
|
+
],
|
|
2002
|
+
networkTimeoutSeconds: 5,
|
|
2003
|
+
})
|
|
2004
|
+
)
|
|
2005
|
+
|
|
2006
|
+
// ====== GRAPHQL ======
|
|
2007
|
+
workbox.routing.registerRoute(
|
|
2008
|
+
({ url }) => url.pathname === '/graphql',
|
|
2009
|
+
new workbox.strategies.NetworkFirst({
|
|
2010
|
+
cacheName: 'remix-graphql-cache',
|
|
2011
|
+
plugins: [
|
|
2012
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
2013
|
+
new workbox.expiration.ExpirationPlugin({
|
|
2014
|
+
maxEntries: 30,
|
|
2015
|
+
maxAgeSeconds: 5 * 60, // 5 mins
|
|
2016
|
+
}),
|
|
2017
|
+
],
|
|
2018
|
+
networkTimeoutSeconds: 4,
|
|
2019
|
+
})
|
|
2020
|
+
)
|
|
2021
|
+
|
|
2022
|
+
// ====== OFFLINE FALLBACK ======
|
|
2023
|
+
const offlineFallbackPage = '/offline.html'
|
|
2024
|
+
workbox.routing.setCatchHandler(async ({ event }) => {
|
|
2025
|
+
if (event.request.destination === 'document') {
|
|
2026
|
+
return caches.match(offlineFallbackPage)
|
|
2027
|
+
}
|
|
2028
|
+
return Response.error()
|
|
2029
|
+
})
|
|
2030
|
+
|
|
2031
|
+
// ====== BROADCAST CACHE UPDATE ======
|
|
2032
|
+
workbox.core.clientsClaim()
|
|
2033
|
+
self.skipWaiting()
|
|
2034
|
+
}
|
|
2035
|
+
`;
|
|
2036
|
+
|
|
2037
|
+
// src/service-worker/sveltekit-ssr.ts
|
|
2038
|
+
var svelteKitSsrServiceWorkerTemplate = `
|
|
2039
|
+
// Load Workbox from CDN
|
|
2040
|
+
importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.4.0/workbox-sw.js')
|
|
2041
|
+
|
|
2042
|
+
// Ensure Workbox is loaded
|
|
2043
|
+
if (typeof workbox !== 'undefined') {
|
|
2044
|
+
// Precache des assets statiques critiques
|
|
2045
|
+
workbox.precaching.precacheAndRoute(self.__WB_MANIFEST)
|
|
2046
|
+
|
|
2047
|
+
// ====== SVELTEKIT STATIQUES (/_app) ======
|
|
2048
|
+
// CacheFirst - Assets fingerprinted
|
|
2049
|
+
workbox.routing.registerRoute(
|
|
2050
|
+
({ url }) => url.pathname.startsWith('/_app/'),
|
|
2051
|
+
new workbox.strategies.CacheFirst({
|
|
2052
|
+
cacheName: 'sveltekit-static-cache',
|
|
2053
|
+
plugins: [
|
|
2054
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
2055
|
+
new workbox.expiration.ExpirationPlugin({
|
|
2056
|
+
maxEntries: 100,
|
|
2057
|
+
maxAgeSeconds: 365 * 24 * 60 * 60, // 1 an
|
|
2058
|
+
}),
|
|
2059
|
+
],
|
|
2060
|
+
})
|
|
2061
|
+
)
|
|
2062
|
+
|
|
2063
|
+
// ====== PAGES HTML (SSR DYNAMIQUE) ======
|
|
2064
|
+
workbox.routing.registerRoute(
|
|
2065
|
+
({ request }) => request.mode === 'navigate',
|
|
2066
|
+
new workbox.strategies.NetworkFirst({
|
|
2067
|
+
cacheName: 'sveltekit-pages-cache',
|
|
2068
|
+
plugins: [
|
|
2069
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
2070
|
+
new workbox.expiration.ExpirationPlugin({
|
|
2071
|
+
maxEntries: 50,
|
|
2072
|
+
maxAgeSeconds: 24 * 60 * 60, // 24h
|
|
2073
|
+
}),
|
|
2074
|
+
],
|
|
2075
|
+
networkTimeoutSeconds: 5,
|
|
2076
|
+
})
|
|
2077
|
+
)
|
|
2078
|
+
|
|
2079
|
+
// ====== LAYOUT & COMPONENT DATA ======
|
|
2080
|
+
// Pour les donn\xE9es de layout et composants
|
|
2081
|
+
workbox.routing.registerRoute(
|
|
2082
|
+
({ url }) =>
|
|
2083
|
+
url.pathname.startsWith('/__data/') ||
|
|
2084
|
+
url.pathname.endsWith('.json'),
|
|
2085
|
+
new workbox.strategies.NetworkFirst({
|
|
2086
|
+
cacheName: 'sveltekit-data-cache',
|
|
2087
|
+
plugins: [
|
|
2088
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
2089
|
+
new workbox.expiration.ExpirationPlugin({
|
|
2090
|
+
maxEntries: 50,
|
|
2091
|
+
maxAgeSeconds: 60 * 60, // 1h
|
|
2092
|
+
}),
|
|
2093
|
+
],
|
|
2094
|
+
networkTimeoutSeconds: 4,
|
|
2095
|
+
})
|
|
2096
|
+
)
|
|
2097
|
+
|
|
2098
|
+
// ====== IMAGES ======
|
|
2099
|
+
workbox.routing.registerRoute(
|
|
2100
|
+
({ request }) => request.destination === 'image',
|
|
2101
|
+
new workbox.strategies.CacheFirst({
|
|
2102
|
+
cacheName: 'sveltekit-images-cache',
|
|
2103
|
+
plugins: [
|
|
2104
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
2105
|
+
new workbox.expiration.ExpirationPlugin({
|
|
2106
|
+
maxEntries: 100,
|
|
2107
|
+
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 jours
|
|
2108
|
+
}),
|
|
2109
|
+
],
|
|
2110
|
+
})
|
|
2111
|
+
)
|
|
2112
|
+
|
|
2113
|
+
// ====== FONTS ======
|
|
2114
|
+
workbox.routing.registerRoute(
|
|
2115
|
+
({ request }) => request.destination === 'font',
|
|
2116
|
+
new workbox.strategies.CacheFirst({
|
|
2117
|
+
cacheName: 'sveltekit-fonts-cache',
|
|
2118
|
+
plugins: [
|
|
2119
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
2120
|
+
new workbox.expiration.ExpirationPlugin({
|
|
2121
|
+
maxEntries: 30,
|
|
2122
|
+
maxAgeSeconds: 365 * 24 * 60 * 60, // 1 an
|
|
2123
|
+
}),
|
|
2124
|
+
],
|
|
2125
|
+
})
|
|
2126
|
+
)
|
|
2127
|
+
|
|
2128
|
+
// ====== STYLES & SCRIPTS ======
|
|
2129
|
+
workbox.routing.registerRoute(
|
|
2130
|
+
({ request }) =>
|
|
2131
|
+
request.destination === 'style' || request.destination === 'script',
|
|
2132
|
+
new workbox.strategies.StaleWhileRevalidate({
|
|
2133
|
+
cacheName: 'sveltekit-assets-cache',
|
|
2134
|
+
plugins: [
|
|
2135
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
2136
|
+
new workbox.expiration.ExpirationPlugin({
|
|
2137
|
+
maxEntries: 60,
|
|
2138
|
+
maxAgeSeconds: 7 * 24 * 60 * 60, // 7 jours
|
|
2139
|
+
}),
|
|
2140
|
+
],
|
|
2141
|
+
})
|
|
2142
|
+
)
|
|
2143
|
+
|
|
2144
|
+
// ====== API ROUTES (/api/**) ======
|
|
2145
|
+
workbox.routing.registerRoute(
|
|
2146
|
+
({ url, request }) =>
|
|
2147
|
+
request.method === 'GET' && url.pathname.startsWith('/api/'),
|
|
2148
|
+
new workbox.strategies.NetworkFirst({
|
|
2149
|
+
cacheName: 'sveltekit-api-cache',
|
|
2150
|
+
plugins: [
|
|
2151
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
2152
|
+
new workbox.expiration.ExpirationPlugin({
|
|
2153
|
+
maxEntries: 50,
|
|
2154
|
+
maxAgeSeconds: 10 * 60, // 10 mins
|
|
2155
|
+
}),
|
|
2156
|
+
],
|
|
2157
|
+
networkTimeoutSeconds: 5,
|
|
2158
|
+
})
|
|
2159
|
+
)
|
|
2160
|
+
|
|
2161
|
+
// ====== GRAPHQL ======
|
|
2162
|
+
workbox.routing.registerRoute(
|
|
2163
|
+
({ url }) => url.pathname === '/graphql',
|
|
2164
|
+
new workbox.strategies.NetworkFirst({
|
|
2165
|
+
cacheName: 'sveltekit-graphql-cache',
|
|
2166
|
+
plugins: [
|
|
2167
|
+
new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
2168
|
+
new workbox.expiration.ExpirationPlugin({
|
|
2169
|
+
maxEntries: 30,
|
|
2170
|
+
maxAgeSeconds: 5 * 60, // 5 mins
|
|
2171
|
+
}),
|
|
2172
|
+
],
|
|
2173
|
+
networkTimeoutSeconds: 4,
|
|
2174
|
+
})
|
|
2175
|
+
)
|
|
2176
|
+
|
|
2177
|
+
// ====== OFFLINE FALLBACK ======
|
|
2178
|
+
const offlineFallbackPage = '/offline.html'
|
|
2179
|
+
workbox.routing.setCatchHandler(async ({ event }) => {
|
|
2180
|
+
if (event.request.destination === 'document') {
|
|
2181
|
+
return caches.match(offlineFallbackPage)
|
|
2182
|
+
}
|
|
2183
|
+
return Response.error()
|
|
2184
|
+
})
|
|
2185
|
+
|
|
2186
|
+
// ====== BROADCAST CACHE UPDATE ======
|
|
2187
|
+
workbox.core.clientsClaim()
|
|
2188
|
+
self.skipWaiting()
|
|
2189
|
+
}
|
|
2190
|
+
`;
|
|
2191
|
+
|
|
1550
2192
|
// src/service-worker/index.ts
|
|
1551
2193
|
function getServiceWorkerTemplate(type) {
|
|
1552
2194
|
const templates = {
|
|
@@ -1563,7 +2205,11 @@ function getServiceWorkerTemplate(type) {
|
|
|
1563
2205
|
"django-spa": djangoSpaServiceWorkerTemplate,
|
|
1564
2206
|
"django-api": djangoApiServiceWorkerTemplate,
|
|
1565
2207
|
"flask-spa": flaskSpaServiceWorkerTemplate,
|
|
1566
|
-
"flask-api": flaskApiServiceWorkerTemplate
|
|
2208
|
+
"flask-api": flaskApiServiceWorkerTemplate,
|
|
2209
|
+
"next-ssr": nextSsrServiceWorkerTemplate,
|
|
2210
|
+
"nuxt-ssr": nuxtSsrServiceWorkerTemplate,
|
|
2211
|
+
"remix-ssr": remixSsrServiceWorkerTemplate,
|
|
2212
|
+
"sveltekit-ssr": svelteKitSsrServiceWorkerTemplate
|
|
1567
2213
|
};
|
|
1568
2214
|
const content = templates[type];
|
|
1569
2215
|
if (!content) {
|
|
@@ -1589,43 +2235,45 @@ function getAvailableTemplateTypes() {
|
|
|
1589
2235
|
"django-spa",
|
|
1590
2236
|
"django-api",
|
|
1591
2237
|
"flask-spa",
|
|
1592
|
-
"flask-api"
|
|
2238
|
+
"flask-api",
|
|
2239
|
+
"next-ssr",
|
|
2240
|
+
"nuxt-ssr",
|
|
2241
|
+
"remix-ssr",
|
|
2242
|
+
"sveltekit-ssr"
|
|
1593
2243
|
];
|
|
1594
2244
|
}
|
|
1595
2245
|
function determineTemplateType(architecture, framework) {
|
|
1596
|
-
|
|
2246
|
+
const f = framework?.toLowerCase() ?? "";
|
|
2247
|
+
if (f === "wordpress" || f === "woocommerce") {
|
|
1597
2248
|
return "wordpress";
|
|
1598
2249
|
}
|
|
1599
|
-
if (
|
|
2250
|
+
if (f === "drupal" || f === "joomla" || f === "magento" || f === "shopify" || f === "prestashop") {
|
|
1600
2251
|
return "php";
|
|
1601
2252
|
}
|
|
1602
|
-
if (
|
|
2253
|
+
if (f === "symfony") {
|
|
1603
2254
|
return architecture === "spa" ? "symfony-spa" : "symfony-api";
|
|
1604
2255
|
}
|
|
1605
|
-
if (
|
|
2256
|
+
if (f === "codeigniter" || f === "cakephp" || f === "yii" || f === "laminas") {
|
|
1606
2257
|
return "php";
|
|
1607
2258
|
}
|
|
1608
|
-
if (
|
|
1609
|
-
if (architecture === "spa")
|
|
1610
|
-
|
|
1611
|
-
}
|
|
1612
|
-
if (architecture === "ssr") {
|
|
1613
|
-
return "laravel-ssr";
|
|
1614
|
-
}
|
|
2259
|
+
if (f === "laravel") {
|
|
2260
|
+
if (architecture === "spa") return "laravel-spa";
|
|
2261
|
+
if (architecture === "ssr") return "laravel-ssr";
|
|
1615
2262
|
return "laravel-api";
|
|
1616
2263
|
}
|
|
1617
|
-
if (
|
|
2264
|
+
if (f === "django") {
|
|
1618
2265
|
return architecture === "spa" ? "django-spa" : "django-api";
|
|
1619
2266
|
}
|
|
1620
|
-
if (
|
|
2267
|
+
if (f === "flask") {
|
|
1621
2268
|
return architecture === "spa" ? "flask-spa" : "flask-api";
|
|
1622
2269
|
}
|
|
1623
|
-
if (architecture === "
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
if (architecture === "ssr")
|
|
1627
|
-
|
|
1628
|
-
|
|
2270
|
+
if (f === "nextjs" && architecture === "ssr") return "next-ssr";
|
|
2271
|
+
if (f === "nuxt" && architecture === "ssr") return "nuxt-ssr";
|
|
2272
|
+
if (f === "remix" && architecture === "ssr") return "remix-ssr";
|
|
2273
|
+
if (f === "sveltekit" && architecture === "ssr") return "sveltekit-ssr";
|
|
2274
|
+
if (f === "astro" && architecture === "ssr") return "ssr";
|
|
2275
|
+
if (architecture === "spa") return "spa";
|
|
2276
|
+
if (architecture === "ssr") return "ssr";
|
|
1629
2277
|
return "static";
|
|
1630
2278
|
}
|
|
1631
2279
|
|
|
@@ -1643,11 +2291,15 @@ var placeholder = true;
|
|
|
1643
2291
|
laravelApiServiceWorkerTemplate,
|
|
1644
2292
|
laravelSpaServiceWorkerTemplate,
|
|
1645
2293
|
laravelSsrServiceWorkerTemplate,
|
|
2294
|
+
nextSsrServiceWorkerTemplate,
|
|
2295
|
+
nuxtSsrServiceWorkerTemplate,
|
|
1646
2296
|
phpServiceWorkerTemplate,
|
|
1647
2297
|
placeholder,
|
|
2298
|
+
remixSsrServiceWorkerTemplate,
|
|
1648
2299
|
spaServiceWorkerTemplate,
|
|
1649
2300
|
ssrServiceWorkerTemplate,
|
|
1650
2301
|
staticServiceWorkerTemplate,
|
|
2302
|
+
svelteKitSsrServiceWorkerTemplate,
|
|
1651
2303
|
symfonyApiServiceWorkerTemplate,
|
|
1652
2304
|
symfonySpaServiceWorkerTemplate,
|
|
1653
2305
|
wordpressServiceWorkerTemplate
|