Skip to content

Commit 9366741

Browse files
vsilentCopilot
andcommitted
web: restore CSS injection and degrade gracefully without WS endpoint
- Use style-loader + css-loader for .css files (fix dashboard styling) - Add css/style loader deps to web package - WebSocket service now falls back to REST-only mode when /ws is unavailable to avoid noisy reconnect/error spam in dev Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a0508b0 commit 9366741

File tree

3 files changed

+20
-6
lines changed

3 files changed

+20
-6
lines changed

web/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@
5858
"@typescript-eslint/parser": "^6.14.0",
5959
"@typescript-eslint/eslint-plugin": "^6.14.0",
6060
"eslint-plugin-react": "^7.33.2",
61-
"eslint-plugin-react-hooks": "^4.6.0"
61+
"eslint-plugin-react-hooks": "^4.6.0",
62+
"style-loader": "^4.0.0",
63+
"css-loader": "^7.1.2"
6264
},
6365
"browserslist": {
6466
"production": [

web/src/services/websocket.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export class WebSocketService {
2626
private reconnectDelay = 1000;
2727
private eventHandlers: Map<WebSocketEvent, Set<EventHandler>> = new Map();
2828
private shouldReconnect = true;
29+
private failedInitialConnect = false;
2930

3031
constructor(url?: string) {
3132
const env = ((globalThis as { __STACKDOG_ENV__?: EnvLike }).__STACKDOG_ENV__ ??
@@ -37,6 +38,10 @@ export class WebSocketService {
3738
connect(): Promise<void> {
3839
return new Promise((resolve, reject) => {
3940
try {
41+
if (this.failedInitialConnect) {
42+
resolve();
43+
return;
44+
}
4045
this.ws = new WebSocket(this.url);
4146

4247
this.ws.onopen = () => {
@@ -56,17 +61,23 @@ export class WebSocketService {
5661

5762
this.ws.onclose = () => {
5863
console.log('WebSocket disconnected');
59-
if (this.shouldReconnect && this.reconnectAttempts < this.maxReconnectAttempts) {
64+
if (!this.failedInitialConnect && this.shouldReconnect && this.reconnectAttempts < this.maxReconnectAttempts) {
6065
this.scheduleReconnect();
6166
}
6267
};
6368

6469
this.ws.onerror = (error) => {
65-
console.error('WebSocket error:', error);
66-
reject(error);
70+
// WebSocket endpoint may be intentionally unavailable in some environments.
71+
// Fall back to REST-only mode after the first failed connect.
72+
this.failedInitialConnect = true;
73+
this.shouldReconnect = false;
74+
console.warn('WebSocket unavailable, running in polling mode');
75+
resolve();
6776
};
6877
} catch (error) {
69-
reject(error);
78+
this.failedInitialConnect = true;
79+
this.shouldReconnect = false;
80+
resolve();
7081
}
7182
});
7283
}
@@ -110,6 +121,7 @@ export class WebSocketService {
110121

111122
disconnect(): void {
112123
this.shouldReconnect = false;
124+
this.failedInitialConnect = false;
113125
if (this.ws) {
114126
this.ws.close();
115127
this.ws = null;

web/webpack.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ module.exports = {
2222
},
2323
{
2424
test: /\.css$/,
25-
type: 'asset/source',
25+
use: ['style-loader', 'css-loader'],
2626
},
2727
],
2828
},

0 commit comments

Comments
 (0)