Les dernières actualités d'Alsacreations.com
Lorsqu'on utilise npm, le gestionnaire de paquets le plus courant pour Node, deux options s'offrent à nous pour installer un nouveau paquet.
npm install --save
installe un package (paquet) et l'ajoute à la section dependencies
de votre fichier package.json. Cela signifie que le package est nécessaire pour votre application à exécuter et sera installé sur les machines des utilisateurs finaux lorsque vous publierez votre application.
Par exemple npm install --save lodash
va produire le fichier package.json suivant
{
"dependencies": {
"lodash": "^4.17.21"
}
}
npm install --save-dev
installe un package et l'ajoute à la section devDependencies
de votre fichier package.json. Cela signifie que le package est nécessaire pour le développement de votre application, mais pas pour son exécution. Par exemple, vous pourriez utiliser un outil de linting lors de votre développement tel qu'eslint, mais il ne serait pas nécessaire pour l'exécution de l'application. Ces fichiers ne seront pas installés sur le serveur de production ou sur les machines des utilisateurs finaux car ils y seraient inutiles, et pour certains pourraient présenter des failles de sécurité.
Par exemple npm install --save-dev eslint
va modifier le précédent fichier package.json :
{
"dependencies": {
"lodash": "^4.17.21"
},
"devDependencies": {
"eslint": "^8.33.0"
}
}
Dans les deux cas, les fichiers téléchargés se retrouvent bien dans le dossier node_modules
.
Vous pouvez aussi utiliser la commande npm install --production
pour n'installer que les paquets listés dans dependencies
. Si vous voulez aussi installer les paquets listés dans devDependencies
, vous utiliserez la commande npm install --development
.
Ces commandes sont souvent déjà exploitées par les différents scripts embarqués par les frameworks (Vue, React, etc) pour leurs tâches de développement, compilation, déploiement.
L'API High Resolution Time (ou l'API de temps à haute résolution) est une interface JavaScript qui permet d'accéder à une horloge de haute précision pour mesurer des périodes de temps avec une précision allant jusqu'à la microseconde.
Cela peut être utile pour des applications qui nécessitent une précision temporelle élevée, comme les jeux, les applications de réalité virtuelle ou tout simplement pour mesurer des écarts de performances lorsque les fonctions classiques telles que getTime()
de l'objet Date
ne suffisent plus.
Cette API est bien reconnue depuis 2013 par l'ensemble des moteurs de navigateurs. Ces derniers pourront néanmoins arrondir les valeurs retournées et diminuer la précision pour des raisons de sécurité et de mitigation d'usage détourné.
Pour utiliser l'API High Resolution Time dans votre code JavaScript, vous pouvez commencer par accéder à l'objet performance
et sa méthode now()
.
Voici un exemple simple d'utilisation de l'API High Resolution Time pour mesurer la durée d'une opération dans votre code :
// Récupération de l'heure actuelle en utilisant l'API High Resolution Time
const start = performance.now();
// Effectuer une ou plusieurs opération(s) ici...
// Récupération de l'heure actuelle une nouvelle fois
const end = performance.now();
// Calcul de la durée de l'opération
const duration = end - start;
// Affichage de la durée totale de l'opération (en ms)
console.log(duration);
Vous pouvez également utiliser l'API High Resolution Time pour mesurer des périodes de temps plus longues en utilisant les méthodes setInterval
et setTimeout
, qui vous permettent d'exécuter du code à des intervalles réguliers. Par exemple :
// Définition d'une fonction qui sera appelée toutes les 10 secondes
function logTime() {
// Récupération de l'heure actuelle en utilisant l'API High Resolution Time
var now = performance.now();
// Affichage de l'heure actuelle dans la console
console.log(now);
}
// Exécution de la fonction toutes les 10 secondes
setInterval(logTime, 10 * 1000);
Vous pouvez en savoir plus sur cette API en consultant la spécification W3C High Resolution Time bien entendu.
L'API Fullscreen standard maintenu par le WhatWG vous permet de faire en sorte qu'un élément de votre page web, quel qu'il soit, occupe tout l'espace disponible de l'écran. Cela peut être utile pour les vidéos en plein écran bien entendu mais également les jeux, ou toute autre application qui nécessite un affichage en plein écran sans nécessairement être constituée de vidéo.
Pour utiliser l'API Fullscreen, vous devez d'abord vérifier que le navigateur prend en charge cette fonctionnalité. Vous pouvez le faire en utilisant la propriété fullscreenEnabled
de l'objet document
:
if (document.fullscreenEnabled) {
// Le navigateur prend en charge l'API Fullscreen
} else {
// Le navigateur ne prend pas en charge l'API Fullscreen
}
Si le navigateur prend en charge l'API Fullscreen, vous pouvez ensuite faire en sorte qu'un élément de votre page web passe en mode plein écran en utilisant la méthode requestFullscreen()
:
const element = document.querySelector('#ma-video');
element.requestFullscreen();
Dans cet exemple, nous avons récupéré l'élément en question par un sélecteur et nous avons appelé la méthode requestFullscreen()
.
Il est important de noter que l'internaute doit accepter de passer en mode plein écran avant que cela se produise. Le navigateur affichera une notification demandant si l'internaute souhaite passer en mode plein écran ou non. Si l'internaute refuse, la méthode "requestFullscreen" ne fera rien.
Inversement, il existe une méthode exitFullscreen()
pour quitter le plein écran.
Pour détecter l'acceptation ou le refus de passer en mode plein écran, vous pouvez écouter l'événement fullscreenchange
toujours sur l'objet document
:
document.addEventListener('fullscreenchange', () => {
if (document.fullscreenElement) {
// Accord de passer en mode plein écran
} else {
// Refus de passer en mode plein écran
}
});
Dans cet exemple, nous avons ajouté un écouteur d'événement sur l'événement fullscreenchange
. Lorsque l'événement se produit, nous vérifions si l'objet fullscreenElement
de l'objet document
est défini. Si c'est le cas, cela signifie que l'utilisateur a accepté de passer en mode plein écran.
L'API est accompagnée d'un pseudo-élément ::backdrop
qui est rendu immédiatement sous l'élément en plein écran, ce qui permet de créer un arrière-plan sombre, un ombrage ou toute autre fantaisie qui va recouvrir le document d'origine lorsqu'on est en mode plein écran.
Pour utiliser le pseudo-élément ::backdrop, il suffit de l'ajouter à la feuille de styles.
#ma-video:fullscreen::backdrop {
background-color: rgba(0, 0, 0, 0.8);
}
L'API est également complétée par une pseudo-classe :fullscreen
qui va correspondre dynamiquement à tout élément passé en plein écran.
Le format de fichier APNG (Animated Portable Network Graphics) est comme son nom le suggère un format d'image animé reposant sur le format PNG, déjà très bien connu.
APNG a été conçu à partir de 2004 à l'initiative de Mozilla qui héberge la spécification APNG en tant que version améliorée du format PNG et offre des fonctionnalités supplémentaires telles que (évidemment) la possibilité d'animer les images... à l'instar du GIF.
Son support s'est amélioré progressivement, entre 2009 (Firefox) et 2020 (Edge) ce qui représente une longue période de temps, et le voit désormais reconnu par tous les navigateurs. Même les anciens programmes reconnaissant PNG peuvent afficher un fichier APNG car sa première image est au format PNG valide, il y a donc en quelque sorte une rétro-compatibilité qui est relativement assurée par le fait que les données d'animation sont stockées dans un espace supplémentaire déjà prévu par le format PNG initial. Le type MIME correspondant est image/apng
.
Il ne s'agit pas nécessairement du format le plus optimisé pour les "images animées" car il existe bien des concurrents dans ce domaine avec des algorithmes appropriés : on privilégie de nos jours notamment les codecs vidéo (MP4, Webm, AV1) et leurs déclinaisons en formats d'images (WebP animé, AVIF animé : voir des démos). C'est d'ailleurs pour cela que les sites majeurs fournisseurs de GIFs et memes variés (Giphy, Tenor) ne vous servent en réalité, depuis bien longtemps, pas des images GIF mais de véritables et courts fichiers vidéo à leur place.
Le format PNG (Portable Network Graphics) est à la base un format d'image bitmap (ou raster) dans lequel on cherche à mémoriser les données pixel par pixel, avec une qualité supérieure à celle des formats d'image populaires tels que JPEG et GIF notamment parce que la compression ne doit pas affecter la qualité et perdre de l'information. Il utilise donc une compression sans perte pour conserver tous les détails de l'image d'origine, ce qui en fait un meilleur choix pour les images de haute qualité, icônes et schémas.
En termes techniques, la principale différence vis-à-vis de son parent le PNG est l'ajout des capacités d'animation en combinant successivement plusieurs images. Le format APNG est donc un format plus avancé ou plutôt une extension de PNG tel que la spécification PNG du W3C l'indique.
Un autre ensemble de quelques tests consultables en ligne GIF vs APNG vs WebP arrive à la conclusion qu'un fichier APNG est plus léger qu'un WebP animé en mode lossless c'est-à-dire sans perte de qualité.
S'il existe désormais de nombreux convertisseurs en ligne, l'outil le plus basique est APNG Assembler qui en ligne de commande (ou en version graphique sous Windows) va "assembler" de multiples fichiers PNG et appliquer un niveau de compression choisi. En complément gif2apng est un vrai convertisseur d'animations GIF vers APNG, et apng2gif son opposé APNG vers GIF.
Le format APNG est binaire : il ne peut être ouvert par un éditeur de texte comme le SVG, il faudra passer par un éditeur hexadécimal tout comme pour JPEG, WebP, etc. Il stocke les données d'animation en combinant plusieurs images en une seule. Chaque image est stockée dans un chunk (que l'on peut traduire par morceau, tronçon) du fichier APNG, avec des informations sur la durée de l'image et les effets de transition à utiliser pour passer à la suivante. Des chunks supplémentaires stockent des informations sur les contrôles de l'animation, telles que la vitesse et le bouclage.
Les chunks sont alors assemblés dans un conteneur qui débute par une "signature" en début de fichier, signalant qu'il s'agit bien d'une image au format APNG, puis un bloc IHDR
en amont des chunks et un bloc IEND
à la fin.
On obtient donc un assemblage de frames qui étaient à l'origine des fichiers PNG indépendants, dont on a conservé uniquement les données IDAT
, réécrites également en fdAT
(frame data chunk) pour les images qui se suivent avec un numéro de séquence.
Schéma provenant de la page Wikipédia APNG
Vous pouvez utiliser le très intéressant PNG file chunk inspector avec vos fichiers PNG ou des exemples fournis pour analyser leur structure en ligne, dont voici un extrait de capture d'écran :
Un exemple de chunk d'image APNG pourrait être résumé ainsi :
IDAT
[Données de l'image]
acTL (animation control)
[Nombre total d'images dans l'animation]
[Nombre de boucles dans l'animation]
fcTL (frame control)
[Numéro de l'image]
[Largeur de l'image]
[Hauteur de l'image]
[X de l'image]
[Y de l'image]
[Durée de l'image en millisecondes]
[Numéro de l'image suivante]
[Effet de transition à utiliser]
Le format APNG (Animated Portable Network Graphics) et le format GIF (Graphics Interchange Format) ont tous deux la même vocation à créer des animations par une succession d'images bitmap (non vectorielles). Cependant, ils diffèrent sur plusieurs points, notamment car ils ne proviennent pas de la même génération. GIF a été inventé en 1987 !
Vite est un outil front-end JavaScript qui vise à améliorer la rapidité de développement en offrant un serveur de développement rapide et une compilation optimisée pour la production. Il prend la suite d'une grande famille dans laquelle on peut évoquer Grunt, Gulp, et dernièrement Webpack.
Vite utilise la fonctionnalité ES Module Import de JavaScript pour charger les modules de manière asynchrone, ce qui permet une expérience de développement plus rapide et une compilation (étape build) plus petite pour la production. Vite est également conçu pour être facile à utiliser et à configurer, ce qui en fait un choix populaire pour les développeurs de front-end.
Vite a été développé par Evan You, le créateur de Vue.js, dans le but de créer un outil de développement de front-end plus rapide et plus efficace que Webpack, notamment pour les projets basés sur Vue.js. Cette idée initiale a été publiée sur Twitter :
Vite a ainsi été lancé en 2020 et a depuis connu un grand succès, non seulement auprès des projets Vue, mais également auprès d'autres projets de développement front-end. Il a désormais remplacé dans Vue 3 la suite d'outils Vue CLI qui était mise en avant pour Vue 2 et qui comprenait Webpack.
Plusieurs techniques ont été rassemblées :
On peut également comprendre que le processus traditionnel est de produire le bundle à partir de tous les modules compilés pour toutes les routes existantes, ce qui nécessite un important temps de préparation. (Schémas issus de la documentation officielle de Vite)
Avec ESM, le serveur est à l'écoute de toute requête, trouve la route correspondante et importe dynamiquement les modules concernés.
Plusieurs frameworks de développement front-end populaires utilisent Vite comme outil de développement et de build, notamment :
Vite n'est pas lié à un framework spécifique et peut être utilisé avec n'importe quel projet de développement front-end, d'ailleurs moult exemples sont fournis officiellement pour Vue et React à la fois.
Si vous faites déjà du Vue 3, il y a de fortes chances que Vite soit déjà utilisé par défaut (vous pouvez le voir tout simplement en lançant la commande de développement ou de compilation). Vous pouvez aussi utiliser Vite avec un projet de développement front-end (existant ou vide), avec la commande suivante :
npm init vite
Cela posera quelques questions, démarrera le serveur de développement à une URL locale et ouvrira votre application dans un navigateur.
On remarque assez aisément que pour un projet complexe comportant de nombreux composants, la phase de compilation initiale est réduite à quelques secondes alors qu'elle peut prendre jusqu'à plusieurs minutes avec Webpack.
Vous pouvez également noter que dans les outils de développement navigateur, onglet Réseau (Network) on voit passer les requêtes pour les différents modules plutôt que vers un seul import compilé.
Si vous souhaitez utiliser des fonctionnalités avancées de Vite, telles que le HMR, vous devrez peut-être ajouter des lignes de code supplémentaires à votre application pour activer ces fonctionnalités.
Le Hot Module Reloading (HMR) est une fonctionnalité de Vite qui permet de mettre à jour les modules de votre application sans avoir à recharger complètement la page. Cela peut être très utile lorsque vous développez une application et que vous souhaitez voir les changements que vous apportez immédiatement.
Comment le HMR fonctionne dans Vite :
Le HMR est réalisé à l'aide du protocole WebSocket qui maintient une connexion persistante, vous pouvez par ailleurs l'examiner dans l'onglet réseau des outils de développement pour voir les échanges de messages.
Le HMR est une fonctionnalité très pratique qui peut grandement améliorer votre expérience de développement et vous faire gagner du temps.
Plusieurs plugins officiels sont disponibles notamment pour Vue 3 et ses SFC (Single File Components), la syntaxe JSX, React, etc.
Il en existe aussi de nombreux autres mis à disposition par la communauté et que l'on retrouvera dans la liste du repo awesome-vite
Si vous souhaitez en savoir plus, consultez la documentation officielle Vite ou encore le replay de la conférence ViteConf 2022.
C'est parti ?
Les blob URLs sont des URLs (Uniform Resource Locators) générées dynamiquement qui permettent d'accéder aux données binaires stockées dans un objet Blob (Binary Large OBject) en JavaScript.
Un objet Blob peut contenir des données de différents types, comme des images, des fichiers audio ou vidéo, du texte ou tout autre type de données binaires. Cela en fait une technique utile et souple pour manipuler des pseudo-fichiers en mémoire, qui n'existent pas en tant que tels sur un serveur web. D'ailleurs on ne pourra pas générer de Blob côté serveur (back-end), cela n'existe que du côté navigateur (front-end).
ð¦ Il ne faut pas le confondre avec Physarum polycephalum qui est une étrange espèce unicellulaire existant depuis des millions d'années, que vous pouvez même adopter, et qui n'est ni un animal, ni un végétal, ni un champignon.
Cet être étrange qui n'a pas de cerveau est capable de communiquer et trouver son chemin dans des labyrinthes, tel que l'ont prouvé des expériences. Il résiste au feu et à l'eau, il a une grande résistance et longévité... et a été emporté dans l'espace.
Toutes ces caractéristiques en ont fait une curiosité idéale inspirant moult livres et films. Dès 1958 on peut retrouver Steven McQueen dans The Blob suivi malheureusement un remake du même titre The Blob qui fut un désastre en 1988.
En revanche, il existe un très bon jeu Tales from Space: Mutant Blobs Attack disponible sur consoles, Windows, Linux, macOS, dans lequel on incarne un blob qui doit grossir de plus en plus pour s'échapper de son laboratoire et par la suite dévorer progressivement le monde des humains.
On peut générer un Blob à partir d'un fichier grâce à l'API File ou à partir du constructeur Blob() qui va prendre en paramètre les données brutes (par exemple du texte, du code HTML, de la donnée binaire image, etc.) et d'un type MIME.
Par la suite, les blob URLs peuvent être générées à l'aide de la méthode URL.createObjectURL()
de JavaScript, en passant l'objet Blob
en argument. Par exemple :
// Création d'un objet Blob à partir de données
const myBlob = new Blob(['Hopla!'], {type: 'text/plain'});
// Création d'une URL blob à partir de l'objet Blob
const blobURL = URL.createObjectURL(myBlob);
// Affichage de l'URL blob générée
console.log(blobURL); // "blob:https://example.org/957b4d22-c5b5-4c5f-b5b5-f7f3b3bf2b05"
Voici un autre exemple pour du JSON
const objet = { type: "fruit", nom: "kiwi" };
const blob = new Blob([JSON.stringify(objet, null, 2)], {type : 'application/json'});
Une fois que vous avez une URL de type blob, vous pouvez l'utiliser comme une URL classique pour accéder aux données contenues dans l'objet Blob. Par exemple, vous pouvez l'utiliser comme source d'une image <img src="blob:https://example.org/957b4d22-c5b5-4c5f-b5b5-f7f3b3bf2b05">
ou comme lien dans un élément a
.
Attention, les blob URLs ne sont valides que pendant la durée de vie de l'objet Blob
auquel elles sont liées, et donc très souvent durant la session de navigation. Le navigateur libère la mémoire lorsqu'on ferme la fenêtre, l'onglet, lorsqu'on recharge, etc. Une fois que le Blob est supprimé ou qu'il n'est plus accessible, la blob URL ne fonctionnera plus et devra être générée à nouveau si nécessaire.
Lire un blob s'effectue avec FileReader
qui est aussi l'API de prédilection pour lire des fichiers File
de manière asynchrone. Par exemple :
let reader = new FileReader();
reader.addEventListener("loadend", function() {
// on lira le contenu de reader.result
});
reader.readAsArrayBuffer(leblob);
L'événement hashchange se déclenche lorsqu'il y a un changement de l'ancre (ou hash) d'une URL, c'est-à-dire la portion après le signe #
. On va le retrouver dans la propriété DOM window.location.hash
.
Le hash est un élément particulier de l'URL : il ne provoque pas de (re)chargement de page lorsqu'il change, il n'est pas divulgué au serveur web dans la requête HTTP.
Dans son usage le plus courant, il est associé à l'accès aux ancres HTML. C'est-à-dire que lorsqu'on clique sur un lien <a href="#recherche">
on va pointer le focus sur l'élément possédant id="ancre"
et faire défiler la page jusqu'à la cible. C'est aussi la technique utilisée par les liens d'évitement pour améliorer l'accessibilité.
Lorsque l'ancre d'une page Web change, on peut également intercepter l'événement hashchange
pour exécuter du code.
// Écouter l'événement
window.addEventListener("hashchange", function(event) {
// Récupérer la nouvelle valeur de l'ancre
const hash = window.location.hash;
// Exécuter du code en fonction de la valeur de hash
// ...
});
Dans cet exemple, nous utilisons la méthode addEventListener()
pour écouter l'événement hashchange
qui se produit sur l'objet window
. En effet, puisqu'il se passe au niveau du navigateur, il n'est pas lié à un élément du DOM en particulier. Lorsque l'événement se déclenche, on récupère la valeur de location.hash
sachant que cet objet location
contient d'autres informations sur l'adresse courante.
Il est aussi possible de récupérer dans l'objet événement event
en premier paramètre de la fonction de callback diverses informations telles que l'ancienne URL oldURL
et la nouvelle newURL
.
Pour utiliser hashchange
afin de charger un nouveau contenu de manière asynchrone en HTTP à l'aide de la fonction fetch()
:
// Écouter l'événement hashchange
window.addEventListener("hashchange", function(event) {
// Récupérer la nouvelle valeur de l'ancre
const hash = window.location.hash;
// Charger le nouveau contenu à l'aide de la fonction fetch
fetch("/api/content/" + hash)
.then(function(response) {
return response.text();
})
.then(function(html) {
// Mettre à jour le contenu de la page
document.querySelector("#content").innerHTML = html;
});
});
Dans ce cas de figure, on récupère toujours à l'aide de hashchange
la nouvelle valeur de l'ancre, puis elle est transmise de manière asynchrone au serveur, ou à une API quelconque de votre choix, pour obtenir le nouveau contenu et l'injecter dans un élement déjà existant de la page grâce à innerHTML
. Il faut donc faire attention à ce qui est renvoyé par le back-end soit une portion de document HTML et non l'intégralité d'une page avec head
, link
, style
, script
et compagnie ce qui ne serait pas conforme et pourrait créer de gros conflits de style et de JavaScript.
Notez que cet exemple utilise then()
pour enchaîner les réponses de la promesse renvoyée par fetch()
. Vous pouvez également utiliser l'opérateur await
pour attendre que la promesse de fetch soit résolue, avant de mettre à jour le contenu de la page, ce qui est un peu plus lisible que de passer par then
.
// Écouter l'événement hashchange
window.addEventListener("hashchange", async function(event) {
// Récupérer la nouvelle valeur de l'ancre
const hash = window.location.hash;
// Charger le nouveau contenu à l'aide de la fonction fetch
const response = await fetch("/api/content/" + hash);
const html = await response.text();
// Mettre à jour le contenu de la page
document.querySelector("#content").innerHTML = html;
});