2525 * Based on https://github.com/humphd/nohost
2626 *
2727 * This module should be functionally as light weight as possible with minimal deps as it is a shell component.
28+ *
29+ * This file is always loaded fresh from network if available bypassing cache to help better resilience
30+ * against stale caches in service worker. So you can assume that this file will get loaded in its most recent
31+ * form despite the cache state in the browser.
2832 * **/
2933
3034
@@ -83,13 +87,17 @@ if (_isServiceWorkerLoaderPage() && 'serviceWorker' in navigator) {
8387 updateViaCache : 'none'
8488 } ) ;
8589
90+ let isServerReady = false ;
91+
92+ window . Phoenix . cache = { } ;
93+
8694 /**
8795 * This will cause a full cache reset in the browser for the phoenix scripts.
8896 * This will help the user to load the latest version of phoenix on the next load.
8997 * @return {boolean }
9098 * @private
9199 */
92- function _forceClearCacheIfNeeded ( ) {
100+ function _forceClearCacheIfNeeded ( doneCB ) {
93101 const cacheKey = "browserCacheVersionKey" ;
94102 const newCacheVersion = "V1" ; // just increment this number to V2, v3 etc. to force clear the cached content.
95103 if ( window . Phoenix . firstBoot ) {
@@ -99,34 +107,48 @@ if (_isServiceWorkerLoaderPage() && 'serviceWorker' in navigator) {
99107 const lastClearedVersion = window . localStorage . getItem ( cacheKey ) ;
100108 if ( lastClearedVersion !== newCacheVersion ) {
101109 console . log ( `Service worker loader: triggering CLEAR_CACHE for live preview service worker upgrade` ) ;
102- window . Phoenix . updatePendingReload = true ;
103- window . Phoenix . updatePendingReloadReason = "clearCache" ;
104110 wb . messageSW ( {
105111 type : 'CLEAR_CACHE'
112+ } ) . then ( ( { updatedFilesCount} ) => {
113+ console . log ( `Service worker loader: clear cache updatedFilesCount: ` , updatedFilesCount ) ;
114+ window . Phoenix . cache . updatePendingReloadReason = "clearCache" ;
115+ window . Phoenix . cache . showUpdateDialogue = true ;
116+ window . Phoenix . cache . updatedFilesCount = updatedFilesCount ;
117+ localStorage . setItem ( cacheKey , newCacheVersion ) ;
118+ doneCB ( ) ;
119+ } ) . catch ( err => {
120+ console . error ( "Service worker loader: Error while triggering clear cache" , err ) ;
121+ doneCB ( "CLEAR_CACHE Error" ) ;
106122 } ) ;
107- localStorage . setItem ( cacheKey , newCacheVersion ) ;
108123 return true ;
109124 }
110125 return false ;
111126 }
112127
113- function _refreshCache ( ) {
114- if ( _forceClearCacheIfNeeded ( ) ) {
128+ // refreshServiceWorkerCache should be done after app load to prevent mixed js script content load. Ie,
129+ // if we do the cache reset now, some scripts loaded may be from cache and some from the new version.
130+ window . refreshServiceWorkerCache = function ( doneCB ) {
131+ if ( ! isServerReady ) {
132+ setTimeout ( ( ) => {
133+ window . refreshServiceWorkerCache ( doneCB ) ;
134+ } , 100 ) ;
135+ }
136+ if ( _forceClearCacheIfNeeded ( doneCB ) ) {
115137 return ;
116138 }
117139 console . log ( `Service worker loader: triggering REFRESH_CACHE` ) ;
118140 wb . messageSW ( {
119141 type : 'REFRESH_CACHE'
120142 } ) . then ( ( { updatedFilesCount} ) => {
121- console . log ( `Service worker loader: updatedFilesCount: ` , updatedFilesCount ) ;
122- if ( updatedFilesCount > 0 ) {
123- window . Phoenix . updatePendingReload = true ;
124- window . Phoenix . updatePendingReloadReason = "refreshCache" ;
125- }
143+ console . log ( `Service worker loader: refresh cache updatedFilesCount: ` , updatedFilesCount ) ;
144+ window . Phoenix . cache . updatePendingReloadReason = "refreshCache" ;
145+ window . Phoenix . cache . updatedFilesCount = updatedFilesCount ;
146+ doneCB ( ) ;
126147 } ) . catch ( err => {
127- console . error ( "Service worker loader: Error while triggering cache refresh" , err ) ;
148+ console . error ( "Service worker loader: Error while triggering refresh cache" , err ) ;
149+ doneCB ( "REFRESH_CACHE Error" ) ;
128150 } ) ;
129- }
151+ } ;
130152
131153 // Hoist service worker comm to window for everyone be able to communicate with the sw.
132154 window . messageSW = function ( params ) {
@@ -135,6 +157,7 @@ if (_isServiceWorkerLoaderPage() && 'serviceWorker' in navigator) {
135157
136158 function serverReady ( ) {
137159 console . log ( 'Service worker loader: Server ready.' ) ;
160+ isServerReady = true ;
138161 wb . messageSW ( {
139162 type : 'INIT_PHOENIX_CONFIG' ,
140163 debugMode : window . logToConsolePref === 'true' ,
@@ -144,7 +167,6 @@ if (_isServiceWorkerLoaderPage() && 'serviceWorker' in navigator) {
144167 } ) . catch ( err => {
145168 console . error ( "Service worker loader: Error while init of service worker" , err ) ;
146169 } ) ;
147- _refreshCache ( ) ;
148170 }
149171
150172 function serverInstall ( ) {
@@ -176,7 +198,7 @@ if (_isServiceWorkerLoaderPage() && 'serviceWorker' in navigator) {
176198 // service worker has installed but is waiting to activate.
177199 wb . addEventListener ( 'waiting' , ( event ) => {
178200 console . log ( "Service worker loader: A new service worker is pending load. Trying to update the worker now." ) ;
179- // window.Phoenix.updatePendingReload = true; not set here to not show too many update dialogues.
201+ window . Phoenix . cache . updatePendingReloadReason = "skipWait" ;
180202 showSkipWaitingPrompt ( event ) ;
181203 } ) ;
182204
0 commit comments