使用coi-serviceworker用于无法控制标头的情况
This commit is contained in:
15
.github/workflows/docs.yml
vendored
15
.github/workflows/docs.yml
vendored
@@ -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:
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
/*
|
|
||||||
Cross-Origin-Embedder-Policy: require-corp
|
|
||||||
Cross-Origin-Opener-Policy: same-origin
|
|
||||||
118
docs/public/coi-serviceworker.js
Normal file
118
docs/public/coi-serviceworker.js
Normal 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);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
@@ -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
7
package-lock.json
generated
@@ -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",
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user