之前配置服务器的时候不知道哪根筋搭错了,非要想在nginx原版里面把请求合并给弄进去,终于在不知道什么原因的作用下达成了把软件搞崩的结果。
目前的情况就是请求数不管怎么配置,总是会出现503。看了服务器自带的防CC,显然不太可能是它出手了。
排查了一个多月以后,我彻底摆烂了,对自己的又菜又爱玩有了更深刻的认知。
在放飞自我了一段时间后,突然想到请求数大部分是来自于图片,如果能让图片不在同一时间向服务器发起请求,那么不就基本能减少503吗(好吧,实际上还是会莫名其妙有503,就当玄学看了)?
好吧,说干就干。
先对正文图片的格式进行改造。
初始格式:
<img src="此处为图片的实际url"/>
改造后的格式:
<img src="data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=" class="lazyload" data-src="此处为图片的实际url" />
在页面引用的js文件中加入以下魔改后的代码(为了不影响页面加载,可以放在body的尾部某个位置):
/** Lazy Load https://appelsiini.net/projects/lazyload Version: 2.0.0-rc.2 * */
(function(root, factory) {
if (typeof exports === "object") {
module.exports = factory(root);
} else if (typeof define === "function" && define.amd) {
define([], factory);
} else {
root.LazyLoad = factory(root);
}
}
)(typeof global !== "undefined" ? global : this.window || this.global, function(root) {
"use strict";
if (typeof define === "function" && define.amd) {
root = window;
}
const defaults = {
src: "data-src",
srcset: "data-srcset",
selector: ".lazyload",
root: null,
rootMargin: "0px",
threshold: 0,
delay: 200 // 默认延迟200毫秒
};
const extend = function() {
let extended = {};
let deep = false;
let i = 0;
let length = arguments.length;
if (Object.prototype.toString.call(arguments[0]) === "[object Boolean]") {
deep = arguments[0];
i++;
}
let merge = function(obj) {
for (let prop in obj) {
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
if (deep && Object.prototype.toString.call(obj[prop]) === "[object Object]") {
extended[prop] = extend(true, extended[prop], obj[prop]);
} else {
extended[prop] = obj[prop];
}
}
}
};
for (; i < length; i++) {
let obj = arguments[i];
merge(obj);
}
return extended;
};
function LazyLoad(images, options) {
this.settings = extend(defaults, options || {});
this.images = images || document.querySelectorAll(this.settings.selector);
this.observer = null;
this.queue = [];
// 新增队列
this.isProcessing = false;
// 是否正在处理队列
this.lastLoadTime = 0;
// 记录上一次加载完成的时间
this.init();
}
LazyLoad.prototype = {
init: function() {
if (!root.IntersectionObserver) {
this.loadImages();
return;
}
let self = this;
let observerConfig = {
root: this.settings.root,
rootMargin: this.settings.rootMargin,
threshold: [this.settings.threshold]
};
this.observer = new IntersectionObserver(function(entries) {
Array.prototype.forEach.call(entries, function(entry) {
if (entry.isIntersecting) {
self.observer.unobserve(entry.target);
// 将图片加入队列
self.queue.push(entry.target);
// 如果未在处理队列,则开始处理
if (!self.isProcessing) {
self.processQueue();
}
}
});
}
,observerConfig);
Array.prototype.forEach.call(this.images, function(image) {
self.observer.observe(image);
});
},
processQueue: function() {
if (this.queue.length === 0) {
this.isProcessing = false;
return;
}
this.isProcessing = true;
const now = Date.now();
const timeSinceLastLoad = now - this.lastLoadTime;
// 计算需要等待的时间
const waitTime = Math.max(0, this.settings.delay - timeSinceLastLoad);
setTimeout( () => {
// 从队列中取出第一张图片
const image = this.queue.shift();
const src = image.getAttribute(this.settings.src);
const srcset = image.getAttribute(this.settings.srcset);
if ("img" === image.tagName.toLowerCase()) {
if (src) {
image.src = src;
}
if (srcset) {
image.srcset = srcset;
}
} else {
image.style.backgroundImage = "url(" + src + ")";
}
// 更新最后加载完成时间
this.lastLoadTime = Date.now();
// 处理下一张图片
this.processQueue();
}
, waitTime);
},
loadAndDestroy: function() {
if (!this.settings) {
return;
}
this.loadImages();
this.destroy();
},
loadImages: function() {
if (!this.settings) {
return;
}
let self = this;
Array.prototype.forEach.call(this.images, function(image) {
let src = image.getAttribute(self.settings.src);
let srcset = image.getAttribute(self.settings.srcset);
if ("img" === image.tagName.toLowerCase()) {
if (src) {
image.src = src;
}
if (srcset) {
image.srcset = srcset;
}
} else {
image.style.backgroundImage = "url('" + src + "')";
}
});
},
destroy: function() {
if (!this.settings) {
return;
}
this.observer.disconnect();
this.settings = null;
}
};
root.lazyload = function(images, options) {
return new LazyLoad(images,options);
}
;
if (root.jQuery) {
const $ = root.jQuery;
$.fn.lazyload = function(options) {
options = options || {};
options.attribute = options.attribute || "data-src";
new LazyLoad($.makeArray(this),options);
return this;
}
;
}
return LazyLoad;
});
记得要插在jquery后面。
在需要使用懒加载的页面插入以下代码(以下代码要保证在:
$('img.lazyload').lazyload({ delay: 400 });
dely后面的参数是上一张图片开始加载后多少毫秒开始加载下一张图片(原则上是上一张加载完成后开始计时,不过实际上嘛……反正差不多能用就行了,哈哈哈,不要太在意细节)。
对了,整个逻辑就是把可视区域class="lazyload"的图片排序,按照先后逐步加载。
非常感谢大佬的原始代码。
发表评论