在网站上进行响应式内容加载

哈Ha!

我正在为我的项目建立一个网站。 在网站上,您需要同时显示很多GIF,每个GIF都很好。 如果一次显示所有内容,则页面加载时间很长。 同时,提供没有GIF的页面(以便可以在此处下载)也是不可能的。

任何对我如何处理此问题感兴趣的人,我都会要求猫。

其实问题是


就像我说的,网站上有非常多的gif,不同而不同。 您可以自己查看其中的多少个: reface.tech

图片

看到该着陆程序的Beta版后,我立即遇到了加载问题:对于某些用户,页面已加载了很长时间。 对于一个严肃的企业,当然不是这样。

有必要以某种方式解决这个问题。 简单的无损压缩是不可能实现的,因为那时所有媒体内容都已经通过compressor.io驱动了。 因此,有必要压缩损失并赋予GIF较差的质量。

但是向拥有良好互联网的用户提供不良媒体内容是一种牺牲。 因此,决定以某种方式确定Internet的速度,并根据速度来确定适当的质量。

我们做一个粗略的草图


我们将有一个数组,其中包含要加载的媒体内容的描述。

一个例子:

[ { "large": { "size": 0.6211118698120117, "url": "gifs/control/large/control_1.gif" }, "middle": { "size": 0.5330495834350586, "url": "gifs/control/middle/control_1.gif" }, "small": { "size": 0.4901447296142578, "url": "gifs/control/small/control_1.gif" } } ] 

在适当质量的基本要素中,这里是url和文件大小。

我们将简单地:

  1. 遍历数组(加载页面时)
  2. 阅读每种质量等级加载的总大小
  3. 确定是否会在4秒内加载所有内容(这是个人困扰我的时间)

因此,有必要:

  1. 看到了某种东西,它将组成这样一个数组,以便一切都不会用笔计算(在python中)
  2. 看到互联网速度

锯速表


这将相对简单。 我们在浏览器的地址栏中输入eu.httpbin.org/stream-bytes/51200 。 下载长度为51200字节的文件。 我们在公共场合将其推向自己(以衡量托管的速度)。

现在我们需要检查文件摆动了多少。 我们将为此提供一个简单的函数,它将以兆字节每秒的速度返回给我们。

 async checkDownloadSpeed(baseUrl, fileSizeInBytes) { return new Promise((resolve, _) => { let startTime = new Date().getTime(); return axios.get(baseUrl).then( response => { const endTime = new Date().getTime(); const duration = (endTime - startTime) / 1000; const bytesPerSecond = (fileSizeInBytes / duration); const megabytesPerSecond = (bytesPerSecond / 1000 / 1000); resolve(megabytesPerSecond); }); }).catch(error => { throw new Error(error); }); } 

也就是说,我们记录了下载的开始时间,结束时间,并测量了差异,并且,由于我们知道文件的大小,因此只需对其进行划分即可。

现在,我们将编写一个将以特定速度执行操作的函数:

 async getNetworkDownloadSpeed() { const baseUrl = process.env.PUBLIC_URL + '/51200'; const fileSize = 51200; const speed = await this.checkDownloadSpeed(baseUrl, fileSize); console.log("Network speed: " + speed); if (speed.mbps === "Infinity") { SpeedMeasure.speed = 1; } else { SpeedMeasure.speed = speed * 5; } } 

通常,此代码存在一个问题:由于文件较小,因此无法确定确切的连接速度。 但是下载更多内容对我们来说太昂贵了,因此我们只需将结果速度乘以5。即使有余地,我们也可以接受,因为实际上速度会更高。

现在,我们将提交一个函数,该函数将根据速度来确定相应的质量:

  static getResolution(gifsArray) { let totalSizeLevel1 = 0; let totalSizeLevel2 = 0; let totalSizeLevel3 = 0; for (let i = 0; i < gifsArray.length; i++) { for (let a = 0; a < gifsArray[i].length; a++) { let element = gifsArray[i][a]; totalSizeLevel1 += element.small.size; totalSizeLevel2 += element.middle.size; totalSizeLevel3 += element.large.size; } } if (isNaN(SpeedMeasure.speed)) { SpeedMeasure.speed = 1; } let timeLevel1 = totalSizeLevel1 / SpeedMeasure.speed; let timeLevel2 = totalSizeLevel2 / SpeedMeasure.speed; let timeLevel3 = totalSizeLevel3 / SpeedMeasure.speed; if (timeLevel3 < APPROPRIATE_TIME_LIMIT) { return "large"; } else if (timeLevel2 < APPROPRIATE_TIME_LIMIT) { return "middle"; } else { return "small"; } } 

由于计算速度的函数与我们异步,因此SpeedMeasure.speed可能为零。 默认情况下,我们认为连接速度为每秒1 MB。 当函数计算速度时,我们只是重新渲染容器。

我们将数组的数组传递给getResolution函数。 怎么了 因为如果页面上有多个容器,将数组中的相应内容传输到每个容器中比较方便,但是我们需要一次考虑所有下载速度。

使用范例


这是一个用法示例(在React上):

  async runFunction() { let speedMeasure = new SpeedMeasure(); await speedMeasure.getNetworkDownloadSpeed(); this.forceUpdate() } componentDidMount() { this.runFunction(); } render() { let quality = SpeedMeasure.getResolution([ Control.getControlArray(), Health.getHealthArray() ]); return ( <div className="app"> <Presentation /> <Control quality={quality} /> <Health quality={quality} /> </div> ); } 

因此,当我们确定速度后,将再次渲染容器。
在容器内部(例如,在Control内部),您只需从数组中获取相应的GIF(按索引),然后按质量获取对象,并按url获取链接。 一切都很简单。

编写Python脚本


现在,我们需要以某种方式自动压缩gif并输出包含内容描述的数组。

首先,让我们编写一个压缩脚本。 我们将使用gifsicle。 对于中等压缩的内容,压缩级别将为80(200个压缩级别),对于非常强大的功能,压缩级别将为160。

 import os GIFS_DIR = "/home/mixeden//Landingv2/" COMPRESSOR_DIR = "/home/mixeden//gifsicle-static" NOT_OPTIMIZED_DIR = "not_optimized" OPTIMIZED_DIR = "optimized" GIF_RESIZED_DIR = "gif_not_optimized_resized" GIF_COMPRESSED_DIR = "gif_compressed" COMPRESSION_TYPE = ["middle", "small"] for (root, dirs, files) in os.walk(GIFS_DIR, topdown=True): if len(files) > 0 and GIF_RESIZED_DIR in root: for file in files: path = root + "/" + file for compression in COMPRESSION_TYPE: final_path = path.replace(GIF_RESIZED_DIR, GIF_COMPRESSED_DIR + "/" + compression + "/" + OPTIMIZED_DIR) print(path, final_path) if compression == COMPRESSION_TYPE[0]: rate = 80 else: rate = 160 os.system("echo 0 > " + final_path) os.system(COMPRESSOR_DIR + " -O3 --lossy={} -o {} {}".format(rate, final_path, path)) 

为了使文件路径易于理解,以下是带有gif的文件目录说明:

  1. NOT_OPTIMIZED_DIR-未优化的GIF
  2. GIF_RESIZED_DIR-未优化的GIF,但会根据容器的大小进行调整
  3. GIF_COMPRESSED_DIR-压缩的GIF

文件夹内有带有GIF类别名称的文件夹。 在具有特定文件夹的文件夹内,包含“大”,“中”和“小”(在压缩文件的类型下)。

在脚本中,我们浏览带有gif的目录,对于每个文件,我们执行两种类型的压缩,调用相应的命令行命令。

现在,让我们继续执行脚本以创建一个包含信息的数组。

 import json import os GIFS_DIR = "/home/mixeden//Landingv2/" COMPRESSOR_DIR = "/home/mixeden//gifsicle-static" NOT_OPTIMIZED_DIR = "not_optimized" OPTIMIZED_DIR = "optimized" GIF_RESIZED_DIR = "gif_not_optimized_resized" GIF_COMPRESSED_DIR = "gif_compressed" COMPRESSION_TYPE = ["large", "middle", "small"] OUTPUT = {} for (root, dirs, files) in os.walk(GIFS_DIR, topdown=True): if len(files) > 0 and GIF_COMPRESSED_DIR in root and NOT_OPTIMIZED_DIR not in root: files.sort() type = root.split(GIFS_DIR)[1].split(GIF_COMPRESSED_DIR)[0].replace("/", "") print(type) if type not in OUTPUT: OUTPUT[type] = [] if len(OUTPUT[type]) == 0: for file in files: OUTPUT[type].append( { "large": { "url": "", "size": 0 }, "middle": { "url": "", "size": 0 }, "small": { "url": "", "size": 0 } }) for file in files: full_path = root + "/" + file bytes_size = os.path.getsize(full_path) kilobytes_size = bytes_size / 1000 megabytes_size = kilobytes_size / 1000 index = int(file.split("_")[1].replace(".gif", "")) - 1 for typer in COMPRESSION_TYPE: if typer in root: local_type = typer new_url = "gifs/" + full_path.replace(GIFS_DIR, "").replace("/" + GIF_COMPRESSED_DIR, "").replace("/" + OPTIMIZED_DIR, "") OUTPUT[type][index][local_type]['url'] = new_url OUTPUT[type][index][local_type]['size'] = megabytes_size print(OUTPUT) print(json.dumps(OUTPUT, indent=4, sort_keys=True)) 

在这里,我们浏览包含文件的文件夹,确定文件大小,找出压缩类型,然后将常规信息放入OUTPUT数组。 然后,我们将这个数组输出到控制台以进行复制。

结论


希望本文对您有所帮助。 伙计们,编码不错。

Source: https://habr.com/ru/post/zh-CN480704/


All Articles