Zim: un format d'archivage pour du contenu web hors-ligne
T’as du réseau toi ?
Dans notre monde privilégié, il est parfois facile d’oublier que la connexion Internet n’est pas aussi répandue qu’on le suppose. Certaines régions continuent de souffrir d’une connectivité limitée, voire de son absence totale.
Il devient alors évident que sans cette connectivité, la plupart de nos terminaux numériques se transforment presque instantanément en “coquilles vides”. Le contenu que nous consommons n’est plus local mais distant, hébergé sur des serveurs souvent situés à l’autre bout du monde.
Lorsque ce contenu se limite au dernier podcast de l’influenceur à la mode, la “perte” peut sembler tolérable. Cependant, la dimension prend une toute autre ampleur lorsque ce contenu a le pouvoir de changer ou de sauver des vies. Envisagez, par exemple, une encyclopédie détaillant les principales mesures d’urgence face à une catastrophe naturelle. Ou encore, des manuels et des supports scolaires dans une salle de classe d’un pays en voie de développement…
Sur cette clé je détiens l’ensemble des connaissances humaines !
Comment remédier à l’absence ou à la restriction de connectivité ? Une des réponses réside dans la création d’un format d’archivage capable de stocker du contenu Web localement de manière efficace, et surtout, de le restituer comme s’il était toujours servi par son serveur d’origine !
Le format ZIM, développé avec le soutien de la Fondation Wikimedia, a été spécifiquement conçu pour relever ces défis. Il propose notamment les fonctionnalités suivantes :
- Indexation: Les entrées (généralement des pages) contenues dans une archive ZIM sont indexées. Ainsi, l’accès à une entrée particulière est rapide, sans nécessiter de parcourir l’intégralité de l’archive.
- Compression: Les données associées aux entrées peuvent être compressées à l’aide de différents algorithmes, principalement LZMA2. Cette compression optimise significativement la taille de l’archive finale.
- Métadonnées: Chaque entrée peut être enrichie de métadonnées telles que le titre et le type MIME. Cette intégration renforce les informations contextuelles, améliorant ainsi la présentation du contenu.
- Hiérarchisation: Les entrées suivent une organisation hiérarchisée avec des espaces de noms. Cette structuration permet de classifier les entrées, améliorant ainsi les possibilités de recherche au sein de l’archive.
- Écosystème: Le format profite d’un écosystème déjà complet:
- Des lecteurs comme Kiwix et bien d’autres.
- Des générateurs d’archives comme le projet Zimit et sa version en ligne.
- Des bibliothèques indexant un large choix de contenu.
Pour vous donner une idée, l’archive ZIM contenant une sélection de 2 500 000 articles (médias inclus) du Wikipédia français fait environ 40G. Pas mal non ?
Se tenir sur les épaules de géants
Il se trouve qu’à Cadoles nous travaillons également sur un projet qui rencontre ce type de contraintes. Sans rentrer dans les détails (peut être dans un futur article), nous cherchons à diffuser du contenu web qui serait la jonction entre des services locaux et distants.
Si vous êtes amateur de “buzz words”, pensez à une approche “offline first” directement au niveau de votre routeur réseau (aussi assimilable au “edge computing”).
À titre personnel j’étais curieux de voir si notre approche était en capacité à intégrer du contenu au format ZIM, et il s’avère que le résultat est plutôt concluant !
Suite à ces travaux, je partage aujourd’hui ma propre librairie pour le langage Go de lecture de ce format. Vous la trouverez à l’adresse: https://github.com/Bornholm/go-zim.
Cette implémentation s’inspire de nombreuses autres déjà existantes, en Go comme dans d’autres langages. Elle apporte cependant une petite nouveauté: une intégration avec l’interface fs.FS
(introduite par Go 1.16) et donc la possibilité de “servir” directement une archive ZIM sous forme d’un http.Handler
. Pour exemple:
package main
import (
"flag"
"net/http"
"github.com/Bornholm/go-zim"
zimFS "github.com/Bornholm/go-zim/fs"
)
func main() {
reader, err := zim.Open(zimPath)
if err != nil {
panic(err)
}
defer func() {
if err := reader.Close(); err != nil {
panic(err)
}
}()
fs := zimFS.New(reader)
fileServer := http.FileServer(http.FS(fs))
if err := http.ListenAndServe(":8080", fileServer); err != nil {
panic(err)
}
}
Plus d’exemple sont disponibles dans le répertoire examples
du dépôt.
Ce projet dérivé est encore à ses débuts et présente plusieurs lacunes, voire des anomalies. Par exemple, à ce stade :
- L’intégration du serveur HTTP pour les archives ZIM générées via le projet warc2zim n’est pas encore opérationnelle. Un problème d’implémentation nécessitant une analyse plus poussée sur lequel je n’ai pas encore pu me pencher….
- Certains temps d’accès aux ressources pourraient être optimisés, cela pourrait être réalisé à l’aide de benchmarks.
- L’étendue des tests pourrait être élargie, notamment pour garantir le support des différentes versions du format..
N’hésitez pas à forker le projet ou à ouvrir des tickets si vous avez des idées, il est ouvert aux contributions !