Files
TankIC/tools/hornet_sw.js
T
TermiNexus 4005213226 feat(tools): 新版本工具链移植 + 本地镜像单包加载,中继改为原样直发与异步有序落盘
- hornet 工具链:无 ght 启动;透视冻结节点拖拽跟随、金箱标记、性能优化;雷达死亡红叉;鼠标稳定器;窗口布局持久化

- 本地镜像:切割与单包加载(pack_unpacked.js)+ SW 单包缓存 + F5 兜底刷新;入口更新为 main.9f4e7a89.js

- 中继 wss_server.js:转发改 socket 反压的原样直发(零等待零缓存);落盘改单条有序异步队列(默认开启);新增反压看门狗(默认 60s)
2026-10-11 19:35:54 +08:00

163 lines
5.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ===== 3DTank Hornet Service Worker =====
// 两个职责:
//
// ① 单包本地缓存(主用途):把 /play/static/js/unpacked/ 下的散装小文件
// (126 个 module_*.js + resources.json)用单个 unpacked.pack.json 就地命中,
// 不再逐个走磁盘小文件。包由 tools/pack_unpacked.js 生成。
// 作用域必须是 /(serve.js 用 Service-Worker-Allowed: / 放行),这样首页 / 发起的
// /play/... 请求才能被接管;加载器会自动注册它。
//
// ② main.*.js 网络层注入(备用):无法改 main 文件时,往 __webpack_require__ 注入
// window.__wp_require__ 捕获行,并追加 hornet_bundle.js 加载。
//
// 卸载:navigator.serviceWorker.getRegistration().then(r => r.unregister()).then(() => location.reload())
var SW_DEBUG = '[Hornet SW]';
var MAIN_JS_PATTERN = /\/main\.[a-f0-9]+\.js$/;
var INJECT_LINE = 'window.__wp_require__=__webpack_require__;';
// 在入口模块加载后注入 hornet_bundle.js
var BUNDLE_MARKER = '__webpack_require__(78231)';
var BUNDLE_INJECT = ';var __hb=document.createElement("script");__hb.src="/play/static/js/unpacked/hornet_bundle.js";document.head.appendChild(__hb);';
// ===== 单包缓存 =====
var PACK_URL = '/play/static/js/unpacked.pack.json';
var PACK_PATH_RE = /^\/play\/static\/js\/unpacked\/(module_\d+\.js|resources\.json)$/;
var PackPromise = null;
var PackMap = null;
var PackVersion = '';
function LoadPack() {
if (PackPromise) return PackPromise;
PackPromise = fetch(PACK_URL, { cache: 'no-cache' })
.then(function (Resp) {
if (!Resp.ok) throw new Error('pack HTTP ' + Resp.status);
return Resp.json();
})
.then(function (Pack) {
PackMap = Pack.files || {};
PackVersion = Pack.version || '';
console.log(SW_DEBUG, '单包已载入: ' + (Pack.count || 0) + ' 个文件 版本=' + PackVersion);
return PackMap;
})
.catch(function (Err) {
console.warn(SW_DEBUG, '单包载入失败(回退逐文件):', Err && Err.message);
PackMap = null;
PackPromise = null; // 允许下次重试
return null;
});
return PackPromise;
}
function PackResponse(Name) {
if (!PackMap) return null;
var Text = PackMap[Name];
if (typeof Text !== 'string') return null;
var Type = /\.json$/.test(Name)
? 'application/json; charset=utf-8'
: 'application/javascript; charset=utf-8';
return new Response(Text, {
status: 200,
headers: {
'Content-Type': Type,
'X-Hornet-Pack': PackVersion,
'Cache-Control': 'no-cache',
},
});
}
self.addEventListener('install', function(event) {
self.skipWaiting();
});
self.addEventListener('activate', function(event) {
event.waitUntil(self.clients.claim());
});
self.addEventListener('fetch', function(event) {
var url = event.request.url;
var PathName = '';
try { PathName = new URL(url).pathname; } catch (Err) {}
// ① 单包命中:散装小文件(126 个模块 + resources.json)一次读包解决
if (PACK_PATH_RE.test(PathName)) {
var Name = PathName.slice(PathName.lastIndexOf('/') + 1);
event.respondWith(
LoadPack().then(function () {
return PackResponse(Name) || fetch(event.request); // 包里没有的才回退网络
}),
);
return;
}
// ② 拦截 main.*.js
if (MAIN_JS_PATTERN.test(url)) {
event.respondWith(
fetch(event.request).then(function(response) {
if (!response.ok) return response;
return response.text().then(function(text) {
// 在 __webpack_require__ 函数定义后注入捕获行
// 匹配模式:function __webpack_require__(t) { ... }
var marker = 'function __webpack_require__(';
var idx = text.indexOf(marker);
if (idx === -1) {
// 尝试 webpack 5 格式
marker = '__webpack_require__ = function';
idx = text.indexOf(marker);
}
if (idx !== -1) {
// 找到函数体的第一个 { 后注入捕获行
var braceIdx = text.indexOf('{', idx);
if (braceIdx !== -1) {
var injectPos = braceIdx + 1;
var modified = text.slice(0, injectPos) + INJECT_LINE + text.slice(injectPos);
// 在入口模块加载后注入 hornet_bundle.js
var bundleIdx = modified.indexOf(BUNDLE_MARKER);
if (bundleIdx !== -1) {
var afterMarker = bundleIdx + BUNDLE_MARKER.length;
modified = modified.slice(0, afterMarker) + BUNDLE_INJECT + modified.slice(afterMarker);
console.log(SW_DEBUG, '注入 __wp_require__ + bundle 加载到', url);
} else {
console.log(SW_DEBUG, '注入 __wp_require__ 捕获行(未找到 bundle marker)', url);
}
return new Response(modified, {
status: response.status,
statusText: response.statusText,
headers: {
'Content-Type': 'application/javascript; charset=utf-8',
'Cache-Control': 'no-cache'
}
});
}
}
console.warn(SW_DEBUG, '未找到 __webpack_require__ 定义,返回原始响应');
return new Response(text, {
status: response.status,
statusText: response.statusText,
headers: response.headers
});
});
}).catch(function(err) {
console.error(SW_DEBUG, '拦截失败:', err);
return fetch(event.request);
})
);
return;
}
// 其他请求正常处理
event.respondWith(fetch(event.request));
});
// 监听消息:手动加载 hornet_bundle
self.addEventListener('message', function(event) {
if (event.data === 'load_bundle') {
self.clients.matchAll().then(function(clients) {
clients.forEach(function(client) {
client.postMessage('load_bundle');
});
});
}
});