使用coi-serviceworker用于无法控制标头的情况

This commit is contained in:
YHH
2025-09-28 21:11:17 +08:00
parent d48b22c656
commit 66dc9780b9
7 changed files with 156 additions and 66 deletions

View File

@@ -50,21 +50,6 @@ jobs:
- name: Build documentation - name: Build documentation
run: npm run docs:build run: npm run docs:build
- name: Add COOP/COEP headers for SharedArrayBuffer support
run: |
# Create _headers file for Netlify compatibility
echo "/*" > docs/.vitepress/dist/_headers
echo " Cross-Origin-Embedder-Policy: require-corp" >> docs/.vitepress/dist/_headers
echo " Cross-Origin-Opener-Policy: same-origin" >> docs/.vitepress/dist/_headers
# Create .htaccess file for Apache compatibility (GitHub Pages sometimes uses this)
echo "Header always set Cross-Origin-Embedder-Policy require-corp" > docs/.vitepress/dist/.htaccess
echo "Header always set Cross-Origin-Opener-Policy same-origin" >> docs/.vitepress/dist/.htaccess
# Create a meta tag fallback in a headers.html file that can be included
echo '<meta http-equiv="Cross-Origin-Embedder-Policy" content="require-corp">' > docs/.vitepress/dist/headers.html
echo '<meta http-equiv="Cross-Origin-Opener-Policy" content="same-origin">' >> docs/.vitepress/dist/headers.html
- name: Upload artifact - name: Upload artifact
uses: actions/upload-pages-artifact@v3 uses: actions/upload-pages-artifact@v3
with: with:

View File

@@ -1,3 +0,0 @@
/*
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin

View File

@@ -0,0 +1,118 @@
/*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */
let coepCredentialless = false;
if (typeof window === 'undefined') {
self.addEventListener("install", () => self.skipWaiting());
self.addEventListener("activate", (event) => event.waitUntil(self.clients.claim()));
self.addEventListener("message", (ev) => {
if (!ev.data) {
return;
} else if (ev.data.type === "deregister") {
self.registration
.unregister()
.then(() => {
return self.clients.matchAll();
})
.then(clients => {
clients.forEach((client) => client.navigate(client.url));
});
} else if (ev.data.type === "coepCredentialless") {
coepCredentialless = ev.data.value;
}
});
self.addEventListener("fetch", function (event) {
const r = event.request;
if (r.cache === "only-if-cached" && r.mode !== "same-origin") {
return;
}
const request = (coepCredentialless && r.mode === "no-cors")
? new Request(r, {
credentials: "omit",
})
: r;
event.respondWith(
fetch(request)
.then((response) => {
if (response.status === 0) {
return response;
}
const newHeaders = new Headers(response.headers);
newHeaders.set("Cross-Origin-Embedder-Policy",
coepCredentialless ? "credentialless" : "require-corp"
);
if (!coepCredentialless) {
newHeaders.set("Cross-Origin-Resource-Policy", "cross-origin");
}
newHeaders.set("Cross-Origin-Opener-Policy", "same-origin");
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: newHeaders,
});
})
.catch((e) => console.error(e))
);
});
} else {
(() => {
// You can customize the behavior of this script through a global `coi` variable.
const coi = {
shouldRegister: () => true,
shouldDeregister: () => false,
coepCredentialless: () => !(window.chrome || window.netscape),
doReload: () => window.location.reload(),
quiet: false,
...window.coi
};
const n = navigator;
if (n.serviceWorker && n.serviceWorker.controller) {
n.serviceWorker.controller.postMessage({
type: "coepCredentialless",
value: coi.coepCredentialless(),
});
if (coi.shouldDeregister()) {
n.serviceWorker.controller.postMessage({ type: "deregister" });
}
}
// If we're already coi: do nothing. Perhaps it's due to this script doing its job, or COOP/COEP are
// already set from the origin server. Also if the browser has no notion of crossOriginIsolated, just give up here.
if (window.crossOriginIsolated !== false || !coi.shouldRegister()) return;
if (!window.isSecureContext) {
!coi.quiet && console.log("COOP/COEP Service Worker not registered, a secure context is required.");
return;
}
// In some environments (e.g. Chrome incognito mode) this won't be available
if (n.serviceWorker) {
n.serviceWorker.register(window.document.currentScript.src).then(
(registration) => {
!coi.quiet && console.log("COOP/COEP Service Worker registered", registration.scope);
registration.addEventListener("updatefound", () => {
!coi.quiet && console.log("Reloading page to make use of updated COOP/COEP Service Worker.");
coi.doReload();
});
// If the registration is active, but it's not controlling the page
if (registration.active && !n.serviceWorker.controller) {
!coi.quiet && console.log("Reloading page to make use of COOP/COEP Service Worker.");
coi.doReload();
}
},
(err) => {
!coi.quiet && console.error("COOP/COEP Service Worker failed to register:", err);
}
);
}
})();
}

View File

@@ -173,17 +173,38 @@
</div> </div>
</div> </div>
<!-- 使用 coi-serviceworker 启用 SharedArrayBuffer 支持 -->
<script src="/ecs-framework/coi-serviceworker.js"></script>
<script> <script>
// Register Service Worker for SharedArrayBuffer support on GitHub Pages // Check SharedArrayBuffer support and display info
if ('serviceWorker' in navigator) { function checkSharedArrayBufferSupport() {
navigator.serviceWorker.register('/ecs-framework/sw.js') const hasSharedArrayBuffer = typeof SharedArrayBuffer !== 'undefined';
.then((registration) => { const isCrossOriginIsolated = self.crossOriginIsolated || false;
console.log('Service Worker registered for SharedArrayBuffer support:', registration); const isLocalhost = location.hostname === 'localhost' || location.hostname === '127.0.0.1';
}) const isGitHubPages = location.hostname === 'esengine.github.io';
.catch((error) => {
console.log('Service Worker registration failed:', error); console.log('=== SharedArrayBuffer 支持检测 ===');
}); console.log('SharedArrayBuffer 存在:', hasSharedArrayBuffer);
console.log('跨域隔离状态:', isCrossOriginIsolated);
console.log('是否本地环境:', isLocalhost);
console.log('是否 GitHub Pages:', isGitHubPages);
if (hasSharedArrayBuffer && isCrossOriginIsolated) {
console.log('✅ SharedArrayBuffer 功能已启用!');
console.log('系统将使用高性能的 SharedArrayBuffer 模式');
} else if (isGitHubPages) {
console.log(' 如果页面刷新,可能是 coi-serviceworker 正在设置跨域隔离');
console.log('刷新后 SharedArrayBuffer 应该可用');
} }
return hasSharedArrayBuffer && isCrossOriginIsolated;
}
// Run check after page load
window.addEventListener('load', () => {
setTimeout(checkSharedArrayBufferSupport, 1000);
});
</script> </script>
</body> </body>
</html> </html>

View File

@@ -1,39 +0,0 @@
// Service Worker to add COOP/COEP headers for SharedArrayBuffer support
// This is a workaround for GitHub Pages which doesn't support custom headers
self.addEventListener('fetch', (event) => {
// Only handle requests for this origin
if (!event.request.url.startsWith(self.location.origin)) {
return;
}
event.respondWith(
fetch(event.request).then((response) => {
// Clone the response to modify headers
const newResponse = new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: {
...Object.fromEntries(response.headers.entries()),
'Cross-Origin-Embedder-Policy': 'require-corp',
'Cross-Origin-Opener-Policy': 'same-origin'
}
});
return newResponse;
}).catch((error) => {
console.error('Service Worker fetch failed:', error);
return fetch(event.request);
})
);
});
self.addEventListener('install', (event) => {
console.log('Service Worker: Installing for SharedArrayBuffer support');
self.skipWaiting();
});
self.addEventListener('activate', (event) => {
console.log('Service Worker: Activated for SharedArrayBuffer support');
event.waitUntil(self.clients.claim());
});

7
package-lock.json generated
View File

@@ -14,6 +14,7 @@
"dependencies": { "dependencies": {
"@types/multer": "^1.4.13", "@types/multer": "^1.4.13",
"@types/ws": "^8.18.1", "@types/ws": "^8.18.1",
"coi-serviceworker": "^0.1.7",
"protobufjs": "^7.5.3", "protobufjs": "^7.5.3",
"reflect-metadata": "^0.2.2", "reflect-metadata": "^0.2.2",
"ws": "^8.18.2" "ws": "^8.18.2"
@@ -6606,6 +6607,12 @@
"node": ">= 0.12.0" "node": ">= 0.12.0"
} }
}, },
"node_modules/coi-serviceworker": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/coi-serviceworker/-/coi-serviceworker-0.1.7.tgz",
"integrity": "sha512-bjSUqEngCPOkErY2vbyWsaIGCNRODYzlNycaREVw5s12/C8SM+RnRUUeX6pZbTtov6C52ZLY/+tvHK+BDxuUuA==",
"license": "MIT"
},
"node_modules/collect-v8-coverage": { "node_modules/collect-v8-coverage": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",

View File

@@ -90,6 +90,7 @@
"dependencies": { "dependencies": {
"@types/multer": "^1.4.13", "@types/multer": "^1.4.13",
"@types/ws": "^8.18.1", "@types/ws": "^8.18.1",
"coi-serviceworker": "^0.1.7",
"protobufjs": "^7.5.3", "protobufjs": "^7.5.3",
"reflect-metadata": "^0.2.2", "reflect-metadata": "^0.2.2",
"ws": "^8.18.2" "ws": "^8.18.2"