Si ce n'était pas le cas, pour une chose, je serais tout à fait d'accord pour écrire tous mes modules comme
import A from './a.js';
var B = function(){
//utiliser A
};
export default B;
puis utiliser un compilateur pour construire cela dans un format de navigateur ou de serveur.
Cependant, mon seul problème avec ce qui précède est la spécification explicite de ./a.js
dans l'import
.
Je comprends pourquoi la spécification a choisi cette voie1, pour favoriser l'analyse statique. Mais il y a deux raisons très pratiques pour lesquelles intégrer à la fois le nom de fichier et son chemin dans un module sont problématiques.
- Comme déjà mentionné ici, lorsque vous recyclez fréquemment des modules d'un projet à un autre, il est fort probable que vous ne puissiez pas maintenir un chemin cohérent vers cette ressource dans votre arborescence de projet. Intégrer un appel d'importation comme
import myModule from './../../vendor/lib/dist/mod.js'
dans le code d'un module ne me semble pas exactement une solution pérenne. -
En plus du chemin lui-même, spécifier le nom de fichier vous attache également. Quelque chose comme ceci semble innocent :
import $ from 'vendor/jquery.js'
Mais que se passera-t-il le jour où je voudrai utiliser Zepto au lieu de jQuery? J'ai trouvé l'abstraction, en particulier autour des bibliothèques de fournisseurs, extrêmement utile lors de la manipulation de bases de code volumineuses, de développeurs avisés et d'un écosystème JavaScript en évolution constante. Je voudrais peut-être importer React en tant que ma bibliothèque de composants aujourd'hui, mais qu'en est-il de demain ? De plus, que se passe-t-il si je vais utiliser le même module à la fois côté client et côté serveur, mais j'ai besoin de versions différentes d'une bibliothèque dépendante?
Je tiens à une abstraction robuste (mais claire et cohérente) dans mes équipes. Souvent, l'abstraction a pris la forme d'une sorte de nommage. J'ai un peu fantasmé à ce sujet :
//MAUVAIS: Incorporation de React dans mes modules de composants
import ComponentLib from './React.js';
//BON : Me laisse libre d'utiliser n'importe quelle bibliothèque similaire à React
import ComponentLib from 'vendor.lib.component';
Où vendor.lib.component
, à la manière de Java, a été enregistré quelque part auparavant.
À noter que, contrairement à cette question, mon objectif n'est pas d'avoir un contrôle dynamique sur mes importations. Je ne veux pas de flexibilité à l'exécution, j'aimerais avoir de la flexibilité à la construction. Je devrais pouvoir remplacer un framework dépendant par un autre, ou par un faux, ou par quelque chose qui fonctionnera dans un environnement particulier, sans devoir m'inquiéter des dépendances que mes modules appellent, ou essayer de dupliquer un arbre de répertoires fou pour chaque produit de construction que je recherche.
Des questions similaires ont conduit à la suggestion d'une bibliothèque qui tire parti de la spécification Système, comme SystemJS. Vous pouvez ensuite utiliser quelque chose comme jspm pour introduire une carte de modules pour obtenir une abstraction. Mais au moment où je fais cela, j'écris tous mes modules différemment :
System.import('a', function(A){
//utiliser 'A'
});
Est-ce soudainement l'avenir ? Si c'est le cas, pourquoi ne devrais-je pas simplement continuer à utiliser AMD ? Pourquoi même se donner la peine d'utiliser des modules ES2015 et d'exécuter des transpilateurs si je vais juste revenir à utiliser une API de chargement qui ressemble à de l'asynchrone ?
Encore plus décourageant, je ne vois pas beaucoup ou pas du tout de mention de l'attaque d'une norme d'API de chargeur de modules dans la spec ES2017.
(EDIT : Question révisée pour répondre aux normes d'une réponse non basée sur l'opinion)
Étant donné tout ce qui précède, je demande à la communauté -- comment puis-je écrire un module JavaScript qui (i) respecte la norme ES2015, (ii) ne fait pas référence à un module dépendant par son nom de fichier ou son chemin, et (iii) ne dépend pas d'outils/configuration intermédiaires étendus qui rendraient le partage du module avec plusieurs équipes prohibitif.
--
Note 1 Comme l'a noté @zeroflagL dans les commentaires, la spécification ne précise pas explicitement qu'un module doit être spécifié comme un chemin, juste une chaîne (voir ModuleSpecifier - http://www.ecma-international.org/ecma-262/6.0/#table-41). Cependant, il y a aussi une instruction claire pour prendre en compte les références circulaires, impliquant une sorte d'analyse statique (http://www.ecma-international.org/ecma-262/6.0/#sec-imports), les chemins de fichiers semblant être le contexte de référence privilégié jusqu'à présent. Nous ne pouvons donc pas blâmer la spécification d'être rigide ici, plutôt le contraire. Il incombe alors au reste d'entre nous de développer des implémentations plus robustes de import
/ModuleSpecifier qui mènent à une norme secondaire.
3 votes
Cela semble être un sujet intéressant, mais ce n'est pas adapté à Stack Overflow, car il n'y a pas de réponse unique correcte.
0 votes
Vous pouvez personnaliser/augmenter le chargeur pour faire ce que vous voulez.
0 votes
@ Felix, il peut ne pas y avoir de réponse correcte, mais je pense qu'il y a une meilleure réponse. @ torazaburo, je le sais, mais ma question ne porte pas sur la capacité, elle concerne les normes. Pourquoi écrirais-je des modules que j'aimerais que d'autres utilisent basés sur une implémentation de chargeur folle que seule moi utilise?
0 votes
Je suis d'accord avec @FelixKling, si nous interprétons les règles strictement, mais laissons-les fléchir pour que nous puissions continuer à avoir une discussion importante sur un sujet important. Ceci devrait absolument être abordé dans la prochaine spécification, sinon il y aura de la douleur
0 votes
Je ne comprends pas votre problème avec SystemJS. Si vous utilisez un transpileur, vous n'avez pas à vous soucier de l'API asynchrone (après transpilage) et vous avez votre configuration système où vous pouvez choisir librement vos noms de paquets.
import { A, B } from 'wherever'
me semble bien. Je ne suggère pas que SystemJS soit la solution idéale. J'essaie simplement de comprendre vos objections.0 votes
@Hampus Je parle en termes de réutilisabilité de modules plus larges, des modules qui seront réutilisés non seulement par moi-même mais aussi par d'autres équipes et d'autres organisations. Forcer l'inclusion de (i) une bibliothèque particulière comme SystemJS, et (ii) un transpileur, signifie beaucoup de travail de configuration supplémentaire pour quiconque voulant compiler mon module dans leur projet. Bien sûr, c'est faisable, et c'est ce que la plupart des développeurs JS finissent par devoir faire dans ces situations, mais je ne qualifierais pas cela de meilleure solution. Ce dont nous avons besoin, c'est d'une norme, mais la norme des modules ES2015 semble insuffisante pour les raisons énoncées ci-dessus.
0 votes
"Je comprends pourquoi la spécification a suivi cette voie ... Mais il y a deux raisons très pratiques pour lesquelles intégrer à la fois le nom de fichier d'un module et son chemin pose problème." La spécification ne vous oblige pas à le faire.
0 votes
@zeroflagL vous avez tout à fait raison, j'ai fait un saut trop grand. J'ai ajouté une note à ma question. Merci pour le commentaire.