Site icon Blog ARC Optimizer

Divisez le plan de site SXA en plusieurs plans de site si la limite de taille est dépassée


Défi:

L’une des meilleures pratiques en matière de plan de site limite un seul plan de site à 50 Mo (non compressé) ou 50 000 URL. Nous devons diviser le plan du site en plusieurs plans de site si nous avons un fichier plus volumineux ou plusieurs URL. Ensuite, référencez chacun d’eux dans l’index du plan du site. À partir de Sitecore 10.3, le plan du site SXA prend en charge la division du plan du site en plusieurs plans de site s’il dépasse la limite de nombre d’URL donnée. Dans cet article, nous améliorons le plan du site SXA pour prendre en charge la division du plan du site en plusieurs plans de site s’il dépasse également 50 Mo ou la taille donnée.

Solution:

L’amélioration discutée dans cet article est développée avec Sitecore 10.3 Update 1 mais devrait également fonctionner avec Sitecore 10.3.

Les paramètres du plan du site SXA peuvent être trouvés dans /sitecore/content///Settings/Sitemap.

Veuillez lire la documentation de Sitecore. Configurer un plan du site pour garantir que le plan du site fonctionne correctement et pour comprendre le but de chaque champ dans l’élément de configuration du plan du site. Vérifiez si le plan du site fonctionne correctement sur /sitemap.xml.

Par défaut, le champ « Nombre maximum de pages par plan de site (s’il n’est pas défini, toutes les URL seront rendues en une seule) » n’a aucune valeur. Selon la classe « Sitecore.XA.Foundation.SiteMetadata.Settings. SitemapSettingsProvider », la valeur par défaut définie pour ce champ, c’est-à-dire la propriété SitemapIndexThreshold, est int.MaxValue (2147483647), comme indiqué ci-dessous.

SitemapIndexThreshold = MainUtil.GetInt(configurationRoot[Sitecore.XA.Foundation.SiteMetadata.Templates.SitemapSettings.Fields.SitemapIndexThreshold], int.MaxValue),

Conformément aux bonnes pratiques en matière de plan de site, fournissons 50 000 pour limiter le nombre d’URL à 50 000 pour un seul plan de site. Par conséquent, si nous avons un nombre d’URL supérieur à cela, le plan du site sera divisé en plusieurs plans de site et les référencera dans un index de plan de site.

Personnalisons la classe « Sitecore.XA.Foundation.SiteMetadata.Services.SitemapManager » pour diviser le plan du site en plusieurs plans du site si la taille du plan du site dépasse 50 Mo ou la taille donnée. Fondamentalement, la taille de chaque plan du site doit être comprise dans la taille donnée.

Voici le code SitemapManager personnalisé. Veuillez vérifier les commentaires pour plus de détails. Pour le code complet, téléchargez le CustomSXA.Foundation.SiteMetaData.Services.SitemapManager code et ajouter à un projet de couche de fondation approprié. N’hésitez pas à mettre à jour l’espace de noms en fonction de votre projet.

//Existing using namespaces here and below are the new one

using Sitecore;
using Sitecore.XA.Foundation.SiteMetadata.Services;
using System.IO;
using System.Text;
using System.Xml;

//Custom namespace and class. 
namespace CustomSXA.Foundation.SiteMetaData.Services 
{
    public class SitemapManager : ISitemapManager
    {
        //Existing properties here
        
        //New property added for content size limit of Sitemap
        private long SitemapMaxSizeLimit { get; } = StringUtil.ParseSizeString(Sitecore.Configuration.Settings.GetSetting("CustomSXA.Foundation.SiteMetaData.SitemapMaxSizeLimit", "50MB"));

        //Existing methods here

        //customized code for GenerateSitemap
        public SitemapContent GenerateSitemap(SiteContext site)
        {
            Item homeItem = this.GetHomeItem(site);
            Sitecore.XA.Foundation.SiteMetadata.Models.Sitemap.SitemapSettings sitemapSettings = this.SitemapSettingsProvider.GetSitemapSettings(homeItem);
            if (sitemapSettings == null)
                return (SitemapContent)null;
            if (sitemapSettings.CacheType == SitemapStatus.Inactive)
                return (SitemapContent)null;
            IList<Item> items = this.SitemapSettingsProvider.GetItemCrawler(sitemapSettings).GetItems(homeItem);
            int count = items.Count;
            bool flag = sitemapSettings.IncludeXdefault && sitemapSettings.GenerateAlternateLinks;
            if (flag)
                count += items.GroupBy<Item, ID>((Func<Item, ID>)(i => i.ID)).Where<IGrouping<ID, Item>>((Func<IGrouping<ID, Item>, bool>)(i => i.Count<Item>() >= 2)).Count<IGrouping<ID, Item>>();
            SitemapContent sitemap;
            if (sitemapSettings.SitemapIndexThreshold < count)
            {
                List<string> stringList = new List<string>();
                IEnumerable<IGrouping<ID, Item>> groupings = items.GroupBy<Item, ID>((Func<Item, ID>)(i => i.ID));
                List<Item> objList = new List<Item>();
                int num1 = 0;
                foreach (IGrouping<ID, Item> grouping in groupings)
                {
                    int num2 = grouping.Count<Item>() < 2 ? 0 : 1;
                    if (flag)
                        num1 += num2;
                    if (objList.Count + grouping.Count<Item>() + num1 <= sitemapSettings.SitemapIndexThreshold || objList.Empty<Item>())
                    {
                        objList.AddRange((IEnumerable<Item>)grouping);
                    }
                    else
                    {
                        SplitSitemap(sitemapSettings, stringList, objList); //New SplitSitemap function is called instead of old code - stringList.Add(this.RenderSitemap((IList<Item>) objList, sitemapSettings));
                        objList.Clear();
                        if (flag)
                            num1 = num2;
                        objList.AddRange((IEnumerable<Item>)grouping);
                    }
                    if (objList.Count + num1 > sitemapSettings.SitemapIndexThreshold)
                    {
                        SplitSitemap(sitemapSettings, stringList, objList); //New SplitSitemap function is called
                        objList.Clear();
                        num1 = 0;
                    }
                }
                if (objList.Any<Item>())
                {
                    SplitSitemap(sitemapSettings, stringList, objList); //New SplitSitemap function is called
                }
                sitemap = new SitemapContent()
                {
                    Values = stringList
                };
            }
            else
            {
                List<string> stringList = new List<string>();
                SplitSitemap(sitemapSettings, stringList, items); //New SplitSitemap function is called. This is the case where the URL count limit is already satisfied but we check for the content size limit here and split it if neeeded
                sitemap = new SitemapContent()
                {
                    Values = stringList
                };
            }
            this.SetRefreshDate(site);
            return sitemap;
        }

        //Existing code for GetSettings() and RenderSitemap() here. 
        
        //Following are the new functions to split the Sitemap based on the content size limit.

        private void SplitSitemap(SitemapSettings sitemapSettings, List<string> stringList, IList<Item> objList)
        {
            string originalSiteMap = this.RenderSitemap((IList<Item>)objList, sitemapSettings);
            List<string> listOfSiteMap = SplitSitemap(originalSiteMap);
            stringList.AddRange(listOfSiteMap);
        }

        public List<string> SplitSitemap(string originalSitemap)
        {
            //return the same original sitemap back if its size is within the given limit 
            List<string> sitemapSegments = new List<string>();
            if (Encoding.UTF8.GetBytes(originalSitemap).Length <= SitemapMaxSizeLimit)
            {
                sitemapSegments.Add(originalSitemap);
                return sitemapSegments;            
            }

            //If not within the size limit, split it.
            StringBuilder currentSegment = new StringBuilder();
            long currentSize = 0;

            using (StringReader stringReader = new StringReader(originalSitemap))
            using (XmlReader xmlReader = XmlReader.Create(stringReader))
            {
                while (xmlReader.Read())
                {
                    if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "urlset")
                    {
                        if (currentSegment.Length > 0)
                        {
                            // Close the previous <urlset> tag
                            currentSegment.AppendLine("</urlset>");
                            sitemapSegments.Add(currentSegment.ToString());
                            currentSegment.Clear();
                            currentSize = 0;
                        }
                        currentSegment.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>");
                        currentSegment.AppendLine("<urlset xmlns:xhtml=\"http://www.w3.org/1999/xhtml\" xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">");
                        // Update the size with the length of the new elements
                        currentSize += Encoding.UTF8.GetBytes(currentSegment.ToString()).Length;
                    }
                    else if (xmlReader.NodeType == XmlNodeType.Element && xmlReader.Name == "url")
                    {
                        if (currentSegment.Length == 0)
                        {
                            throw new InvalidOperationException("Invalid sitemap structure");
                        }

                        string urlElement = xmlReader.ReadOuterXml();
                        // Calculate the size of the new URL element, including existing elements
                        int urlSizeInBytes = Encoding.UTF8.GetBytes(urlElement).Length;
                        long newSize = currentSize + urlSizeInBytes;

                        if (newSize + "</urlset>".Length > SitemapMaxSizeLimit)
                        {
                            // Close the previous <urlset> tag
                            currentSegment.AppendLine("</urlset>");
                            sitemapSegments.Add(currentSegment.ToString());
                            currentSegment.Clear();
                            currentSize = 0;

                            // Start a new <urlset> tag
                            currentSegment.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>");
                            currentSegment.AppendLine("<urlset xmlns:xhtml=\"http://www.w3.org/1999/xhtml\" xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">");
                            currentSize += Encoding.UTF8.GetBytes(currentSegment.ToString()).Length;
                        }

                        currentSegment.AppendLine(urlElement);
                        currentSize += urlSizeInBytes;
                    }
                }
            }

            if (currentSegment.Length > 0)
            {
                // Close the last <urlset> tag
                currentSegment.AppendLine("</urlset>");
                sitemapSegments.Add(currentSegment.ToString());
            }

            return sitemapSegments;
        }
    }
}

Fournissez la configuration de correctif Sitecore suivante : CustomSXA.Foundation.SiteMetaData.config.

<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <services>
      <register patch:instead="register[@implementationType="Sitecore.XA.Foundation.SiteMetadata.Services.SitemapManager, Sitecore.XA.Foundation.SiteMetadata"]"
        serviceType="Sitecore.XA.Foundation.SiteMetadata.Services.ISitemapManager, Sitecore.XA.Foundation.SiteMetadata" implementationType="CustomSXA.Foundation.SiteMetaData.Services.SitemapManager, CustomSXA.Foundation.SiteMetaData" lifetime="Singleton"/>
    </services>
    <settings>
      <setting name="CustomSXA.Foundation.SiteMetaData.SitemapMaxSizeLimit" value="50MB" />
    </settings>
  </sitecore>
</configuration>

Mettez à jour CustomSXA.Foundation.SiteMetaData.SitemapMaxSizeLimit pour répondre à vos besoins. Utilisez Ko, Mo ou Octets. S’il s’agit d’octets, fournissez uniquement la valeur numérique. Sitecore.StringUtil.ParseSizeString(), utilisé pour traiter ce paramètre, peut également prendre des Go, veuillez donc effectuer la validation nécessaire dans le code si nécessaire. Mettez également à jour l’espace de noms avec le vôtre.

Pensez à installer les packages Nuget à partir de ceci liste. Créez la solution et déployez-la.

Démo

Plan du site SXA par défaut.

Sortie du plan du site SXA par défaut

Avec le code SitemapManager personnalisé. À des fins de démonstration, nous avons défini le « Seuil d’index du plan du site » (limite du nombre d’URL) sur 5 dans l’élément de paramètre Plan du site et avons défini le « CustomSXA.Foundation.SiteMetaData.SitemapMaxSizeLimit » (limite de taille du contenu) sur 1 000, soit 1 000. Octets. Veuillez mettre à jour ces paramètres selon vos besoins.

Le plan du site SXA est divisé en plusieurs plans du site en fonction de la taille et de la limite du nombre d’URL.

Le plan du site SXA est divisé si le nombre d’URL est compris dans le seuil SitemapIndexThreshold donné et si la taille dépasse la limite de taille donnée.

C’est bien de lire la documentation de Sitecore Prioriser une page dans le plan du site du moteur de recherche pour gérer les paramètres du plan du site au niveau des éléments de page.

J’espère que cela t’aides. Bon apprentissage Sitecore !






Source link
Quitter la version mobile