Rendre le chargement de contenu réactif sur le site

Bonjour, Habr!

Je fais un site web pour mon projet. Sur le site, vous devez montrer beaucoup de gifs en même temps, chacun pèse assez bien. Si vous affichez tout à la fois, la page se charge pendant très longtemps. Dans le même temps, il est également impossible de donner la page sans GIF (afin qu'ils puissent y être téléchargés).

Quiconque s'intéresse à la façon dont j'ai traité ce problème, je demande un chat.

En fait, le problème


Comme je l'ai dit, il y a TRÈS de nombreux gifs sur le site, bons et différents. Vous pouvez voir par vous-même combien d'entre eux: reface.tech

image

Dès que j'ai vu la version bêta de l'atterrissage, j'ai immédiatement eu un problème de chargement: pour certains utilisateurs, les pages se chargeaient depuis longtemps. Pour une entreprise sérieuse, ce n'est bien sûr pas le cas.

Il était nécessaire de résoudre ce problème d'une manière ou d'une autre. Il était impossible de se débrouiller avec une simple compression sans perte, car déjà à ce moment-là, tout le contenu multimédia était déjà passé par compresseur.io . Par conséquent, il était nécessaire de compresser avec des pertes et de donner des GIF de pire qualité.

Mais distribuer un mauvais contenu multimédia à des utilisateurs disposant d'un bon Internet est une sorte de sacrilège. Par conséquent, il a été décidé de déterminer en quelque sorte la vitesse de ceux-ci de votre Internet, et en fonction de la vitesse à laquelle vous offrez la qualité appropriée.

Nous faisons un croquis


Nous aurons un tableau avec une description du contenu multimédia à charger.

Un exemple:

[ { "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" } } ] 

Ici, dans les éléments pour le degré de qualité approprié se trouve l'url et la taille du fichier.

Nous allons simplement:

  1. Parcourez le tableau (lors du chargement de la page)
  2. Lire la taille totale chargée pour chaque degré de qualité
  3. Déterminez s'il va tout charger en 4 secondes (c'est la période qui me dérange personnellement)

En conséquence, il est nécessaire:

  1. Vu une sorte de chose qui fera un tel tableau pour que tout ne compte pas avec des stylos (en python)
  2. Vu la vitesse d'Internet

Scier la jauge de vitesse


Ce sera relativement simple. Nous tapons dans la barre d'adresse de votre navigateur eu.httpbin.org/stream-bytes/51200 . Un fichier d'une longueur de 51200 octets est téléchargé. Nous nous le poussons en public (pour mesurer la vitesse d'un hébergement).

Maintenant, nous devons vérifier combien le fichier oscille. Nous allons déposer une fonction simple pour cela, qui nous renverra la vitesse en mégaoctets par seconde.

 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); }); } 

C'est-à-dire que nous avons enregistré l'heure de début du téléchargement, l'heure de fin, mesuré la différence et, comme nous connaissons la taille du fichier, nous l'avons simplement divisée.

Nous allons maintenant écrire une fonction qui fera quelque chose à cette vitesse particulière:

 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; } } 

En général, il y a un problème avec ce code: c'est que la vitesse de connexion exacte n'est pas déterminée en raison de la petite taille du fichier. Mais télécharger quelque chose de plus est trop cher pour nous, donc nous multiplions simplement la vitesse résultante par 5. Même avec une marge, nous le prenons, car en réalité la vitesse sera encore plus élevée.

Nous allons maintenant déposer une fonction qui, en fonction de la vitesse, réduira la qualité correspondante:

  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"; } } 

Puisque la fonction qui compte la vitesse est asynchrone pour nous, SpeedMeasure.speed peut être nul. Par défaut, nous pensons que la vitesse de connexion est de 1 mégaoctet par seconde. Lorsque la fonction calcule la vitesse, nous restituons simplement le conteneur.

Nous passons un tableau de tableaux à la fonction getResolution. Pourquoi? Parce que si nous avons plusieurs conteneurs sur la page, il est plus pratique pour nous de transférer le contenu correspondant à chacun d'eux dans un tableau, mais nous devons considérer la vitesse de téléchargement pour tous à la fois.

Exemple d'utilisation


Voici un exemple d'utilisation (sur 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> ); } 

Par conséquent, lorsque notre détermination de vitesse est chargée, le conteneur sera rendu à nouveau.
À l'intérieur du conteneur (par exemple, à l'intérieur de Control), vous prenez simplement le GIF correspondant du tableau (par index), puis vous obtenez un objet par qualité et vous obtenez un lien par url. Tout est simple.

Écrire un script Python


Maintenant, nous devons en quelque sorte compresser automatiquement les gifs et sortir le tableau avec la description du contenu.

Pour commencer, écrivons un script pour la compression. Nous utiliserons gifsicle. Pour le contenu à compression moyenne, le niveau de compression sera de 80 (sur 200), pour une fonctionnalité très puissante, il sera de 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)) 

Pour rendre les chemins d'accès aux fichiers compréhensibles, voici la description du répertoire des fichiers avec des gifs:

  1. NOT_OPTIMIZED_DIR - GIF non optimisés
  2. GIF_RESIZED_DIR - GIF non optimisés, mais redimensionnés en fonction de la taille du conteneur pour eux
  3. GIF_COMPRESSED_DIR - GIF compressés

À l'intérieur des dossiers, il y a des dossiers avec des noms de catégorie GIF. À l'intérieur d'un dossier avec un dossier spécifique contient "grand", "milieu" et "petit" (sous les types de fichiers compressés).

Dans le script, nous parcourons le répertoire avec des gifs et pour chaque fichier, nous faisons deux types de compression, en appelant la commande de ligne de commande correspondante.

Passons maintenant au script pour créer un tableau contenant des informations.

 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)) 

Ici, nous parcourons les dossiers avec les fichiers, déterminons la taille du fichier, découvrons le type de compression et mettons les informations générales dans le tableau OUTPUT. Et puis nous avons magnifiquement sorti ce tableau sur la console pour le copier.

Conclusion


J'espère que cet article vous aidera avec quelque chose. Ayez un bon codage, les gars.

Source: https://habr.com/ru/post/fr480704/


All Articles