Composante du Web

C'est l'histoire d'un de mes projets. Un gros. Un mélange entre PHP et Node.js. C'est une application d'une seule page d'un point de vue et un site Web optimisé pour le référencement d'un autre. Des tonnes de JavaScript, CSS et HTML ont été écrites. En un mot, un cauchemar de spaghettis pour tout développeur. Il y avait des chutes et des montées. Produire et résoudre des bugs. Combattre avec les dernières technologies et aboutir à une bibliothèque merveilleusement simple, qui est le sujet de cet article.

Le début

Comme cela arrive normalement, le projet était considéré comme pas si gros. Le mémoire est arrivé, nous avons discuté de la façon dont le développement serait géré, des technologies qui seraient utilisées et de la façon dont nous les utiliserions. Nous avons élaboré un plan et nous nous sommes mis au travail. Au début, nous avions quelques pages, qui étaient contrôlées par un CMS. Au début, il n'y avait pas tellement de code JavaScript, car notre système livrait l'essentiel du contenu..

Voici une structure approximative du projet:

Nous avons mis notre code côté client dans différents répertoires. Le code côté serveur n’était que PHP pour le moment, il est donc entré dans la php annuaire. Nous avons tout emballé dans environ 30 fichiers et tout était OK.

Le voyage

Pendant quelques mois, nous avons essayé différents concepts et modifié le code du projet à plusieurs reprises. Du point de vue actuel, je pourrais repérer quatre grands problèmes que nous avons rencontrés.

Problème n ° 1 - Trop de fichiers mal structurés

Il semble que le client était satisfait du résultat et a décidé d'investir davantage dans son apparence sur Internet. On nous a demandé de créer quelques nouvelles fonctionnalités. Certains d'entre eux n'étaient que de nouveaux lieux de contenu, d'autres des ajouts à des pages déjà existantes. Nous avons commencé à ajouter de plus en plus de fichiers dans tous les dossiers ci-dessus. Cela a commencé à devenir un peu brouillon, nous avons donc décidé de créer des sous-répertoires pour les différentes pages et d'y enregistrer le code nécessaire..

Par exemple, les styles CSS pour le sur page étaient dans css / about / styles.css. Le JavaScript dans js / about / scripts.js etc. Nous avons utilisé un script PHP qui concatène les fichiers. Il y avait, bien sûr, des parties du site qui figuraient sur plusieurs pages et nous les avons insérées commun des répertoires. C'était bon pendant un certain temps, mais cela n'a pas fonctionné longtemps, car lorsque les répertoires étaient pleins, il était lent à modifier quelque chose. Vous avez dû rechercher trois répertoires différents pour trouver ce dont vous aviez besoin. Le site était encore principalement écrit en PHP.

Problème n ° 2 - Le grand tournant ou comment nous avons gâché les choses

A cette époque, les applications mobiles sont devenues populaires. Le client souhaitait que son site soit disponible pour les appareils mobiles et c’est le grand tournant du projet. Nous avons dû convertir le site en une application à une seule page. Et pas seulement cela, il devait avoir des tonnes de fonctionnalités en temps réel. Bien entendu, tout le contenu du site ne devait pas être chargé de manière dynamique. Le référencement était toujours un élément important de la vision du client. Nous avons choisi la pile MEAN pour les prochaines pièces. Le problème était avec les anciennes pages. Leur contenu devait être servi par PHP, mais la logique des pages a changé et il a été entièrement créé avec JavaScript. Pendant plusieurs semaines, nous nous sommes sentis comme les passagers du Titanic. Nous étions pressés de libérer quelque chose, mais il y avait trou après trou et très vite, notre bateau était plein d'eau (insectes).

Problème n ° 3 - Un processus de travail difficile

Nous avons utilisé GruntJS pendant un certain temps, mais avons migré vers Gulp. Cela nous a beaucoup aidé car nous avons augmenté notre vitesse de développement. Cependant, il était encore trop ennuyeux d’ajouter ou de modifier des composants existants. La solide architecture que nous avions au début a été transformée en un mélange complexe de fichiers. Oui, il y avait des conventions strictes pour nommer et placer ces fichiers, mais c'était encore trop compliqué. Nous nous sommes ensuite cogné la tête et avons proposé le format suivant:

Nous avons divisé le site en différents composants, qui ressemblaient à des boîtes noires. Ils vivent dans leur propre dossier. Tout ce qui concerne le composant a été enregistré dans son répertoire. Nous avons soigneusement conçu les API des classes. Ils étaient testables et communicatifs. Nous avons constaté qu'une telle structure fonctionnait mieux pour nous car nous avions des tonnes de modules indépendants. Oui, nous mélangeons les fichiers JavaScript avec des styles CSS et des modèles HTML, mais il était simplement plus facile de travailler à l'unité, au lieu de creuser profondément dans plusieurs répertoires..

Problème n ° 4 - Code angulaire vs code personnalisé

Les pages anciennes que nous devions livrer via PHP étaient également pleines de logique JavaScript. Cependant, dans certains cas, Angular ne fonctionnait pas très bien. Nous avons dû faire de petites manipulations pour que tout se passe bien. Nous nous sommes retrouvés avec un mélange de contrôleurs angulaires et de code personnalisé. La bonne nouvelle est que le budget du projet a été élargi et nous avons décidé d'utiliser notre propre cadre. A cette époque, je développais mon propre préprocesseur CSS. Le projet va vraiment très vite. Très vite, j'ai porté ma bibliothèque pour une utilisation côté client. Ligne par ligne, il a été transformé en un petit cadre que nous avons commencé à intégrer au projet..

Pourquoi créer un nouveau cadre??

C'est probablement ce que vous demandez. Eh bien, il y en a une douzaine d'autres qui offrent un large éventail de capacités. Oui, c'est vrai, mais… nous n'avions pas besoin d'un large éventail de capacités. Nous avions besoin de choses spécifiques et rien de plus. Nous étions prêts à accepter le fait qu’en utilisant un framework populaire, nous puissions ajouter quelques kilo-octets à la charge totale de la page. Ce n'était pas un gros problème. 

Le statut de notre base de code était le problème. Nous nous sommes concentrés sur la construction d'une bonne architecture et nous sommes tous d'accord pour dire que parfois la solution personnalisée convient mieux. L'utilisation de Angular, Ember, Knockout ou Backbone présente des avantages, mais la vérité est qu'il n'existe pas de cadre universel.. 

J'aime les paroles de Jeremy Keith, dans son discours intitulé Le pouvoir de la simplicité, il a dit que la chose la plus importante lors du choix de votre outil est la philosophie de la personne qui l'a fabriqué et si cette philosophie est en harmonie avec la vôtre. Si les idées du cadre ne correspondent pas aux vôtres, vous irez très vite à l’encontre de celles-ci. La même chose nous est arrivée. Nous avons essayé d’utiliser Angular et il y avait trop de difficultés. Problèmes que nous avons pu résoudre, mais nous avons utilisé des hacks et des solutions de contournement complexes. 

Nous avons également essayé Ember, mais cela n’a pas fonctionné, car il est fortement basé sur ses mécanismes de routage. Backbone était un bon choix et c'était ce qui se rapprochait le plus de notre vision. Cependant, quand j'ai présenté AbsurdJS, nous avons décidé de l'utiliser.

Ce qu'AbsurdJS a fait pour nous

AbsurdJS a été initialement lancé en tant que préprocesseur CSS, étendu à un préprocesseur HTML et il a été porté avec succès pour une utilisation côté client. Donc, au début, nous l’utilisons pour compiler JavaScript en HTML ou CSS. Oui, tu m'as bien entendu; nous avons commencé à écrire nos styles et nos balises en JavaScript (ça a probablement l'air étrange, mais continuez à lire). J'ai poussé la bibliothèque et une douzaine de fonctionnalités ont été ajoutées.

Diviser pour régner

Lorsque vous avez un système complexe, avec plusieurs pages, vous ne voulez vraiment pas résoudre de gros problèmes. Il est bien préférable de tout scinder en tâches plus petites et de les résoudre un à un. Nous avons fait la même chose. Nous avons décidé que notre application serait construite à partir de composants plus petits, comme suit:

var absurd = Absurd (); var MyComp = absurd.component ('MyComp', constructeur: function () //…); var instance = MyComp (); 

composant absurde définit une classe. Appeler le MyComp () méthode crée une nouvelle instance.

Parlons l'un à l'autre

Ayant tous ces petits composants, nous avions besoin d'un canal de communication. Le motif de l'observateur était parfait pour ce cas. Ainsi, chaque composant est un répartiteur d'événements.

var MyComp = absurd.component ('MyComp', doQuelque chose: function () this.dispatch ('quelque chose se passe');); var instance = MyComp (); instance.on ('quelque chose se passe', function () console.log ('Hello!');); instance.doquelquechose (); 

Nous sommes également en mesure de transmettre des données avec le message. La définition des composants et leur nature "listen-dispatch" sont assez triviales. J'ai adopté ce concept à partir des autres cadres populaires, car il semble naturel. Il était également beaucoup plus facile pour mes collègues de commencer à utiliser AbsurdJS.

Contrôler le DOM

En plus du balisage PHP servi, nous avons créé dynamiquement des éléments DOM. Cela signifie que nous avions besoin d'accéder aux éléments DOM existants ou à de nouveaux éléments, qui seront ultérieurement ajoutés à la page. Par exemple, supposons que nous ayons le code HTML suivant:

Titre de la page

Lorem ipsum dolor sit amet, consectetur elip adipiscing elit.

Voici un composant qui récupère l'en-tête:

absurd.component ('MyComp', html: '.content h1', constructeur: function () this.populate (); console.log (this.el.innerHTML); // Titre de la page) (); 

le peupler la méthode est la seule la magie méthode dans toute la bibliothèque. Il fait plusieurs choses comme compiler CSS ou HTML, il lie des événements et de telles choses. Dans l'exemple ci-dessus, il voit qu'il y a un html propriété et initialise le el variable qui pointe vers l'élément DOM. Cela fonctionne assez bien pour nous car une fois que nous avons eu cette référence, nous avons pu travailler avec les éléments et ses enfants. Pour les composants nécessitant des éléments créés dynamiquement, la html propriété accepte un objet.

absurd.component ('MyComp', html: 'div.content': h1: 'Titre de la page', p: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', constructeur: function () this .populate (); document.querySelector ('body'). appendChild (this.el);) (); 

Le JSON ci-dessus est traduit dans le même balisage HTML. J'ai choisi JSON parce que, d'un point de vue JavaScript, il est beaucoup plus flexible. Nous sommes en mesure de fusionner des objets, de remplacer ou de supprimer seulement des parties de celui-ci. Dans la plupart des frameworks populaires, les modèles ne sont que du texte brut, ce qui les rend difficiles à manipuler. AbsurdJS a également son propre moteur de templates.

absurd.component ('MyComp', html: 'div.content': h1: '<% this.title %>', ul: ['<% for(var i=0; i',  li: '<% this.availableFor[i] %>','<%  %>'], titre:' C'est génial ', disponiblePour: [' tous les navigateurs ',' Node.js '], constructeur: function () this.populate (); document.querySelector ('body'). appendChild (this.el); ) (); 

Le résultat est:

C'est génial

  • tous les navigateurs
  • Node.js

le ce mot-clé dans les expressions ci-dessus, pointe vers le composant lui-même. Le code entre <% et %> est valide JavaScript. Ainsi, des caractéristiques telles que les propriétés calculées pourraient être facilement développées directement dans la définition du modèle. Bien entendu, nous pouvons utiliser le même moteur de gabarit avec des balises déjà existantes. Par exemple:

<% this.title %>

    <% for(var i=0; i<this.availableFor.length; i++) %>
  • <% this.availableFor[i] %>
  • <% %>

… Pourrait être contrôlé avec le composant suivant (le résultat est le même):

absurd.component ('MyComp', html: '.content', titre: 'C'est génial', disponiblePour: ['tous les navigateurs', 'Node.js'], constructeur: function () this.populate ();) (); 

Quoi qu'il en soit, le fait est que nous avons pu définir des modèles ou créer de tels modèles à partir de rien. Nous sommes également en mesure de contrôler les données injectées de manière simple et naturelle. Tout n'est que propriétés du bon vieil objet JavaScript.

Qu'en est-il du style?

Nous avons réussi à scinder l'ensemble du système en petits modules. Les parties qui étaient avant les contrôleurs angulaires sont devenues des composants AbsurdJS. Nous avons réalisé que leur code HTML était étroitement lié à leur définition, ce qui a complètement modifié la gestion du balisage dans l'application. Nous avons cessé de penser à la concaténation, aux conventions ou à quelque chose du genre. Nous n'avons pas du tout créer de fichiers HTML. Quand je regarde en arrière, je pouvais voir ce moment exact dans notre histoire de commit. Il est facilement visible car de nombreux fichiers ont été supprimés de la base de code..

Ensuite, j'ai pensé à ce qu'il va se passer si nous faisons la même chose avec le CSS. C'était bien sûr possible car AbsurdJS était un pré-processeur CSS et pouvait produire du CSS. Nous venons de recevoir la chaîne compilée, créer un nouveau style tag dans le tête de la page actuelle et l'injecter là.

absurd.component ('MyComp', css: '.content': h1: color: '# 99FF00', remplissage: 0, marge: 0, p: fontSize: '20px', html : '.content', constructeur: function () this.populate ();) (); 

Voici la style tag qui est produit:

Et jour après jour, nous avons transféré les styles CSS des fichiers SASS (car nous avons parfois choisi SASS en tant que préprocesseur CSS) aux composants AbsurdJS. Pour être honnête, c'était assez facile car tous les mixins et les variables que nous avons ont été définis comme des fonctions et des variables JavaScript. Le partage des styles était encore plus facile car tout était JavasSript.

Ce moment génant

… Quand tout fonctionne parfaitement mais que vous sentez que quelque chose ne va pas

Nous examinions le code. Ça a marché. AbsurdJS a conduit même les pièces anciennes. Le nouveau matériel utilise la même bibliothèque. Le HTML et le CSS ont été bien séparés et placés directement dans la définition des composants. Cependant, je sentais qu'il y avait quelque chose qui n'allait pas. Je me suis arrêté un moment et je me suis demandé: "De quoi est fait le Web?".

Et ce que nous avons fait est un peu différent. Cela ressemble plus à l'image ci-dessous.

Je construis des sites Web depuis plus de dix ans et je me souviens de l'époque où nous nous sommes tous battus pour la séparation de ces trois matériaux de construction. Et ce que j'ai fait dans ce projet est exactement le contraire. Il n'y avait pas (presque) de fichiers CSS et HTML. Tout était JavaScript. 

Beaucoup de gens diront que c'est ridicule et que nous devrions rendre l'argent du client. Oui, cela pourrait être vrai, mais ce concept a parfaitement fonctionné dans notre cas. Nous n'avons pas écrit d'application. En fait, nous avons écrit un tas de composants indépendants. Je crois que le Web sera une combinaison de composants prêts à l'emploi. 

En tant que développeurs, nous devrons développer de tels composants et probablement nous connecter et utiliser de tels composants écrits par d’autres. Des projets comme AbsurdJS ou Polymer montrent que cela est possible et je vous encourage à expérimenter dans cette direction..

Retour à la réalité

Au final, les affaires du client se sont bien déroulées. C'était tellement bon qu'il a décidé de lancer un nouveau service. Et devine quoi. Il souhaitait que certaines parties de la demande existante soient transférées dans le nouveau projet. Je ne peux pas vous dire à quel point nous étions heureux de déplacer des composants d'un endroit à un autre. Nous n’avions pas à installer quelque chose, copier du balisage HTML ou des fichiers CSS. Nous venons de recevoir le fichier JavaScript du composant, de le placer quelque part et d'en créer une instance. Cela fonctionnait simplement car il n'y avait pas de dépendances. Je ne serais pas surpris que certains de ces composants soient mis en vente très bientôt. Ils sont assez légers et fournissent une fonctionnalité intéressante liée au produit du client.

Oui, nous avons enfreint certaines règles. Règles que je suis personnellement d'accord avec. Règles que j'ai suivies pendant de nombreuses années. Cependant, la réalité est que nous voulons tous de la qualité et que parfois cette qualité est accessible en enfreignant les règles. Nous voulons produire un bon code, bien structuré, facile à gérer, flexible et extensible. Nous ne voulons pas regarder en arrière et dire, "Oh mon dieu… est-ce que ça a été écrit par moi!?". Quand je regarde en arrière maintenant, je sais pourquoi le code a cette apparence. Ça ressemble à ça parce que ça a été écrit spécialement pour ce projet.

Conclusion

Si vous avez trouvé ce tutoriel intéressant, consultez la page officielle d’AbsurdJS. Il existe des guides, de la documentation et des articles. Vous pouvez même essayer la bibliothèque en ligne. Comme tous les autres outils, AbsurdJS est conçu pour un usage spécifique. Cela convient bien à notre projet et pourrait convenir au vôtre. Je n'appelle même pas cela un cadre, parce que je n'aime pas cette définition. Cela ressemble plus à une boîte à outils qu'à un framework complet. N'hésitez pas à l'expérimenter, à faire des demandes d'extraction ou à soumettre des problèmes. C'est complètement open source et disponible sur GitHub.