[Alleen PaaS]{class="badge informative" title="Is alleen van toepassing op Adobe Commerce op Cloud-projecten (door Adobe beheerde PaaS-infrastructuur) en op projecten in het veld."}

Geavanceerde JavaScript-pakketten

Bij het bundelen van JavaScript-modules voor betere prestaties gaat het om het reduceren van twee dingen:

  1. Het aantal serveraanvragen.
  2. De grootte van die serververzoeken.

In een modulaire toepassing, kan het aantal serververzoeken in honderden bereiken. De volgende schermafbeelding toont bijvoorbeeld alleen het begin van de lijst met JavaScript-modules die op de startpagina van een schone installatie zijn geladen.

geen bundeling

Samenvoegen en bundelen

Commerce ondersteunt bundeling om het aantal serveraanvragen te verminderen. Bundelen is standaard uitgeschakeld. U kunt het in Stores > Montages > Configuration > Advanced > Developer > JavaScript Settings, of van de bevellijn aanzetten.

Zie ​ Bundling uiteinden ​ in beste praktijken van de Configuratie voor derdetooling, HTTP/2, en begeleiding op afgekeurde JS en CSS fusie.

het Bundelen

Basisbundeling

Om ingebouwde bundeling van de bevellijn toe te laten:

php -f bin/magento config:set dev/js/enable_js_bundling 1

Dit is een native Commerce-mechanisme dat alle in het systeem aanwezige elementen combineert en deze onder bundels van hetzelfde formaat distribueert (bundle_0.js, bundle_1.js … bundle_x.js):

het bundelen van Commerce

Beter, maar browser laadt nog ALLE bundels van JavaScript, niet alleen nodig.

Commerce-pakketten verminderen het aantal verbindingen per pagina, maar voor elke paginaaanvraag worden alle bundels geladen, zelfs als de aangevraagde pagina alleen afhankelijk is van bestanden binnen een of twee van de bundels. De prestaties verbeteren nadat de bundels in de cache van de browser zijn geplaatst. Maar omdat de browser deze bundels synchroon laadt, kan het eerste bezoek van de gebruiker aan een Commerce-winkel even duren om de gebruikerservaring te renderen en te beschadigen.

Basissamenvoeging (niet aanbevolen)

NOTE
We raden u niet aan Merge JavaScript Files te gebruiken. Deze instelling is alleen ontworpen voor JavaScript die synchroon is geladen in de HEAD-sectie van de pagina en kan ertoe leiden dat het maken van pakketten en RequireJS -logica onjuist werken. Deze eigenschap wordt alleen behouden voor achterwaartse compatibiliteit en biedt geen prestatievoordeel wanneer HTTP/2 is ingeschakeld.
Als u Merge JavaScript Files hebt ingeschakeld en problemen ondervindt, schakelt u deze uit voordat u patches toepast. Zie ​ ACSD-67908 ​ als u het samenvoegen niet kunt onbruikbaar maken.

Ingebouwde samenvoeging via de opdrachtregel inschakelen:

php -f bin/magento config:set dev/js/merge_files 1

Met deze opdracht voegt u alle synchrone JavaScript-bestanden samen tot één bestand. Samenvoegen inschakelen zonder ook bundelen in te schakelen is niet nuttig omdat Commerce RequireJS gebruikt. Als u bundelen niet inschakelt, voegt Commerce alleen RequireJS en de bijbehorende configuratie samen. Wanneer u zowel bundelen als samenvoegen inschakelt, maakt Commerce één JavaScript-bestand:

Reëel-wereld het samenvoegen

Rendertijden in de praktijk

De vorige gebundelde en samengevoegde laadtijden zien er goed uit in een ontwikkelomgeving. Maar in de echte wereld kunnen veel dingen het renderen vertragen: langzame verbindingen, grote verbindingsdrempels, beperkte netwerken. Bovendien renderen mobiele apparaten niet zo snel als desktops.

Om uw storefront plaatsing voor de echte wereld te testen en voor te bereiden, adviseren wij u met het Chrome inheemse throttling profiel van "Traag 3G." te testen Met Trage 3G weerspiegelen onze vorige gebundelde uitvoertijden nu de verbindingsrealiteiten van veel gebruikers:

Reëel-wereld die bundelt

Bij Trage 3G-connectiviteit duurt het ongeveer 44 seconden om alle bundels te laden voor de startpagina van een schone Commerce-installatie.

Dit geldt ook voor het samenvoegen van de bundels in één bestand. Gebruikers konden nog steeds ongeveer 42 seconden wachten op het laden van de eerste pagina, zoals hier wordt getoond:

Reëel-wereld het samenvoegen

Met een geavanceerdere aanpak van JavaScript-bundeling kunnen we deze laadtijden verbeteren.

Geavanceerde bundeling

Het doel van JavaScript-pakketten is om het aantal en de grootte van aangevraagde elementen voor elke pagina die in de browser wordt geladen, te reduceren. Hiervoor willen we onze bundels maken, zodat elke pagina in onze winkel alleen een gemeenschappelijke bundel en een paginaspecifieke bundel hoeft te downloaden voor elke pagina die wordt geopend.

U kunt dit bereiken door uw bundels op paginatypen te definiëren. U kunt Commerce-pagina's indelen in verschillende paginatypen, zoals Categorie, Product, CMS, Klant, Winkel en Afhandeling. Elke pagina die in een van deze paginatypen is gecategoriseerd, heeft een andere set RequireJS module-afhankelijkheden. Wanneer u de RequireJS -modules bundelt op paginatype, krijgt u uiteindelijk slechts een handvol bundels die de afhankelijkheden van elke pagina in uw winkel bedekken.

U kunt bijvoorbeeld een bundel maken voor de afhankelijkheden die op alle pagina's van toepassing zijn, een bundel voor alleen CMS-pagina's, een bundel voor alleen Catalog-pagina's, een andere bundel voor alleen Search-pagina's en een bundel voor uitcheckpagina's.

U kunt ook pakketten maken op doeleinde: voor algemene functies, productgerelateerde functies, verzendfuncties, afrekenfuncties, belastingen en formuliervalidaties. Hoe u uw bundels bepaalt is aan u en de structuur van uw opslag. Sommige bundelingstrategieën werken mogelijk beter dan andere.

Een schone Commerce-installatie biedt voldoende goede prestaties door bundels op paginatypen te splitsen, maar voor sommige aanpassingen is mogelijk een diepgaande analyse en andere distributies van bedrijfsmiddelen vereist.

Vereiste gereedschappen

In de volgende stappen moet u de volgende programma's installeren en vertrouwd zijn met deze programma's:

Voorbeeldcode

Volledige versies van de voorbeeldcode die in dit artikel worden gebruikt, zijn hier beschikbaar:

Deel 1: Een bundelconfiguratie maken

1. Een bestand build.js toevoegen

Maak een build.js -bestand in de hoofdmap van de Commerce. Dit dossier zal de volledige bouwstijlconfiguratie voor uw bundels bevatten.

({
    optimize: 'none',
    inlineText: true
})

Later wijzigen we de instelling optimize: van_ none in uglify2 om de uitvoer van de bundel te minimaliseren. Maar voor nu, tijdens de ontwikkeling, kunt u het plaatsen aan none verlaten om snellere bouwstijlen te verzekeren.

2. RequireJS afhankelijkheden, vormen, paden en kaarten toevoegen

Voeg de volgende RequireJS buildconfiguratieknooppunten deps , shim , paths en map toe aan het constructiebestand:

({
    optimize: 'none',
    inlineText: true,

    deps: [],
    shim: {},
    paths: {},
    map: { "*": {} },
})

3 Instantiewaarden van requirejs-config.js samenvoegen

In deze stap moet u alle meerdere deps -, shim -, paths - en map configuratieknooppunten uit het requirejs-config.js -bestand van uw winkel samenvoegen tot de corresponderende knooppunten in uw build.js -bestand. Hiertoe opent u het tabblad Network in het deelvenster Gereedschappen voor ontwikkelaars van uw browser en navigeert u naar elke pagina in uw winkel, zoals de startpagina. Op het tabblad Netwerk ziet u de instantie van het requirejs-config.js -bestand van uw winkel bovenaan, die hier wordt gemarkeerd:

RequireJS configuration

In dit bestand vindt u meerdere items voor elk van de configuratieknooppunten (deps , shim , paths , map ). U moet deze veelvoudige knoopwaarden in de enige configuratieknooppunt van uw build.js- dossier samenvoegen. Als de requirejs-config.js -instantie van uw winkel bijvoorbeeld items bevat voor 15 aparte map knooppunten, moet u de items voor alle 15 knooppunten samenvoegen tot één map -knooppunt in uw build.js -bestand. Hetzelfde geldt voor de knooppunten deps , shim en paths . Zonder een script om dit proces te automatiseren kan het enige tijd duren.

U moet het pad mage/requirejs/text als volgt wijzigen in requirejs/text in paths -configuratienode:

({
    //...
    paths: {
        //...
        "text": "requirejs/text"
    },
})

4. Een moduleknooppunt toevoegen

Aan het eind van het build.js dossier, voeg de modules [] serie als placeholder voor de bundels toe u voor uw storefront later zult bepalen.

({
    optimize: 'none',
    inlineText: true,

    deps: [],
    shim: {},
    paths: {},
    map: { "*": {} },

    modules: [],
})

5 RequireJS afhankelijkheden ophalen

U kunt alle RequireJS module gebiedsdelen van de de paginatypen van uw opslag terugwinnen door te gebruiken:

  1. PhantomJS via de opdrachtregel (ervan uitgaande dat u PhantomJS hebt geïnstalleerd).
  2. RequireJS in de browserconsole.

Als u PhantomJS wilt gebruiken:

Maak in de hoofdmap van Commerce een nieuw bestand met de naam deps.js en kopieer het bestand in de onderstaande code. Deze code gebruikt PhantomJS om een pagina te openen en te wachten totdat de browser alle pagina-elementen laadt. Vervolgens worden alle RequireJS -afhankelijkheden voor een bepaalde pagina uitgevoerd.

"use strict";
var page = require('webpage').create(),
    system = require('system'),
    address;

if (system.args.length === 1) {
    console.log('Usage: $phantomjs deps.js url');
    phantom.exit(1);
} else {
    address = system.args[1];
    page.open(address, function (status) {
        if (status !== 'success') {
            console.log('FAIL to load the address');
        } else {
            setTimeout(function () {
                console.log(page.evaluate(function () {
                    return Object.keys(window.require.s.contexts._.defined);
                }));
                phantom.exit();
            }, 5000);
        }
    });
}

Open een terminal in de hoofdmap van Commerce en voer het script uit op elke pagina in uw winkel die een specifiek paginatype vertegenwoordigt:

phantomjs deps.js  url-aan-specifiek-pagina  >  tekst-dossier-vertegenwoordigen-pagina-gebiedsdelen 

Hier ziet u bijvoorbeeld vier pagina's uit de voorbeeldwinkel met het thema Luma die de vier paginatypen vertegenwoordigen die we gebruiken om onze vier pakketten te maken (homepage, categorie, product, winkelwagen):

phantomjs deps.js http://m2.loc/ > bundle/homepage.txt
phantomjs deps.js http://m2.loc/women/tops-women/jackets-women.html > bundle/category.txt
phantomjs deps.js http://m2.loc/beaumont-summit-kit.html > bundle/product.txt
phantomjs deps.js http://m2.loc/checkout/cart/?SID=m2tjdt7ipvep9g0h8pmsgie975 > bundle/cart.txt (prepare a shopping cart)
..............

De browserconsole gebruiken:

Als u PhantomJS niet wilt gebruiken, kunt u het volgende bevel van de console van uw browser in werking stellen terwijl het bekijken van elk paginatype in uw winkel:

Object.keys(window.require.s.contexts._.defined)

Met deze opdracht (gebruikt in het script PhantomJS ) wordt dezelfde lijst met RequireJS -afhankelijkheden gemaakt en weergegeven binnen de browserconsole. Het nadeel van deze benadering is dat u uw eigen bundel-/paginatype tekstbestanden moet maken.

6 De uitvoer opmaken en filteren

Nadat u de RequireJS gebiedsdelen in paginatype tekstdossiers samenvoegt, kunt u het volgende bevel op elk pagina-type gebiedsdeeldossier gebruiken om de komma's in uw dossiers met nieuwe lijnen te vervangen:

sed -i -e $'s/,/\\\n/g' bundle/category.txt
sed -i -e $'s/,/\\\n/g' bundle/homepage.txt
sed -i -e $'s/,/\\\n/g' bundle/product.txt
....

U zou ook alle menins voor elk dossier moeten verwijderen omdat de dubbele gebiedsdelen mengt. Gebruik het volgende bevel op elk gebiedsdeeldossier:

sed -i -e 's/mixins\!.*$//g' bundle/homepage.txt
sed -i -e 's/mixins\!.*$//g' bundle/category.txt
sed -i -e 's/mixins\!.*$//g' bundle/product.txt
...

7\ Unieke en algemene bundels identificeren

Het doel is om een gemeenschappelijke bundel van JavaScript dossiers tot stand te brengen nodig door alle pagina's. Op die manier hoeft de browser alleen de algemene bundel te laden samen met een of meer specifieke paginatypen.

Open een terminal in de hoofdmap van Commerce en gebruik de volgende opdracht om te controleren of u afhankelijkheden hebt die u in afzonderlijke bundels kunt splitsen:

sort bundle/*.txt |uniq -c |sort -n

Met deze opdracht voegt u de afhankelijkheden die in de bundle/*.txt -bestanden zijn gevonden samen en sorteert u deze. De output toont ook het aantal dossiers die elk gebiedsdeel bevatten:

1 buildTools,
1 jquery/jquery.parsequery,
1 jsbuild,
2 jquery/jquery.metadata,
2 jquery/validate,
2 mage/bootstrap,
3 jquery
3 jquery/ui
3 knockoutjs/knockout
...

Deze uitvoer toont aan dat buildTools afhankelijk is van een bundel/*.txt-bestand. De jquery/jquery.metadata -afhankelijkheid is in twee (2) bestanden en es6-collections is in drie (3) bestanden.

Onze uitvoer toont slechts drie paginatypen (homepage, categorie en product), wat ons het volgende vertelt:

  • Drie gebiedsdelen zijn uniek aan slechts één paginatype (aangetoond door aantal 1).
  • Drie meer gebiedsdelen komen op twee paginatypen voor (die door aantal 2 worden getoond).
  • De laatste drie gebiedsdelen zijn gemeenschappelijk voor alle drie van onze paginatypen (die door aantal 3 worden getoond).

Dit vertelt ons dat wij de pagina-ladingssnelheden van onze opslag waarschijnlijk kunnen verbeteren door onze gebiedsdelen in verschillende bundel te verdelen, zodra wij weten welke paginatypes vereisen welke gebiedsdelen.

​8. Een bestand voor afhankelijkheidsverdeling maken

Als u wilt weten welke paginatypen welke afhankelijkheden nodig hebben, maakt u een nieuw bestand in de Commerce-hoofdmap met de naam deps-map.sh en kopieert u dit bestand in de onderstaande code:

awk 'END {
 for (R in rec) {
   n = split(rec[R], t, "/")
   if (n > 1)
     dup[n] = dup[n] ? dup[n] RS sprintf("\t%-20s -->\t%s", rec[R], R) : \
       sprintf("\t%-20s -->\t%s", rec[R], R)
   }
 for (D in dup) {
   printf "records found in %d files:\n\n", D
   printf "%s\n\n", dup[D]
   }
 }
{
 rec[$0] = rec[$0] ? rec[$0] "/" FILENAME : FILENAME
}' bundle/*.txt

U kunt het manuscript in ​ https://www.unix.com/shell-programming-and-scripting/140390-get-common-lines-multiple-files.html ​ ook vinden

Open een terminal in de hoofdmap van Commerce en voer het bestand uit:

bash deps-map.sh

De uitvoer van dit script, dat wordt toegepast op onze drie voorbeeldpaginatypen, moet er ongeveer als volgt uitzien (maar veel langer):

bundle/product.txt   -->   buildTools,
bundle/category.txt  -->   jquery/jquery.parsequery,
bundle/product.txt   -->   jsbuild,

bundle/category.txt/bundle/homepage.txt -->    jquery/jquery.metadata,
bundle/category.txt/bundle/homepage.txt -->    jquery/validate,
bundle/category.txt/bundle/homepage.txt -->    mage/bootstrap,

bundle/category.txt/bundle/homepage.txt/bundle/product.txt --> jquery,
bundle/category.txt/bundle/homepage.txt/bundle/product.txt --> jquery/ui,
bundle/category.txt/bundle/homepage.txt/bundle/product.txt --> knockoutjs/knockout,

Dit is genoeg informatie om een bundelconfiguratie te bouwen.

​9. Maak pakketten in het bestand build.js

Open het configuratiebestand van build.js en voeg uw bundels toe aan het knooppunt modules . Elke bundel moet de volgende eigenschappen definiëren:

  • name— de naam van de bundel. Met de naam bundles/cart wordt bijvoorbeeld een cart.js bundel in een submap bundles gegenereerd.

  • create— een Booleaanse markering om de bundel te maken (waarden: true of false).

  • include— een array met elementen (tekenreeksen) die zijn opgenomen als afhankelijkheden voor de pagina. RequireJS traceert alle afhankelijkheden en neemt deze op in de bundel, tenzij deze worden uitgesloten.

  • exclude— een array van bundels of elementen die van de bundel moeten worden uitgesloten.

{
    name: 'bundles/catalog',
    create: true,
    include: [
        'addToWishlist',
        'priceBundle',
        'priceUtils',
        'priceOptions',
        'sticky',
        'productSummary',
        'slide'
    ],
    exclude: [
        'requirejs/require',
        'bundles/default',
        'mage/bootstrap'
    ],
}

In dit voorbeeld worden elementen mage/bootstrap en requirejs/require opnieuw gebruikt, waarbij een hogere prioriteit wordt ingesteld op de belangrijkste componenten en componenten die synchroon moeten worden geladen. De aanwezige bundels zijn:

  • requirejs/require - de enige synchroon geladen bundel
  • mage/bootstrap - de laarzentrekkerbundel met UI-componenten
  • bundles/default—standaardbundel vereist voor alle pagina's
  • bundles/cart - een bundel die is vereist voor de basispagina
  • bundles/shipping - gebruikelijke bundel voor winkelwagentje en afhandelingspagina (ervan uitgaande dat uitchecken nooit rechtstreeks wordt geopend, wordt de afhandelingspagina nog sneller geladen als de winkelpagina eerder is geopend en de verzendbundel al is geladen)
  • bundles/checkout - alles voor uitchecken
  • bundles/catalog - alles voor product- en categoriepagina's

Deel 2: Bundels genereren

In de onderstaande stappen wordt het basisproces beschreven voor het genereren van efficiëntere Commerce-bundels. U kunt dit proces op elke gewenste manier automatiseren, maar u moet toch nodejs en r.js gebruiken om daadwerkelijk uw bundels te genereren. En als uw thema's zijn aangepast aan JavaScript en hetzelfde build.js -bestand niet opnieuw kunnen gebruiken, moet u mogelijk verschillende build.js -configuraties per thema maken.

​1. Genereer statische winkelsites

Voordat u bundels genereert, voert u de statische implementatieopdracht uit:

php -f bin/magento setup:static-content:deploy -f -a frontend

Dit bevel produceert statische opslagplaatsingen voor elk thema en elke scène u opstelling hebt. Als u bijvoorbeeld het thema Luma en een aangepast thema met landinstellingen in het Engels en Frans gebruikt, genereert u vier statische implementaties:

  • …luma/nl_NL
  • …luma/fr_FR
  • …custom/nl_NL
  • …custom/fr_FR

Herhaal de onderstaande stappen voor elk winkelthema en elke landinstelling om bundels voor alle winkelthema's en -landinstellingen te genereren.

​2. Verplaats de statische opslaginhoud naar een tijdelijke map

Eerst moet u de statische inhoud verplaatsen van de doelmap naar een tijdelijke map, omdat RequireJS alle inhoud in de doelmap vervangt.

mv pub/static/frontend/Magento/{theme}/{locale} pub/static/frontend/Magento/{theme}/{locale}_tmp

Bijvoorbeeld:

mv pub/static/frontend/Magento/luma/en_US pub/static/frontend/Magento/luma/en_US_tmp

​3. Voer de optimalisatiefunctie voor r.js uit

Voer vervolgens de optimalisatiefunctie voor r.js in het build.js -bestand uit vanuit de hoofdmap van Commerce. Paden naar alle mappen en bestanden zijn relatief ten opzichte van de werkmap.

r.js -o build.js baseUrl=pub/static/frontend/Magento/luma/en_US_tmp dir=pub/static/frontend/Magento/luma/en_US

Deze opdracht genereert bundels in een submap bundles van de doelmap, wat in dit geval resulteert in pub/static/frontend/Magento/luma/en_US/bundles .

De inhoud van de nieuwe bundelmap weergeven kan er als volgt uitzien:

ll pub/static/frontend/Magento/luma/en_US/bundles
total 1900
drwxr-xr-x  2 root root    4096 Mar 28 11:24 ./
drwxr-xr-x 70 root root    4096 Mar 28 11:24 ../
-rw-r--r--  1 root root  116417 Mar 28 11:24 cart.js
-rw-r--r--  1 root root  187090 Mar 28 11:24 catalog.js
-rw-r--r--  1 root root  307619 Mar 28 11:24 checkout.js
-rw-r--r--  1 root root 1240608 Mar 28 11:24 default.js
-rw-r--r--  1 root root   74233 Mar 28 11:24 shipping.js

​4. Configureer RequireJS voor het gebruik van bundels

Als u wilt dat RequireJS de bundels kan gebruiken, voegt u een onModuleBundleComplete callback na het knooppunt modules in het build.js -bestand toe:

[
    {
       //...
       exclude: [
           'requirejs/require',
           'bundles/default',
           'bundles/checkout',
           'bundles/cart',
           'bundles/shipping',
           'mage/bootstrap'
       ],
   },
],
bundlesConfigOutFile: `${config.dir}/requirejs-config.js`,
onModuleBundleComplete: function(data) {
    if (this.bundleConfigAppended) {
        return;
    }
    this.bundleConfigAppended = true;

    // bundlesConfigOutFile requires a simple require.config call in order to modify the configuration
    const bundleConfigPlaceholder = `
(function (require) {
require.config({});
})(require);
    `;

    fs.appendFileSync(this.bundlesConfigOutFile, bundleConfigPlaceholder);
}

​5. Voer de opdracht opnieuw uit

Voer de volgende opdracht uit om te implementeren:

r.js -o app/design/frontend/Magento/luma/build.js baseUrl=pub/static/frontend/Magento/luma/en_US_tmp dir=pub/static/frontend/Magento/luma/en_US

Open requirejs-config.js in de pub/static/frontend/Magento/luma/en_US -map om te controleren of RequireJS het bestand heeft toegevoegd met oproepen tot bundelconfiguratie:

require.config({
    bundles: {
        "bundles/default": ["mage/template", "mage/apply/scripts", "mage/apply/main", "mage/mage", "mage/translate", "mage/loader"],
        "bundles/cart": ["Magento_Ui/js/lib/validation/utils", "Magento_Ui/js/lib/validation/rules", "Magento_Ui/js/lib/validation/validation"]
    }
}
NOTE
Wanneer het vormen van bundels, zorg ervoor u requirejs.config() vraag in de orde plaatst u hen uitgevoerd wilt, aangezien de vraag in de orde wordt uitgevoerd zij verschijnen.

​6. Test de resultaten

Nadat de pagina is geladen, ziet u dat de browser verschillende afhankelijkheden en bundels laadt. Hier volgen bijvoorbeeld de resultaten voor het profiel 'Langzaam 3G':

tweemaal zo snel

De laadtijd van de pagina voor een lege startpagina is nu twee keer zo snel als het gebruik van native Commerce-pakketten. Maar we kunnen nog beter.

​7. De bundels optimaliseren

Zelfs als ze worden gecomprimeerd, zijn de JavaScript-bestanden nog steeds groot. U kunt deze miniaturen maken met RequireJS . Hierbij wordt de miniatuur van JavaScript gebruikt voor goede resultaten.

Als u de optimalisator in uw build.js -bestand wilt inschakelen, voegt u uglify2 toe als waarde voor de eigenschap optimize boven aan het build.js -bestand:

({
    optimize: 'uglify2',
    inlineText: true
})

De resultaten kunnen significant zijn:
drie keer sneller

De laadtijden zijn nu drie keer sneller dan bij native Commerce-pakketten.

recommendation-more-help
c0c5bbed-4957-4162-81bc-120c837a1894