Maison > interface Web > js tutoriel > Une brève analyse de la modularisation JavaScript

Une brève analyse de la modularisation JavaScript

高洛峰
Libérer: 2017-02-04 16:24:58
original
1165 Les gens l'ont consulté

Préface

Concernant la modularisation, la manifestation la plus directe est les mots-clés require et import que nous écrivons. Si vous vérifiez les informations pertinentes, vous rencontrerez certainement les termes CommonJS, CMD AMD, ainsi que RequireJS, SeaJS. , etc. Cadre étrange. Par exemple, le site officiel de SeaJS se décrit ainsi : "Spécifications de définition de module simples et conviviales, Sea.js suit la spécification CMD. Organisation naturelle et intuitive du code, chargement automatique des dépendances..."

Comme un novice du front-end, je suis honnête. Il avait l'air confus et ne pouvait pas comprendre. Selon mon style habituel, avant d'introduire quelque chose, je dois toujours expliquer pourquoi c'est nécessaire.

Bases de JavaScript

Les étudiants qui travaillent côté client doivent être familiers avec le #import "classname" d'OC, les modules et les modificateurs de fichiers de Swift, ainsi que le mode de classe de package d'importation de Java. Nous sommes habitués au modèle selon lequel le référencement à un fichier fait référence à une classe. Cependant, dans un langage dynamique comme JavaScript, les choses ont changé :







Bonjour Wrold



// index.js
function onPress() {
var p = document.getElementById('hello');
p.innerHTML = 'Bonjour bestswifter';
}

Le < script> en HTML peut être compris comme une importation, de sorte que l'événement onclick du bouton puisse appeler la fonction onPress définie dans index.js.

Supposons qu'au fur et à mesure que le projet se développe, nous constatons que le texte cliqué doit être généré dynamiquement et généré par d'autres fichiers JS, alors un simple index.js ne pourra pas faire le travail. Nous supposons que le contenu généré est défini dans le fichier math.js :

// math.js
function add(a, b) {
return a b;
}

Selon la réflexion du client, le fichier index.js à ce moment devrait être écrit comme ceci :

// index.js
import "math.js"

function onPress() {
var p = document.getElementById('hello');
p.innerHTML = add(1, 2);
}

Malheureusement , JavaScript n'est pas pris en charge. Cette façon d'écrire l'importation signifie que les méthodes d'un fichier JS ne peuvent pas du tout être référencées dans d'autres fichiers JS. La bonne solution consiste à appeler la méthode add directement dans index.js et à référencer math.js dans index.html :





< /head>


Bonjour Wrold





// index.js
function onPress() {
var p = document. getElementById('hello');
p.innerHTML = add(1, 2);
}

Vous voyez que cette façon d'écrire n'est pas élégante pour Index.js. n'avez aucun contrôle sur le contenu des autres fichiers JS. La possibilité d'appeler la méthode add dépend entièrement du fait que votre propre fichier HTML a correctement référencé d'autres fichiers JS.

Modularisation préliminaire

Les problèmes que nous venons de mentionner peuvent en fait être divisés en deux types :

index.js ne peut pas être importé et s'appuie sur des références HTML

La source de la méthode add ne peut pas être distinguée dans index.js et le concept d'espace de noms est manquant

La première question recevra une réponse plus tard. Résolvons d'abord la deuxième question, comme mettre la fonction dans un objet. first. , afin que nous puissions exposer un objet et permettre aux utilisateurs d'appeler plusieurs méthodes de cet objet :

//index.js
function onPress() {
var p = document.getElementById(' bonjour');
p.innerHTML = math.add(1, 2);
}

//math.js
var math = {
base : 0,
add: function(a, b) {
return a b base;
},
};

Vous pouvez voir que vous pouvez déjà spécifier une fonction simple dans index Version .js de l'espace de noms (c'est-à-dire mathématique). Mais il reste encore un petit problème. Par exemple, l'attribut de base sera exposé au monde extérieur et pourra également être modifié. Une meilleure façon est donc de définir math dans une fermeture pour masquer les propriétés internes :

// math.js
var math = (function() {
var base = 0;
return {
ajouter : function(a, b) {
return a b base;
},
};
})();

Jusqu'à présent, nous avons mis en œuvre la définition et l'utilisation des modules. Cependant, l'essence de la modularisation réside dans l'espace de noms, ce qui signifie que nous espérons que notre module mathématique ne sera pas global, mais importé à la demande, même si plusieurs fichiers exposent des objets portant le même nom, il n'y en aura pas. problème. Tout comme dans node.js, le module qui doit être exposé définit son propre contenu d'exportation, puis l'appelant utilise la méthode require.

En fait, vous pouvez simplement simuler le mode de fonctionnement de node.js et le résoudre en ajoutant une couche intermédiaire : Définissez d'abord une variable globale :

// global.js
var module = {
exports : {}, // Utilisé pour stocker tout le contenu exposé
};

  Ensuite, exposez l'objet dans math.js :

var math = ( function() {
var base = 0;
return {
ajouter : function(a, b) {
return a b base;
},
};
} )();

module.exports.math = math;

L'utilisateur index.js devrait maintenant être :

var math = module.exports. math ;

function onPress() {
var p = document.getElementById('hello');
// math
p.innerHTML = math.add(1, 2);
}

Solutions modulaires existantes

La méthode de modularisation simple ci-dessus présente quelques problèmes mineurs. Tout d'abord, index.js doit strictement s'appuyer sur l'exécution de math.js, car ce n'est qu'après l'exécution de math.js qu'il s'enregistrera auprès du module global.export. Cela oblige les développeurs à gérer manuellement l'ordre de chargement des fichiers js. À mesure que les projets prennent de l’ampleur, la maintenance des dépendances devient de plus en plus complexe.

Deuxièmement, puisque le navigateur cessera de restituer la page Web lors du chargement du fichier JS, nous avons également besoin d'un chargement asynchrone à la demande du fichier JS.

Le dernier problème est que la solution de modularisation simplifiée donnée précédemment ne résout pas l'espace de noms du module. La même exportation remplacera toujours le contenu précédent, et la solution est de conserver un "chemin de fichier< ;–> Exporter le contenu". " et chargez-la en fonction du chemin du fichier.

Sur la base des besoins ci-dessus, de nombreux ensembles de solutions modulaires sont apparus sur le marché. La raison pour laquelle il existe plusieurs ensembles de normes est en fait due aux caractéristiques du frontal. En raison de l'absence d'une norme unifiée, dans de nombreux cas, tout le monde s'appuie sur des conventions pour faire des choses, comme l'exportation et les exigences mentionnées ci-dessus. Si le fournisseur du code stocke le contenu de l'exportation dans module.exports et que l'utilisateur lit module.export, c'est naturellement en vain. De plus, les méthodes de mise en œuvre et les scénarios d'utilisation de chaque spécification sont également différents.

CommonJS

Les spécifications les plus connues incluent CommonJS, AMD et CMD. Les frameworks bien connus Node.js, RequireJS et Seajs implémentent respectivement les spécifications ci-dessus.

La première spécification est CommonJS, qui est utilisée par Node.js. Cette spécification est similaire à notre approche précédente, qui consiste à charger des scripts JS de manière synchrone. Il n'y a aucun problème à faire cela côté serveur, car les fichiers sont stockés sur le disque. Cependant, les caractéristiques du navigateur déterminent que le script JS doit être chargé de manière asynchrone, sinon il perdra la réponse, donc la spécification CommonJS ne peut pas le faire. être utilisé directement dans le navigateur.

AMD 

Le célèbre outil de gestion de modules Require.js côté navigateur est chargé de manière asynchrone, chargeant le script JS via la fonction importScripts(url) de Webworker, puis exécutant le rappel initialement enregistré ; . La méthode d'écriture de Require.js est :

require(['myModule1', 'myModule2'], function (m1, m2){
// Logique de rappel principale
m1.printName() ;
m2.printName();
});

Puisque ces deux modules sont téléchargés de manière asynchrone, il n'est pas certain quel module sera téléchargé et exécuté en premier, mais il est certain que le module principal sera téléchargé et exécuté en premier. Le rappel doit être exécuté une fois que toutes les dépendances ont été chargées.

Cette façon d'écrire Require.js est également appelée chargement frontal. Toutes les dépendances doivent être spécifiées avant d'écrire la logique principale, et ces dépendances seront immédiatement chargées de manière asynchrone.

 La spécification dérivée de Require.js est appelée AMD (Asynchronous Module Definition).

CMD

Un autre excellent outil de gestion de modules est Sea.js. Sa méthode d'écriture est :

define(function(require, exports, module) {
var foo. = require('foo'); // Synchronisation
foo.add(1, 2);
...
require.async('math', function(math) { // Asynchrone
math.add(1, 2);
});
});

Sea.js est également appelé chargement à proximité, d'après la façon dont il est écrit, c'est évident. pour voir la différence avec Require.js. Nous pouvons déclarer des dépendances uniquement lorsque nous devons les utiliser.

Lorsque Sea.js rencontre une dépendance, il téléchargera uniquement le fichier JS et ne l'exécutera pas. Au lieu de cela, il attendra que tous les scripts JS dépendants aient été téléchargés avant d'exécuter la logique principale à partir de zéro. Par conséquent, l’ordre d’exécution des modules dépendants est exactement le même que l’ordre d’écriture.

La spécification dérivée de Sea.js est appelée CMD (Common Module Definition).

Modularité ES 6

Dans ES6, nous utilisons le mot-clé export pour exporter des modules et le mot-clé import pour référencer des modules. Il convient de noter que cet ensemble de normes d'ES 6 n'est pas directement lié aux normes actuelles, et actuellement peu de moteurs JS peuvent le prendre directement en charge. Par conséquent, Babel traduit en fait l'importation non prise en charge en demande actuellement prise en charge.

Bien qu'il y ait actuellement peu de différence entre l'utilisation de import et require (essentiellement la même chose), il est toujours fortement recommandé d'utiliser le mot-clé import, car une fois que le moteur JS pourra analyser le mot-clé import ES 6, l'ensemble de l'implémentation sera de la même manière que de grands changements ont lieu actuellement. Si vous commencez à utiliser le mot-clé import maintenant, les changements de code à l'avenir seront très minimes.

via : http://fullstack.blog/2017/01/25/JavaScript Modularization Brief/

Pour plus d'articles sur l'analyse brève de la modularisation JavaScript, veuillez faire attention au site Web PHP chinois !

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal