@equinor/fusion-framework-vite-plugin-spa 1.1.1 → 1.1.3
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/CHANGELOG.md +42 -0
- package/dist/esm/html/register-service-worker.js +72 -13
- package/dist/esm/html/register-service-worker.js.map +1 -1
- package/dist/esm/html/sw.js +7 -1
- package/dist/esm/html/sw.js.map +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/html/bootstrap.js +72 -13
- package/dist/html/bootstrap.js.map +1 -1
- package/dist/html/sw.js +7 -1
- package/dist/html/sw.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/html/index.html.d.ts +1 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +5 -5
- package/src/html/register-service-worker.ts +85 -16
- package/src/html/sw.ts +8 -1
- package/src/version.ts +1 -1
|
@@ -15,5 +15,5 @@
|
|
|
15
15
|
* @constant
|
|
16
16
|
* @type {string}
|
|
17
17
|
*/
|
|
18
|
-
export declare const html = "\n <!DOCTYPE html>\n <html>\n <head>\n <title>%FUSION_SPA_TITLE%</title>\n <meta name=\"mode\" content=\"%MODE%\">\n <meta name=\"fusion-spa-plugin-version\" content=\"1.1.
|
|
18
|
+
export declare const html = "\n <!DOCTYPE html>\n <html>\n <head>\n <title>%FUSION_SPA_TITLE%</title>\n <meta name=\"mode\" content=\"%MODE%\">\n <meta name=\"fusion-spa-plugin-version\" content=\"1.1.3\">\n <link rel=\"stylesheet\" href=\"https://cdn.eds.equinor.com/font/equinor-font.css\" />\n <script type=\"module\" src=\"%FUSION_SPA_BOOTSTRAP%\"></script>\n <script>\n // suppress console error for custom elements already defined. \n // WebComponents should be added by the portal, but not removed from application\n const _customElementsDefine = window.customElements.define;\n window.customElements.define = (name, cl, conf) => {\n if (!customElements.get(name)) {\n _customElementsDefine.call(window.customElements, name, cl, conf);\n }\n };\n </script>\n <style>\n html, body {\n margin: 0;\n padding: 0;\n height: 100%;\n font-family: 'EquinorFont', sans-serif;\n }\n </style>\n </head>\n <body></body>\n </html>\n";
|
|
19
19
|
export default html;
|
package/dist/types/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "1.1.
|
|
1
|
+
export declare const version = "1.1.3";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@equinor/fusion-framework-vite-plugin-spa",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "Vite plugin for SPA development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"rollup": "^4.39.0",
|
|
48
48
|
"typescript": "^5.8.2",
|
|
49
49
|
"vite": "^7.1.5",
|
|
50
|
-
"@equinor/fusion-framework-module": "
|
|
51
|
-
"@equinor/fusion-framework-module
|
|
52
|
-
"@equinor/fusion-framework-module-
|
|
53
|
-
"@equinor/fusion-framework-module-
|
|
50
|
+
"@equinor/fusion-framework-module-http": "7.0.1",
|
|
51
|
+
"@equinor/fusion-framework-module": "5.0.2",
|
|
52
|
+
"@equinor/fusion-framework-module-msal": "5.0.1",
|
|
53
|
+
"@equinor/fusion-framework-module-service-discovery": "9.0.1"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"build": "tsc -b",
|
|
@@ -13,26 +13,21 @@ export async function registerServiceWorker(framework: ModulesInstance<[MsalModu
|
|
|
13
13
|
return;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
// wait for the service worker to be ready
|
|
24
|
-
await navigator.serviceWorker.ready;
|
|
25
|
-
|
|
26
|
-
// allow the service worker to start receiving messages
|
|
27
|
-
navigator.serviceWorker.startMessages();
|
|
28
|
-
|
|
29
|
-
// send the config to the service worker
|
|
30
|
-
registration.active?.postMessage({
|
|
16
|
+
/**
|
|
17
|
+
* Helper function to send configuration to the service worker
|
|
18
|
+
*/
|
|
19
|
+
const sendConfigToServiceWorker = (worker: ServiceWorker) => {
|
|
20
|
+
worker.postMessage({
|
|
31
21
|
type: 'INIT_CONFIG',
|
|
32
22
|
config: resourceConfigs,
|
|
33
23
|
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
// allow the service worker to start receiving messages early
|
|
28
|
+
navigator.serviceWorker.startMessages();
|
|
34
29
|
|
|
35
|
-
// listen for messages from the service worker
|
|
30
|
+
// listen for messages from the service worker (set up before registration)
|
|
36
31
|
navigator.serviceWorker.addEventListener('message', async (event) => {
|
|
37
32
|
if (event.data.type === 'GET_TOKEN') {
|
|
38
33
|
try {
|
|
@@ -61,6 +56,80 @@ export async function registerServiceWorker(framework: ModulesInstance<[MsalModu
|
|
|
61
56
|
}
|
|
62
57
|
}
|
|
63
58
|
});
|
|
59
|
+
|
|
60
|
+
// register the service worker
|
|
61
|
+
// updateViaCache: 'none' ensures the service worker script is always fetched fresh
|
|
62
|
+
// This is important during development to pick up code changes
|
|
63
|
+
const registration = await navigator.serviceWorker.register('/@fusion-spa-sw.js', {
|
|
64
|
+
type: 'module',
|
|
65
|
+
scope: '/',
|
|
66
|
+
updateViaCache: 'none',
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Handle service worker updates/installations
|
|
70
|
+
// If there's a service worker waiting or installing, send config when it activates
|
|
71
|
+
if (registration.waiting) {
|
|
72
|
+
sendConfigToServiceWorker(registration.waiting);
|
|
73
|
+
}
|
|
74
|
+
if (registration.installing) {
|
|
75
|
+
registration.installing.addEventListener('statechange', (event) => {
|
|
76
|
+
const worker = event.target as ServiceWorker;
|
|
77
|
+
if (worker.state === 'activated') {
|
|
78
|
+
sendConfigToServiceWorker(worker);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Listen for controller changes (happens during hard refresh or updates)
|
|
84
|
+
navigator.serviceWorker.addEventListener('controllerchange', () => {
|
|
85
|
+
if (navigator.serviceWorker.controller) {
|
|
86
|
+
sendConfigToServiceWorker(navigator.serviceWorker.controller);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// wait for the service worker to be ready
|
|
91
|
+
const readyRegistration = await navigator.serviceWorker.ready;
|
|
92
|
+
|
|
93
|
+
// ensure we have an active service worker before sending config
|
|
94
|
+
const activeWorker = readyRegistration.active;
|
|
95
|
+
if (!activeWorker) {
|
|
96
|
+
console.error('[Service Worker Registration] Service worker is not active after ready state');
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// CRITICAL: Wait for the service worker to become the controller
|
|
101
|
+
// This ensures the service worker can intercept fetch requests
|
|
102
|
+
if (!navigator.serviceWorker.controller) {
|
|
103
|
+
await new Promise<void>((resolve) => {
|
|
104
|
+
let checkInterval: NodeJS.Timeout;
|
|
105
|
+
|
|
106
|
+
const finish = () => {
|
|
107
|
+
clearInterval(checkInterval);
|
|
108
|
+
navigator.serviceWorker.removeEventListener('controllerchange', onControllerChange);
|
|
109
|
+
resolve();
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const onControllerChange = () => finish();
|
|
113
|
+
|
|
114
|
+
// If controllerchange fires, the service worker has taken control
|
|
115
|
+
navigator.serviceWorker.addEventListener('controllerchange', onControllerChange);
|
|
116
|
+
|
|
117
|
+
// Polling fallback and timeout to prevent infinite waiting
|
|
118
|
+
checkInterval = setInterval(() => {
|
|
119
|
+
if (navigator.serviceWorker.controller) finish();
|
|
120
|
+
}, 200);
|
|
121
|
+
|
|
122
|
+
setTimeout(finish, 5000);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// send the config to the active service worker
|
|
127
|
+
sendConfigToServiceWorker(activeWorker);
|
|
128
|
+
|
|
129
|
+
// Also send to the controller if it exists and is different from active
|
|
130
|
+
if (navigator.serviceWorker.controller && navigator.serviceWorker.controller !== activeWorker) {
|
|
131
|
+
sendConfigToServiceWorker(navigator.serviceWorker.controller);
|
|
132
|
+
}
|
|
64
133
|
} catch (error) {
|
|
65
134
|
console.error('Service Worker registration failed:', error);
|
|
66
135
|
}
|
package/src/html/sw.ts
CHANGED
|
@@ -176,10 +176,17 @@ self.addEventListener('activate', (event: ExtendableEvent) => {
|
|
|
176
176
|
});
|
|
177
177
|
|
|
178
178
|
// Handle configuration from main thread
|
|
179
|
-
self.addEventListener('message', (event: ExtendableMessageEvent) => {
|
|
179
|
+
self.addEventListener('message', async (event: ExtendableMessageEvent) => {
|
|
180
180
|
const { type, config } = event.data;
|
|
181
181
|
if (type === 'INIT_CONFIG') {
|
|
182
182
|
resourceConfigurations = config as ResourceConfiguration[];
|
|
183
|
+
|
|
184
|
+
// CRITICAL: Force skipWaiting() and claim clients to ensure this service worker takes control
|
|
185
|
+
// This handles both waiting and already-active service workers during hard refresh
|
|
186
|
+
// - skipWaiting() forces activation if the service worker is in waiting state
|
|
187
|
+
// - clients.claim() takes control of all clients immediately
|
|
188
|
+
await self.skipWaiting();
|
|
189
|
+
await self.clients.claim();
|
|
183
190
|
}
|
|
184
191
|
});
|
|
185
192
|
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '1.1.
|
|
2
|
+
export const version = '1.1.3';
|