Skip to content

Commit b10dc3c

Browse files
committed
Refactor script loading to ensure Monaco loads first
Refactored the script loading sequence to guarantee that the Monaco Editor is fully loaded and initialized before other scripts and before the loading screen is hidden. Introduced a monacoReady flag and updated readiness checks and fallback logic accordingly. Removed the unused updateLoadingText function. Increased the fallback timeout to 10 seconds to accommodate Monaco's loading time. These changes improve the reliability and sequencing of script dependencies during application startup.
1 parent 73d42e8 commit b10dc3c

File tree

1 file changed

+85
-36
lines changed

1 file changed

+85
-36
lines changed

src/framework/Elsa.Studio.Shared/wwwroot/js/elsa-studio-loader-server.js

Lines changed: 85 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
let loadingHidden = false;
1111
let blazorReady = false;
1212
let initialRenderComplete = false;
13+
let monacoReady = false;
1314

1415
// Load required stylesheets
1516
function loadStyles() {
@@ -31,25 +32,88 @@
3132
});
3233
}
3334

34-
// Load required scripts
35-
function loadScripts() {
35+
// Load Monaco Editor first with proper sequencing
36+
function loadMonacoEditor() {
37+
return new Promise((resolve, reject) => {
38+
// First load the Monaco loader
39+
const loaderScript = document.createElement('script');
40+
loaderScript.src = '_content/BlazorMonaco/lib/monaco-editor/min/vs/loader.js';
41+
loaderScript.onload = () => {
42+
// Configure RequireJS paths for Monaco
43+
if (typeof require !== 'undefined') {
44+
require.config({
45+
paths: {
46+
'vs': '_content/BlazorMonaco/lib/monaco-editor/min/vs'
47+
}
48+
});
49+
50+
// Load Monaco editor main
51+
require(['vs/editor/editor.main'], () => {
52+
console.log('Monaco editor loaded successfully');
53+
monacoReady = true;
54+
resolve();
55+
}, (error) => {
56+
console.error('Failed to load Monaco editor:', error);
57+
reject(error);
58+
});
59+
} else {
60+
// Fallback: load editor.main.js directly
61+
const editorScript = document.createElement('script');
62+
editorScript.src = '_content/BlazorMonaco/lib/monaco-editor/min/vs/editor/editor.main.js';
63+
editorScript.onload = () => {
64+
console.log('Monaco editor loaded (fallback method)');
65+
monacoReady = true;
66+
resolve();
67+
};
68+
editorScript.onerror = reject;
69+
document.body.appendChild(editorScript);
70+
}
71+
};
72+
loaderScript.onerror = reject;
73+
document.body.appendChild(loaderScript);
74+
});
75+
}
76+
77+
// Load remaining scripts after Monaco is ready
78+
function loadOtherScripts() {
3679
const scripts = [
3780
'_content/BlazorMonaco/jsInterop.js',
38-
'_content/BlazorMonaco/lib/monaco-editor/min/vs/loader.js',
39-
'_content/BlazorMonaco/lib/monaco-editor/min/vs/editor/editor.main.js',
4081
'_content/MudBlazor/MudBlazor.min.js',
4182
'_content/CodeBeam.MudBlazor.Extensions/MudExtensions.min.js',
4283
'_content/Radzen.Blazor/Radzen.Blazor.js',
4384
'_framework/blazor.server.js'
4485
];
4586

46-
scripts.forEach(src => {
47-
if (!document.querySelector(`script[src="${src}"]`)) {
87+
const loadPromises = scripts.map(src => {
88+
return new Promise((resolve, reject) => {
89+
if (document.querySelector(`script[src="${src}"]`)) {
90+
resolve(); // Already loaded
91+
return;
92+
}
93+
4894
const script = document.createElement('script');
4995
script.src = src;
96+
script.onload = resolve;
97+
script.onerror = reject;
5098
document.body.appendChild(script);
51-
}
99+
});
52100
});
101+
102+
return Promise.all(loadPromises);
103+
}
104+
105+
// Load all scripts in proper sequence
106+
async function loadScripts() {
107+
try {
108+
console.log('Loading Monaco editor...');
109+
await loadMonacoEditor();
110+
console.log('Loading other scripts...');
111+
await loadOtherScripts();
112+
console.log('All scripts loaded successfully');
113+
} catch (error) {
114+
console.error('Script loading failed:', error);
115+
// Continue anyway - some features might still work
116+
}
53117
}
54118

55119
// Inject loading screen HTML
@@ -83,14 +147,6 @@
83147
document.head.insertAdjacentHTML('beforeend', loadingStyle);
84148
}
85149

86-
// Update loading text (minimal usage)
87-
function updateLoadingText(text) {
88-
const loadingTextEl = document.getElementById('elsa-loading-text');
89-
if (loadingTextEl) {
90-
loadingTextEl.textContent = text;
91-
}
92-
}
93-
94150
// Hide loading screen when actually ready
95151
function hideLoadingScreen() {
96152
if (!loadingHidden) {
@@ -102,16 +158,14 @@
102158

103159
// Check if we should hide loading screen
104160
function checkReadiness() {
105-
if (blazorReady && initialRenderComplete && !loadingHidden) {
161+
if (blazorReady && initialRenderComplete && monacoReady && !loadingHidden) {
106162
hideLoadingScreen();
107163
}
108164
}
109165

110166
// Detect when Blazor Server connection is established
111167
function detectBlazorConnection() {
112-
// Check for Blazor global object and connection
113168
if (typeof window.Blazor !== 'undefined') {
114-
// Monitor for SignalR connection
115169
const originalLog = console.log;
116170
console.log = function(...args) {
117171
const message = args.join(' ');
@@ -123,13 +177,11 @@
123177
};
124178
}
125179

126-
// Check for Blazor Server specific DOM changes
127180
const observer = new MutationObserver(function(mutations) {
128181
mutations.forEach(function(mutation) {
129182
if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
130183
for (let node of mutation.addedNodes) {
131184
if (node.nodeType === Node.ELEMENT_NODE) {
132-
// Check for Blazor component markers
133185
if (node.hasAttribute && (
134186
node.hasAttribute('_bl_') ||
135187
node.querySelector && node.querySelector('[_bl_]') ||
@@ -152,7 +204,6 @@
152204
attributes: true
153205
});
154206

155-
// Stop observing after readiness is detected
156207
setTimeout(() => {
157208
if (blazorReady || loadingHidden) {
158209
observer.disconnect();
@@ -162,7 +213,6 @@
162213

163214
// Detect when initial render is complete
164215
function detectRenderCompletion() {
165-
// Check for common Blazor/MudBlazor elements
166216
function checkForMainContent() {
167217
const indicators = [
168218
'.mud-main-content',
@@ -184,7 +234,6 @@
184234
return false;
185235
}
186236

187-
// Use requestAnimationFrame to detect when rendering settles
188237
let frameCount = 0;
189238
let lastBodyHeight = 0;
190239
let stableFrames = 0;
@@ -195,7 +244,7 @@
195244

196245
if (currentHeight === lastBodyHeight && currentHeight > 100) {
197246
stableFrames++;
198-
if (stableFrames >= 5) { // 5 stable frames
247+
if (stableFrames >= 5) {
199248
if (!initialRenderComplete && checkForMainContent()) {
200249
return;
201250
} else if (!initialRenderComplete && frameCount > 30) {
@@ -212,16 +261,13 @@
212261
if (frameCount < 100 && !initialRenderComplete) {
213262
requestAnimationFrame(checkRenderStability);
214263
} else if (!initialRenderComplete) {
215-
// Fallback after 100 frames
216264
initialRenderComplete = true;
217265
checkReadiness();
218266
}
219267
}
220268

221-
// Start checking on next frame
222269
requestAnimationFrame(checkRenderStability);
223270

224-
// Also check periodically
225271
const intervalCheck = setInterval(() => {
226272
if (checkForMainContent()) {
227273
clearInterval(intervalCheck);
@@ -233,29 +279,32 @@
233279

234280
// Enhanced Blazor Server initialization
235281
function initializeBlazorServer(maxWaitMs) {
236-
maxWaitMs = maxWaitMs || 8000; // Fallback timeout
282+
maxWaitMs = maxWaitMs || 8000;
237283

238-
// Start detection methods
239284
setTimeout(() => detectBlazorConnection(), 100);
240285
setTimeout(() => detectRenderCompletion(), 500);
241286

242-
// Ultimate fallback timeout
243287
setTimeout(function() {
244288
if (!loadingHidden) {
245289
console.warn('Fallback timeout reached - forcing loading screen to hide');
246290
blazorReady = true;
247291
initialRenderComplete = true;
292+
monacoReady = true; // Force ready on timeout
248293
hideLoadingScreen();
249294
}
250295
}, maxWaitMs);
251296
}
252297

253-
// Initialize everything
254-
function initialize() {
298+
// Initialize everything with proper sequencing
299+
async function initialize() {
300+
console.log('Starting Elsa Studio initialization...');
255301
loadStyles();
256302
injectLoadingScreen();
257-
loadScripts();
258-
initializeBlazorServer(8000);
303+
304+
// Load scripts asynchronously but track completion
305+
loadScripts(); // Don't await - let it load in background
306+
307+
initializeBlazorServer(10000); // Give more time for Monaco loading
259308
}
260309

261310
// Run initialization
@@ -265,13 +314,13 @@
265314
initialize();
266315
}
267316

268-
// Expose API for manual control if needed
317+
// Expose API
269318
window.ElsaStudio = window.ElsaStudio || {};
270319
window.ElsaStudio.hideLoading = hideLoadingScreen;
271-
window.ElsaStudio.updateLoadingText = updateLoadingText;
272320
window.ElsaStudio.forceReady = function() {
273321
blazorReady = true;
274322
initialRenderComplete = true;
323+
monacoReady = true;
275324
checkReadiness();
276325
};
277326

0 commit comments

Comments
 (0)