pipecraftnet / jsdelivr-auto-fallback Goto Github PK
View Code? Open in Web Editor NEW修复 cdn.jsdelivr.net 无法访问的问题
License: MIT License
修复 cdn.jsdelivr.net 无法访问的问题
License: MIT License
项目地址:hexo-theme-next,之前在_config.next.yml 配置项vendors:internal: jsdelivr配置jsdelivr,如果迁移如何配置,谢谢
比如
<div style="background-image: url("https://cdn.jsdelivr.net/something");"></div>
image {
background-image: url("https://cdn.jsdelivr.net/something");
}
Due to how firefox handle document-start,the test facility of the script won't work.
See greasemonkey/greasemonkey#2515
Here my own modified one that currently works.
// ==UserScript==
// @name Jsdelivr Auto Fallback
// @namespace https://github.com/PipecraftNet/jsdelivr-auto-fallback
// @version 0.2.2
// @author PipecraftNet&DreamOfIce
// @description 修复 cdn.jsdelivr.net 无法访问的问题
// @homepage https://github.com/PipecraftNet/jsdelivr-auto-fallback
// @supportURL https://github.com/PipecraftNet/jsdelivr-auto-fallback/issues
// @license MIT
// @match *://*/*
// @run-at document-start
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
function act() {
'use strict';
let fastNode;
let failed;
let isRunning;
const DEST_LIST = [
'cdn.jsdelivr.net',
'unpkg.com',
'testingcf.jsdelivr.net',
'test1.jsdelivr.net',
'fastly.jsdelivr.net',
'gcore.jsdelivr.net',
];
const PREFIX = '//';
const SOURCE = DEST_LIST[0];
const starTime = Date.now();
const TIMEOUT = 800;
const STORE_KEY = 'jsdelivr-auto-fallback';
const TEST_PATH = '/[email protected]/object.js?';
const shouldReplace = (text) => text && text.includes(PREFIX + SOURCE);
const replace = (text) => text.replace(PREFIX + SOURCE, PREFIX + fastNode);
const setTimeout = window.setTimeout;
const $ = document.querySelectorAll.bind(document);
const replaceElementSrc = () => {
let element;
let value;
for (element of $('link[rel="stylesheet"]')) {
value = element.href;
if (shouldReplace(value) && !value.includes(TEST_PATH)) {
element.href = replace(value);
}
}
for (element of $('script')) {
value = element.src;
if (shouldReplace(value)) {
const newNode = document.createElement('script');
newNode.src = replace(value);
element.defer = true;
element.src = '';
element.before(newNode);
element.remove();
}
}
for (element of $('img')) {
value = element.src;
if (shouldReplace(value)) {
// Used to cancel loading. Without this line it will remain pending status.
element.src = '';
element.src = replace(value);
}
}
// All elements that have a style attribute
for (element of $('*[style]')) {
value = element.getAttribute('style');
if (shouldReplace(value)) {
element.setAttribute('style', replace(value));
}
}
for (element of $('style')) {
value = element.innerHTML;
if (shouldReplace(value)) {
element.innerHTML = replace(value);
}
}
};
const tryReplace = () => {
if (!isRunning && failed && fastNode) {
console.warn(SOURCE + ' is not available. Use ' + fastNode);
isRunning = true;
setTimeout(replaceElementSrc, 0);
// Some need to wait for a while
setTimeout(replaceElementSrc, 20);
// Replace dynamically added elements
setInterval(replaceElementSrc, 500);
}else{
console.log("Use original target.");
}
};
const checkAvailable = (url, callback) => {
let timeoutId;
const newNode = document.createElement('link');
const handleResult = (isSuccess) => {
if (!timeoutId) {
return;
}
clearTimeout(timeoutId);
timeoutId = 0;
// Used to cancel loading. Without this line it will remain pending status.
if (!isSuccess) newNode.href = 'data:text/plain;base64,';
newNode.remove();
callback(isSuccess);
console.log(url + " is Ok..");
};
timeoutId = setTimeout(handleResult, TIMEOUT);
newNode.addEventListener('error', () => handleResult(false));
newNode.addEventListener('load', () => handleResult(true));
newNode.rel = 'prefetch';
newNode.text = 'text/javascript';
newNode.href = url + TEST_PATH + starTime;
console.log("Testing .. " + url);
if(document.head !== null) {
document.head.insertAdjacentElement('afterbegin', newNode);
}else{
console.log("DOM not fully ready!");
}
};
const cached = (() => {
try {
// eslint-disable-next-line new-cap
return Object.assign({}, GM_getValue(STORE_KEY));
} catch {
return {};
}
})();
const main = () => {
cached.time = starTime;
cached.failed = false;
cached.fastNode = null;
for (const url of DEST_LIST) {
checkAvailable('https://' + url, (isAvailable) => {
// console.log(url, Date.now() - starTime, Boolean(isAvailable));
if (!isAvailable && url === SOURCE) {
failed = true;
cached.failed = true;
}
if (isAvailable && !fastNode) {
fastNode = url;
}
if (isAvailable && !cached.fastNode) {
cached.fastNode = url;
}
tryReplace();
});
}
setTimeout(() => {
// If all domains are timeout
if (failed && !fastNode) {
fastNode = DEST_LIST[1];
tryReplace();
}
// eslint-disable-next-line new-cap
GM_setValue(STORE_KEY, cached);
}, TIMEOUT + 200);
};
if (
cached.time &&
starTime - cached.time < 60 * 60 * 1000 &&
cached.failed &&
cached.fastNode
) {
failed = true;
fastNode = cached.fastNode;
tryReplace();
setTimeout(main, 1000);
} else {
main();
}
}
const observer = new MutationObserver(() => {
if(document.head !== null) {
observer.disconnect();
act();
console.log("Head is OK now");
}
});
const observerOptions = {
childList: true,
subtree: true,
};
observer.observe(document,observerOptions);
可以提高访问速度,可以避免 gcore.jsdelivr.net 不可用时,仍能正常显示网站。
已知备选可用域名:
结果保存一天。
记录用到这个项目的地方,方便有必要的更新时,提醒对方修改。
如果有其他项目用到了,请以评论方式补充。
如题,昨天下午开始我的镜像站也开始被墙了
详见 jsdelivr/jsdelivr#18397 (comment)
晚点我会更新一下脚本,顺带加一些别的镜像站
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.