Skip to content

Commit a9592ab

Browse files
committed
feat: transparent updates and delay cache refresh till after app loads
1 parent eb7558c commit a9592ab

3 files changed

Lines changed: 53 additions & 22 deletions

File tree

src/extensions/default/Phoenix/newly-added-features.js

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,25 @@ define(function (require, exports, module) {
5757
}, 3000);
5858
}
5959

60-
function _showReloadForUpdateDialog() {
60+
function _cacheUpdatedCB(err) {
61+
if(err) {
62+
Metrics.countEvent(Metrics.EVENT_TYPE.PLATFORM, "cache", "errorRefresh");
63+
return;
64+
}
6165
setTimeout(()=>{
62-
if(window.Phoenix.updatePendingReload){
66+
if(window.Phoenix.cache.showUpdateDialogue){
6367
Dialogs.showModalDialog(
6468
DefaultDialogs.DIALOG_ID_INFO,
6569
Strings.UPDATE_AVAILABLE_TITLE,
6670
Strings.UPDATE_RELOAD_APP
6771
);
68-
Metrics.countEvent(Metrics.EVENT_TYPE.PLATFORM, "updateDlg",
69-
window.Phoenix.updatePendingReloadReason || "shown");
72+
Metrics.countEvent(Metrics.EVENT_TYPE.PLATFORM, "updateDlg", "shown");
7073
}
7174
}, 5000);
75+
Metrics.countEvent(Metrics.EVENT_TYPE.PLATFORM, "cache",
76+
`${window.Phoenix.cache.updatePendingReloadReason}.done`);
77+
Metrics.countEvent(Metrics.EVENT_TYPE.PLATFORM, "cache", `updateCount`,
78+
window.Phoenix.cache.updatedFilesCount||0);
7279
}
7380

7481
async function _readMarkdownTextFile() {
@@ -93,12 +100,13 @@ define(function (require, exports, module) {
93100
console.error("Error while showing new feature markdown on update", e);
94101
});
95102
}
96-
_showReloadForUpdateDialog();
97103
}
98104

99105
exports.init = function () {
100106
if(!Phoenix.firstBoot && !window.testEnvironment){
101107
_showNewUpdatesIfPresent();
102108
}
109+
Metrics.countEvent(Metrics.EVENT_TYPE.PLATFORM, "cache", "doRefresh");
110+
window.refreshServiceWorkerCache(_cacheUpdatedCB);
103111
};
104112
});

src/phoenix/virtual-server-loader.js

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
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

src/virtual-server-main.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,13 @@ workbox.routing.registerRoute(
143143
);
144144

145145
// cache and offline access route
146-
function _clearCache() {
146+
function _clearCache(event) {
147147
caches.open(CACHE_NAME_EVERYTHING).then((cache) => {
148148
cache.keys().then((keys) => {
149149
keys.forEach((request, index, array) => {
150150
cache.delete(request);
151151
});
152+
event.ports[0].postMessage({updatedFilesCount: keys.length});
152153
});
153154
});
154155
}
@@ -281,7 +282,7 @@ addEventListener('message', (event) => {
281282
self._debugSWLivePreviewLogs = event.data.logLivePreview;
282283
self.__WB_DISABLE_DEV_LOGS = Config.debug && _debugSWCacheLogs;
283284
event.ports[0].postMessage({baseURL}); break;
284-
case 'CLEAR_CACHE': _clearCache(); break;
285+
case 'CLEAR_CACHE': _clearCache(event); break;
285286
case 'REFRESH_CACHE': _refreshCache(event); break;
286287
case 'setInstrumentedURLs': self.Serve.setInstrumentedURLs(event); return true;
287288
default:

0 commit comments

Comments
 (0)