Comment / où Magento convertit-il un nom de module RequireJS en URL?

8

Dans Magento 2, vous pouvez utiliser RequireJS pour inclure un module javascript avec du code qui ressemble à ceci.

#File: app/code/Package/Name/view/frontend/requirejs-config.js
var config = {
    map: {
        '*': {
            modulename: 'Package_Name/js/path/to/file'
        }
    }
}

Bien que le requirejs-config.jsfichier soit un peu de magie Magento 2, cela semble être le RequireJS standard. Vous mappez essentiellement le nom court modulenameau module javascript nommé Package_Name/js/path/to/file.

Ce qui n'est pas clair, c'est où ou comment Magento 2 convertit le nom du module javascript ci-dessus

Package_Name/js/path/to/file

Dans l'URL HTTP (S)

//magento.example.com/static/frontend/Magento/luma/en_US/Package_Name/js/path/to/file.js

Dans un système Stock RequireJS, RequireJS essaierait de charger l'URL suivante

//magento.example.com/Package_Name/js/path/to/file.js

Il est donc clair que Magento fait quelque chose pour s'assurer que l'URL ci-dessus est convertie en URL frontend Magento. Ce qui n'est pas clair, c'est

  1. Où cela se produit (couche PHP? Couche Javascript?)
  2. Quelle est la règle pour cette conversion. Le module RequireJS ne ressemble pas à un identifiant de fichier Magento standard ( Package_Name::js/path/to/file)

Alors, comment / où Magento 2 / RequireJS convertit-il le module en chemin.

Alan Storm
la source

Réponses:

7

RequireJS a une fonctionnalité qui vous permet de définir une baseUrl personnalisée .

Magento génère baseUrl pour RequireJS dans le corps de la page, où les ressources JS sont demandées. Donc, c'est fondamentalement une partie de plus de la configuration RequireJS générée par Magento. Cette baseUrl est calculée côté serveur et est basée sur le thème, les paramètres régionaux et l'URL de base actuels pour les fichiers de vue statique pour le magasin. Ensuite, la fonctionnalité native RequireJS calcule le chemin complet comme suit

baseUrl + file + '.js'
BuskaMuza
la source
Cela ne semble pas répondre à la question que j'ai posée.
Alan Storm
Pourriez-vous, s'il vous plaît, clarifier la question? Magento utilise simplement la fonctionnalité RequireJS de baseUrl- requirejs.org/docs/api.html#config-baseUrl et pour le faire fonctionner correctement, il baseUrlest égal à //magento.example.com/static/frontend/Magento/luma/en_US/la page. RequireJS le concatène simplement avec le chemin du module: //magento.example.com/static/frontend/Magento/luma/en_US/ + Package_Name/js/path/to/file -> //magento.example.com/static/frontend/Magento/luma/en_US/Package_Name/js/path/to/fileet ajoute .js.
BuskaMuza
Informations utiles @BushaMuza, mais encore une fois, pas la question que j'ai posée.
Alan Storm
1
Je pense que c'est vanille RequireJS. Si la balise 'data-main' est définie (ce qui est par défaut M2), elle ajoutera la baseUrl qui est définie dans le fichier BuskaMuza références devant l'URL JS mappée. La baseUrl est définie sur le dossier statique (avec locale), qui est par exemple //magento.example.com/static/frontend/Magento/luma/en_US/. Ajoutez- Package_Name/js/path/to/file.jsy et vous aurez l'URL complète. Je pense que c'est ce que vous recherchez; github.com/magento/magento2/blob/develop/lib/web/requirejs/…
Peter Jaap Blaakmeer
7

Vous vous demandez comment

Module_Name/js/path/to/module

devient

//magento.example.com/static/frontend/Package/Theme/locale/Module_Name/js/path/to/module.js

Tout d'abord, il est important de comprendre que c'est entièrement nécessaire JS, pas de sauce spéciale Magento (bien qu'il y en ait ailleurs). Pour la plupart, le front-end utilise uniquement le comportement normal de RequireJS. La magie réside généralement dans la façon dont elle génère pub/static, à savoir comment view/area/web/js/path/to/module.jsest lié à un lien symbolique pub/static/area/Package/theme/Module_Name/js/path/to/module.js. Ceci est géré par le processus de compilation des actifs statiques de Magento, et je ne vais pas y entrer ici.

requirejs-config.js

Introduisons un nouveau fichier, que vous mentionnez: requirejs-config.js. Il s'agit d'une sauce spéciale Magento 2, mais probablement pas autant que vous ne le pensez.

Ce fichier peut être n'importe quel JavaScript, mais devrait au moins déclarer une variable (globale) appelée config. L'objet lié à configest transmis directement à requireJS pour le configurer.

La façon dont cela fonctionne est que Magento trouve tout requirejs-config.jsdans un projet. Ceux-ci peuvent être dans un module, sous view/areaou dans un thème, dans son répertoire racine, et dans la substitution de module d'un thème, par exemple Magento_Catalog/requirejs-config.js. Notez que cela n'inclut aucun enfant d'un webrépertoire. Ce fichier devrait en général être le frère d'un webrépertoire.

Une fois globlé, chaque fichier est décoré dans une fermeture (donc notre variable globale ne l'est pas), et une ligne à la fin de la fermeture transmet la configvariable à l' requireobjet. Cela se voit:

C’est Magento_Checkout::view/frontend/requirejs-config.js:

/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */

 var config = { 
 map: { 
 '*': { 
 discountCode: 'Magento_Checkout/js/discount-codes',
 shoppingCart: 'Magento_Checkout/js/shopping-cart', 
 regionUpdater: 'Magento_Checkout/js/region-updater', 
 opcOrderReview: 'Magento_Checkout/js/opc-order-review',
 sidebar: 'Magento_Checkout/js/sidebar', 
 payment: 'Magento_Checkout/js/payment', 
 paymentAuthentication: 'Magento_Checkout/js/payment-authentication' 
 }
 } 
};

Quand il arrive au front-end, il ressemblera à ceci:

(function() {
 /**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */

 var config = { 
 map: { 
 '*': { 
 discountCode: 'Magento_Checkout/js/discount-codes',
 shoppingCart: 'Magento_Checkout/js/shopping-cart', 
 regionUpdater: 'Magento_Checkout/js/region-updater', 
 opcOrderReview: 'Magento_Checkout/js/opc-order-review',
 sidebar: 'Magento_Checkout/js/sidebar', 
 payment: 'Magento_Checkout/js/payment', 
 paymentAuthentication: 'Magento_Checkout/js/payment-authentication' 
 }
 } 
}; require.config(config);
})();

Cette décoration peut être vue dans Magento\Framework\RequireJs\Config.

Chacun de ces fichiers décorés est concaténé et jeté static/_requirejs/area/Package/theme/locale/secure/requirejs-config.js. Cet emplacement est convenu à l'avance, de sorte que le code HTML charge ce script comme il charge requireJS:

<script type="text/javascript" src="https://magento.example.com/static/area/Package/theme/locale/requirejs/require.js"></script> <script type="text/javascript" src="https://magento.example.com/static/_requirejs/area/Package/theme/locale/secure/requirejs-config.js"></script>

Je considère comment configurer RequireJS hors de portée pour cette réponse, mais ils ont une assez bonne documentation à ce sujet . Il y a cependant deux choses importantes à noter:

  1. Les appels successifs à require.configsuperposeront les objets les uns sur les autres, donc la dernière écriture l'emportera. Ils ne remplacent pas, ce qui est crucial.
  2. Il existe une configuration en haut de cette configuration qui définit baseUrl. Ce n'est pas dans un requirejs-config.js. Il est inséré au moment de la compilation par Magento\Framework\RequireJs\Config.

Oubliant un instant comment Magento détermine quels modules RequireJS doivent être chargés (une bonne discussion pour une autre fois, peut-être; comme indice, regardez dans mage/apply/main.js), supposons que nous avons le code:

require(['modulename'], function () {});

quelque part dans le vide. Comment Magento sait-il quoi faire?

Eh bien, la première chose que requireJS fera sera de rechercher modulenamedans son mappage. Dans notre cas, il apprendra qu'il doit traiter toutes les demandes modulenamecomme une demande Module_Name/js/path/to/module. Il ne fait cela qu'une seule fois. Les mappages ne sont pas récursifs. Je répète. Si vous avez un mappage de aà bet de bà a, cela permutera chaque demande et ne provoquera pas de boucle infinie.

Une fois que nous avons parcouru la cartographie brouhaha, RequireJS regarde ce qu'il a. S'il se termine .jset ne ressemble pas à un lien absolu ou à une URL, il ajoutera le baseUrlscript configuré et chargera ce script via ses procédures normales. S'il ne se termine pas .jset n'est pas un lien ou une URL absolu, il ajoutera .jsà la fin, puis ajoutera la configuration baseUrlet chargera ses procédures normales. Si requireJS estime qu'il a une URL, il essaie simplement de la charger.

Max Bucknell
la source
OK, j'ai celui-ci. La pièce manquante pour moi était la configuration baseUrl de RequireJS. ie "RequireJS a une fonctionnalité qui vous permet de définir une baseUrl personnalisée, Magento utilise cette fonctionnalité et génère l'URL de base sur ce backend" requirejs.org/docs/api.html#config-baseUrl
Alan Storm
0

Il utilise les composants plus en détail, vous vérifiez la classe Magento \ Framework \ View \ Element \ Js \ Components et le fournisseur de fichiers de module par défaut \ magento \ module-catalog \ view \ frontend \ layout \ default.xml

<referenceContainer name="after.body.start">
        <block class="Magento\Framework\View\Element\Js\Components" name="head.components" as="components" template="Magento_Catalog::js/components.phtml"/>
    </referenceContainer>
Pratik
la source
Cela ne semble pas répondre à la question que j'ai posée.
Alan Storm