@quicktvui/web-cli 2.2.0 → 2.4.0
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.
|
@@ -292,6 +292,124 @@
|
|
|
292
292
|
// 页面加载后的冷却期:这段时间内忽略 bundle-update 事件
|
|
293
293
|
// 防止 SSE 重连后收到缓存的旧 bundle-update 导致无限刷新
|
|
294
294
|
var sseCooldownUntil = Date.now() + 3000; // 3 秒冷却期
|
|
295
|
+
|
|
296
|
+
// ========== CORS 代理 ==========
|
|
297
|
+
// 在 web-cli dev 模式下,拦截所有跨域 fetch/XHR/Image 请求,
|
|
298
|
+
// 转换为 /proxy/ 路径由 DevServer 代理转发,解决浏览器 CORS 限制
|
|
299
|
+
// TV 原生环境无 CORS 限制,但浏览器中所有外部请求都会被拦截
|
|
300
|
+
(function initDevProxy() {
|
|
301
|
+
var LOCAL_ORIGIN = window.location.origin;
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* 判断 URL 是否为跨域请求(需要代理)
|
|
305
|
+
* 排除 data:, blob:, javascript:, about: 等非 HTTP 协议 URL
|
|
306
|
+
*/
|
|
307
|
+
function isCrossOrigin(url) {
|
|
308
|
+
if (!url || typeof url !== 'string') return false;
|
|
309
|
+
// 非网络协议的 URL 不需要代理
|
|
310
|
+
if (/^(data|blob|javascript|about):/i.test(url)) return false;
|
|
311
|
+
try {
|
|
312
|
+
var urlObj = new URL(url, window.location.href);
|
|
313
|
+
// 非 http/https 协议也不代理
|
|
314
|
+
if (urlObj.protocol !== 'http:' && urlObj.protocol !== 'https:') return false;
|
|
315
|
+
return urlObj.origin !== LOCAL_ORIGIN;
|
|
316
|
+
} catch (e) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* 将跨域 URL 转换为代理路径
|
|
323
|
+
* https://api.example.com/v1/data?a=1 → /proxy/https/api.example.com/v1/data?a=1
|
|
324
|
+
*/
|
|
325
|
+
function toProxyUrl(url) {
|
|
326
|
+
try {
|
|
327
|
+
var urlObj = new URL(url, window.location.href);
|
|
328
|
+
// 只代理 http/https 协议
|
|
329
|
+
if (urlObj.protocol !== 'http:' && urlObj.protocol !== 'https:') return url;
|
|
330
|
+
var proxyPath = '/proxy/' + urlObj.protocol.replace(':', '') + '/' + urlObj.host + urlObj.pathname + urlObj.search + urlObj.hash;
|
|
331
|
+
return proxyPath;
|
|
332
|
+
} catch (e) {
|
|
333
|
+
return url;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// ===== 38989 debug server URL 转换 =====
|
|
338
|
+
// es3-vue 在非生产环境下会将 assets/xxx 转换为 http://127.0.0.1:38989/assets/xxx
|
|
339
|
+
// 但在 web 环境下这些资源就在 dist/dev/assets/ 中,应转为相对路径
|
|
340
|
+
var DEBUG_SERVER_RE = /https?:\/\/[^/:]+:38989\//;
|
|
341
|
+
function convertDebugServerUrl(url) {
|
|
342
|
+
if (typeof url === 'string' && DEBUG_SERVER_RE.test(url)) {
|
|
343
|
+
var converted = url.replace(DEBUG_SERVER_RE, './');
|
|
344
|
+
console.log('[DevProxy] 38989 URL converted:', url, '->', converted);
|
|
345
|
+
return converted;
|
|
346
|
+
}
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// ===== 拦截 fetch =====
|
|
351
|
+
var originalFetch = window.fetch;
|
|
352
|
+
window.fetch = function(input, init) {
|
|
353
|
+
var url = (typeof input === 'string') ? input : (input && input.url ? input.url : input);
|
|
354
|
+
// 优先处理 38989 debug server URL → 相对路径
|
|
355
|
+
var debugConverted = convertDebugServerUrl(url);
|
|
356
|
+
if (debugConverted) {
|
|
357
|
+
if (typeof input === 'string') {
|
|
358
|
+
input = debugConverted;
|
|
359
|
+
} else if (input instanceof Request) {
|
|
360
|
+
input = new Request(debugConverted, init || {});
|
|
361
|
+
}
|
|
362
|
+
} else if (isCrossOrigin(url)) {
|
|
363
|
+
var proxyUrl = toProxyUrl(url);
|
|
364
|
+
console.log('[DevProxy] fetch:', url, '->', proxyUrl);
|
|
365
|
+
if (typeof input === 'string') {
|
|
366
|
+
input = proxyUrl;
|
|
367
|
+
} else if (input instanceof Request) {
|
|
368
|
+
input = new Request(proxyUrl, init || {});
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return originalFetch.call(this, input, init);
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
// ===== 拦截 XMLHttpRequest =====
|
|
375
|
+
var originalXHROpen = XMLHttpRequest.prototype.open;
|
|
376
|
+
XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
|
|
377
|
+
// 优先处理 38989 debug server URL → 相对路径
|
|
378
|
+
var debugConverted = convertDebugServerUrl(url);
|
|
379
|
+
if (debugConverted) {
|
|
380
|
+
url = debugConverted;
|
|
381
|
+
} else if (isCrossOrigin(url)) {
|
|
382
|
+
var proxyUrl = toProxyUrl(url);
|
|
383
|
+
console.log('[DevProxy] XHR:', url, '->', proxyUrl);
|
|
384
|
+
url = proxyUrl;
|
|
385
|
+
}
|
|
386
|
+
return originalXHROpen.call(this, method, url, async !== false, user, password);
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
// ===== 拦截 Image src =====
|
|
390
|
+
var originalImageSrcDescriptor = Object.getOwnPropertyDescriptor(HTMLImageElement.prototype, 'src');
|
|
391
|
+
if (originalImageSrcDescriptor && originalImageSrcDescriptor.set) {
|
|
392
|
+
Object.defineProperty(HTMLImageElement.prototype, 'src', {
|
|
393
|
+
...originalImageSrcDescriptor,
|
|
394
|
+
set(value) {
|
|
395
|
+
// 优先处理 38989 debug server URL → 相对路径
|
|
396
|
+
var debugConverted = convertDebugServerUrl(value);
|
|
397
|
+
if (debugConverted) {
|
|
398
|
+
return originalImageSrcDescriptor.set.call(this, debugConverted);
|
|
399
|
+
}
|
|
400
|
+
if (isCrossOrigin(value)) {
|
|
401
|
+
var proxyUrl = toProxyUrl(value);
|
|
402
|
+
console.log('[DevProxy] Image:', value, '->', proxyUrl);
|
|
403
|
+
return originalImageSrcDescriptor.set.call(this, proxyUrl);
|
|
404
|
+
}
|
|
405
|
+
return originalImageSrcDescriptor.set.call(this, value);
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
console.log('[DevProxy] CORS proxy initialized - all cross-origin requests will be proxied');
|
|
411
|
+
})();
|
|
412
|
+
|
|
295
413
|
if (window.__BUNDLE_CONFIG__ && window.__BUNDLE_CONFIG__.watch) {
|
|
296
414
|
try {
|
|
297
415
|
var sse = new EventSource(window.__BUNDLE_CONFIG__.sseEndpoint);
|