Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox

Chapitre 8 : Emballage

Par gnicos (Nicolas Gauville), le 13 juillet 2012
Navigation rapide :

<< Chapitre 7 - Sommaire

Nous allons maintenant voir comment rassembler et compresser notre code de façon intelligente, de façon à pouvoir l'utiliser et le publier réellement.

Ce chapitre va décrire les diverses méthodes et moyens de s'organiser pour publier un projet en HTML5/JS de façon efficace.

I. Séparer développement / publication

La première chose va être de séparer notre code : d'un côté, nous aurons notre code “éditable”, sur lequel nous travaillons, de l'autre, le code “publié”, destiné à être diffusé sur le web. Mais avant tout, nous allons voir pourquoi cette séparation est intéressante.

a) Les erreurs, c'est pas pour les visiteurs !

Pour commencer, nous avons besoin de tester notre code. Bien sur, il y a des moyens de tester notre code sur notre ordinateur (bien qu'en JavaScript, certains navigateurs bloquent certaines fonctions lorsque les fichiers sont locaux), mais certains, pour des raisons pratiques notamment (le fait de pouvoir éditer le code partout, par exemple) choisissent d'éditer le code directement en ligne, via des applications comme Coda, Diet Coda, ShiftEdit ou encore CodeAnywhere.

Cependant, il faut penser que lorsque l'on code, bien souvent, il y a des erreurs. C'est naturel, et même les plus grands éditeurs de logiciels passent par une phase de test. Il faut donc séparer absolument la version sur laquelle on travaille de la version “utilisable”.

b) Un code clair != un code léger

Deuxième point : un code clair sera lourd inutilement, du fait de la présence de commentaires, d'indentations, de sauts de lignes, d'espaces inutiles, … qui seront très utiles au codeur, permettant de relire facilement le code, mais alourdiront inutilement le fichier JavaScript.

A l'inverse, un code léger (débarrassé de tous les commentaires, espaces et autres éléments inutiles) sera complément illisible pour le codeur.

Nous allons donc devoir avoir deux versions de notre projet, une pour le développement, l'autre pour l'exploitation.

c) Mise en pratique

Pour commencer, nous allons donc mettre tout notre projet dans un sous dossier, par exemple “dev”, et créer un autre dossier, qui, parallèlement, contiendra la version “web” de notre projet, destinée à l'exploitation sur internet et non au développement (ici, “www”).

Nous pouvons donc avoir l'architecture suivante :

II. Rassembler les fichiers

La deuxième chose que nous allons faire, c'est rassembler certains fichiers.

a) Le ping, ça compte !

Le temps de chargement d'un site internet dépend d'un certain nombre de facteurs, que l'on peut regrouper en trois catégories :

  1. - Les fichiers du site.
  2. - La vitesse d'envoi du serveur.
  3. - La vitesse de réception du client.

Ici, nous allons nous intéresser au premier facteur : les fichiers du site. Globalement, deux choses comptent : le poids, et le nombre.

Pour télécharger rapidement un gros volume de fichiers (soit d'un poids important), il faut un bon débit internet. A l'inverse, pour télécharger rapidement un grand nombre de fichiers, il faut un bon ping.

Le ping correspond à un délais de transmission entre l'ordinateur et le serveur distant. Globalement, l'influence de ce délais aura une forte importance lors de la transmission de beaucoup d'éléments, et sera moins importante lors de la transmission d'éléments volumineux (cas dans lequel le débit compte plus). Nous pourrions l'associer, par analogie, aux électrons : ils se déplacent très lentement dans une connexion électrique, et pourtant, la vitesse du courant, est, elle, très importante.

Il est donc important de ne pas avoir un trop grand nombre de fichiers dans un site internet, et c'est la raison pour laquelle nous allons regrouper certains fichiers. Bien sur, le regroupement est d'autant plus important que le nombre de fichiers (dans la version de développement) est élevé.

b) Rassembler logiquement

Avant de nous lancer et de regrouper tous les fichiers en un, il faut tout de même réfléchir un peu pour le faire logiquement. Globalement, un regroupement va se justifier pour deux raisons :

Des fichiers "liés"

Premier critère : rassembler les fichiers ayant un lien. Par exemple, dans notre jeu, nous pouvons distinguer trois catégories de fichiers : le moteur (dossier “src”), les graphismes, et le fichier “core”.

Pourquoi ces trois catégories ? Parce qu'il s'agit de “groupes” de fichiers que nous éditons chacun séparément. En effet, lorsque l'on touche au graphisme, on ne modifiera que le (ou les) fichier(s) correspondant au graphisme. De la même façon, une fois notre moteur terminé, nous n'avons, en principe, plus besoin de le modifier pour modifier notre jeu.

Rassembler plusieurs fichiers ne se fait pas tout seul, est cela devient vite pénible si nous devons le faire toutes les cinq minutes. Nous allons donc essayer de faire des “paquets”, de sorte que lorsque nous modifions certains fichiers, nous n'ayons pas a rassembler d'autres, qui n'auraient de toute façon pas été modifiés.

Des fichiers "réutilisables"

Ensuite, il faut penser aux fichiers “réutilisables”, qui ne doivent donc pas être mélangés avec des fichiers spécifiques à un projet. Par exemple, notre moteur isométrique pourra être utilisé dans plusieurs projets, alors que le reste sera spécifique à chacun. Ainsi, le fichier final du moteur isométrique pourra servir plusieurs fois.

c) Mise en pratique

Nous allons donc passer de nos six fichiers JS à trois fichiers : “core.js”, “gfx.js” et “iso.js” (peu importe le nom, l'essentiel, c'est qu'il représente notre moteur isométrique.

Notre page “index.html” contient donc maintenant ceci :

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<style>body{background-color: black;text-align: center;}</style>
                <script src="http://code.createjs.com/easeljs-0.4.1.min.js"></script>
		<title>TBG HTML/JS</title>
	</head>
	<body>
		<canvas id="gameview" width="800" height="600">
  			Désolé, votre navigateur ne supporte pas la technologie Canvas.
		</canvas>
 
        	<script type="text/javascript" src="src/iso.js"></script>
                <script type="text/javascript" src="assets/gfx.js"></script>
        	<script type="text/javascript" src="assets/core.js"></script>
	</body>
</html>

Pour le reste, vous pouvez donc copier-coller le dossier “assets” du répertoire “dev” dans le répértoire “www” (pas de changements de ce côté la, pour l'instant). Pour le dossier “src”, vous pouvez donc créer un fichier “iso.js” dans le dossier “www/src”, et coller à l'intérieur le contenu de tous les fichiers du dossier “dev/src”.

Lors de cette manipulation, faites tout de même attention à les coller dans le même ordre que celui indiqué dans le fichier “index.html” du dossier dev, à savoir : “tiletype”, puis “tile”, puis “map”, puis “player”.

III. Compresser le code

a) Le débit aussi, sa compte !

Si comme nous l'avons vu, le ping et le nombre de fichiers ont leur importance, le débit, et donc le poids des fichiers, joue également beaucoup. La compression du code va donc permettre de réduire la taille des fichiers par plusieurs moyens :

  1. - Supprimer les commentaires.
  2. - Supprimer tout les caractère inutiles (retours à la ligne, espaces, tabulations, …)
  3. - Renommer les variables internes (comme les paramètres), de façon à gagner de la place (en leur donnant des noms très courts), tout en gardant un code qui fonctionne.

Cette compression, contrairement à ce que l'on peut penser, à son importance. Dans le cas du fichier “core.js” par exemple, nous pouvons réduire la taille du fichier de plus de 70% (après essai !).

b) Un code plus sûr !

La deuxième chose, c'est rendre le code illisible. Bien sur, quelqu'un d'acharné pourra toujours réussir à relire le code, mais vous verrez qu'un code compressé (sans espaces, sans noms de variables éloquents) est très difficile à lire.

Il ne s'agit pas la de ne pas vouloir partager le code, mais plutôt de rendre un peu plus complexe les tentatives de triches.

Cette méthode ne permet pas de protéger un code ! Un code exécuté par le client est TOUJOURS un code à risque, cette méthode rend la tache légèrement plus difficile, mais ne constitue pas une réelle protection du code, et ne pourra pas suffire à empêcher la triche dans un jeu multi-joueur par exemple.

c) Mise en pratique

Bien entendu, vous vous doutez que nous n'allons pas réaliser cette compression “à la main”. Heureusement, des compresseurs existent.

Par exemple : http://javascriptcompressor.com/

Il vous suffit de copier-coller le code dans la partie du haut, et de cliquer sur “Compress”. Je vous conseille également l'option “Shrink Variables” permettant de gagner un peu plus de place encore. Dans le cas du fichier “iso.js”, nous passons par exemple d'un fichier de 6 358 octets, à 1965 octets, ce qui montre bien le gain non négligeable de cette compression. Le résultat obtenu est alors le suivant :

var TileType={PNG:"PNG",DRAW:"DRAW"};var Tile=function(a,b,c,d,e){this.construct(a,b,c,d,e)};var p=Tile.prototype;p.type=TileType.DRAW;p.content=null;p.walkable=true;p.offsetX=0;p.offsetY=0;p.map=null;p.posX=0;p.posY=0;p.posZ=0;p.construct=function(a,b,c,d,e){if(a===TileType.PNG){this.type=a}if(c===false){this.walkable=false}if(typeof d===typeof 0){this.offsetX=d}if(typeof e===typeof 0){this.offsetY=e}if(b&&b.visible){this.content=b}};p.dispose=function(){this.map=null;this.type=null;this.content=null;this.walkable=null;this.offsetX=null;this.offsetY=null};var Map=function(){};var p=Map.prototype=new Container();p.tiles=[];p.tilesWidth=128;p.tilesHeight=64;p.offsetX=0;p.offsetY=0;p.addTile=function(a,b,c,d){a.posX=b;a.posY=c;a.posZ=d;a.map=this;this.tiles.push(a);this.addChild(a.content);this.update()};p.removeTile=function(a){var b=this.tiles.indexOf(a);if(b===-1){throw new Error('Map.removeTile : la tuile à supprimer ne fait pas partie de la carte !');}this.removeChild(a.content);this.tiles.splice(b,1);a.dispose()};p.getTileAt=function(b,c,d){var e=null;this.tiles.forEach(function(a){if(a.posX===b&&a.posY===c&&a.posZ===d){e=a}});return e};p.update=function(){this.tiles.forEach(function(a){a.content.x=(a.posY-a.posX)*(a.map.tilesWidth/2)+(a.offsetX+a.map.offsetX);a.content.y=(a.posY+a.posX)*(a.map.tilesHeight/2)+(a.offsetY+a.map.offsetY);a.content.tile=a});this.sortChildren(function(a,b){$n_a=5*(a.tile.posX+a.tile.posY)+a.tile.posZ;$n_b=5*(b.tile.posX+b.tile.posY)+b.tile.posZ;if($n_a>$n_b){return 1}else if($n_a<$n_b){return-1}else{return 0}})};p.dispose=function(){while(this.tiles.length>0){this.removeTile(this.tiles[0])}this.tiles=null;this.tilesWidth=null;this.tilesHeight=null;this.offsetX=null;this.offsetY=null};var Player=function(a,b,c,d,e){this.construct(a,b,c,d,e)};var p=Player.prototype=new Tile();p.move=function(a,b){if(this.map.getTileAt(this.posX+a,this.posY+b,0).walkable){this.posX+=a;this.posY+=b;this.map.update()}};

Nous pouvons donc compresser le fichier “iso.js” (tout en gardant, bien évidement, les fichiers du dossier “dev” éditables). La compression des autres n'est pas forcément tout aussi intéressante, cela dépend des modifications à faire, de leur volume, etc.

De plus, sachez qu'il arrive que la compression génère des erreurs. La plupart du temps, il ne s'agit pas d'une erreur du compresseur, mais d'une erreur du code, qui a été révélée par le compresseur, comme, par exemple, l'absence d'un ”;”.

IV. Le chiffrement

Vous avez probablement remarqué l'option “base62 encore” dans le compresseur. Cette option permet de gagner encore un peu plus de place, et de rendre, cette fois, le code très complexe à éditer.

Cependant, je vous déconseille fortement cette option ! Voici pourquoi :

1 : Pas de réel intérêt

Pour commencer, ne croyez pas réellement rendre votre code infaillible avec cette méthode, car ce n'est toujours pas le cas. En effet, un bon codeur saura passer cette ruse très simplement : Il suffit de remplacer la fonction “eval” par “alert”, et le code compressé (sans le chiffrement en base 62) est alors affiché via la fonction alert. Ce chiffrement n'apporte donc aucune sécurité supplémentaire au code.

2 : La fonction eval

Deuxième point : la fonction “eval” fait partie des mauvaises habitudes en JavaScript, et est à banir le plus souvent. De plus, le moteur JavaScript va ici devoir déchiffrer le code avant de le lire, ce qui ralentira particulièrement sont execution.

3 : Les erreurs

Enfin, ce chiffrement génère fréquemment des erreurs sur certains navigateurs, une raison de plus de le bannir.

V. Résultat

Ainsi, dans ce chapitre, nous avons pu voir comment optimiser notre code pour le web. Retenez bien que l'intérêt de tout ceci est d'accélérer le temps de chargement, et rien d'autre !

Pensez donc au fait que cela peu être très utile pour un gros projet (de très nombreux fichiers, et beaucoup de lignes de code), mais qu'à l'inverse, ce n'est pas forcément nécessaire dans un projet de petite taille !

VI. Téléchargements

Enfin, voici les téléchargements du résultat final de ces 8 chapitres.

Jeu entier (incluant les dossiers “www” et “dev”) : jeu.zip

Moteur isométrique (dossier “dev/src” uniquement) : moteur_iso.zip

Navigation rapide :

<< Chapitre 7 - Sommaire