开篇废话
这几天在弄 ugoira.huggy.moe 的前端,本质是个很简单的网页,就是给出 pixiv 的动图 mp4 格式 然后下载之类的。
整个网页也很简单,使用了 vite.js 和 ef.js 就开搞了
整个网站在打包后甚至在 40kb 以内 平平淡淡才是真
然后就发现了一个问题,一个网页内的视频(也就是 video tag)如果超过 75 个,那么 Chromium 系列浏览器就会拒绝加载余下资源,并且在 console 丢给你一个错误
也就是直接不渲染了
前排💩山警告,提供大概思路,代码是一次性的,未经过优化,请勿直接抄
分析
一开始我想 iframe 套娃的,觉得太麻烦就懒得搞了。
然后老宋在群里提了下 <video>
可以动态加载,从池里抽 DOM
主要逻辑就是这样的:
只加载用户可视页面里面资源,不可见区域的资源使用奇怪的办法占位或者隐藏(删掉)
Twitter 的思路是这样的的:
css: min-height:36519px;
是拿来填充高度的
然后下面的 transform: translateY(4703px);
是拿来当 div 的假高度的
最后效果就是:只在前端可视范围内渲染大概 18 个 Tweet(不知道宽屏或者窄屏幕这个数量会不会变化)
并且滚动没有什么问题,是动态补偿的 每个 Tweet 都被安排得明明白白
而且媒体流都是手动点击才有的
这样的操作就能减少很多渲染压力了,浏览器访问也更不卡了
不过显然我这种简单的站不需要像 Twitter 优化地这么彻底,我们只需要 <video>
按需加载就可以了,文字部分全部留着够了
最后思路:
监听滚动事件,然后动态更新需要渲染的 div 不需要的 div 就直接清空 + 占个高度(不占高度滚动条会很鬼畜)
实践
一开始先写按需渲染的函数,参考
sid
就是要加载的项目,然后 count
是前后加载多少个(默认是4)
然后不在 sid +- count
范围内(如果 sid = 2, count = 2 那么 0 1 2 3 4 会被渲染,其它的不会被渲染)
最后使用了九个 <video>
作为占位的,也就是在一个页面里面最多会出现 9 个 <video>
也就不会有一开始的错误了 页面滚动也许会快点
(原生写法应为 document.createElement('video')
)
然后再监听一下滚动事件或者 1 秒轮询一次
// 如果是监听滚动事件,那么优化要做好来,我直接监听的话滚动就开始卡了(因为滚动一下就会 update 一下)
最后我使用了轮询 也就是 setInterval
拿了个 scroll_Y
当缓存,判断是否需要执行
这里判断 可视的 div offsetTop > Y 时,就喂给前面的按需加载 (videoloader) 函数,这样就加载到了前后 9 个视频了
最后效果:
总结
这种懒加载之前也听说过,不过现在真正写过类似的还是第一次,还是记录下思路。
最终目的就是 减少 DOM 的渲染,减轻浏览器渲染的负担,按照这个思路想就行了。
占位的的长宽我就不太想搞了,所以滚动条还是有点鬼畜的,这个懒得再优化了。(视频的宽度和高度是有的,但是要按照比例缩放之类的,还要根据各种宽度的设备作适配,懒了)
代码最后写糊了,不过还能用就是了,反正功能也不多 全丢在一个 .js 里面了,然后这个项目我想要的功能也基本加完了,如果哪天想到新功能也可以再加下。
完