Sitecore 10 Content Serialization and best practices – Part 3

SCS is pretty new, and there are a few basic recommendations while doing the first setup, In this blog, we will discuss those settings and options.

This blog has split into three parts, and this is part 3.

  1. Configure the relative serialization path correctly. In Microsoft NTFS the maximum length is 240. In SCS the content serialization path size limit is defined in the settings, by default, the value is 100.
{
  "$schema": "./.sitecore/schemas/RootConfigurationFile.schema.json",
  "modules": [
    "src/*/*/*.module.json"
  ],
  "serialization": {
    "defaultMaxRelativeItemPathLength": 100,
    "defaultModuleRelativeSerializationPath": "items"
  }
}

The maximum relative item path length = the file system maximum path and file name length – (the base path length + the serialization path length). for more details, please follow this link – Configure the maximum relative item path length

2. Define the hash and alias for relative serialization path – Hashing to shorten paths and aliases and to make it human readable.

It’s super important for two purposes. One is to mitigate the risk of serialization path, and second is define the structure of the project like we can define common aliases for the site.

Relative path is combination of four section (Base path + serialization path +include path content item path) , for example

C:\Users\jsoni\Sitecore\Project\src\Sites\ +  serialization\ + content\ + Home\Products\P1\test.yml

define the alias

"rules": [
  {
    "path": "/Home/Products/P1/test",
    "alias": "alpath"
  }
]

3. Sequence is most important while defining the module.json – As a rule of thumb with Sitecore, all the dependencies should be defined first, for example before defining the content we have to define the templates, layout and rendering etc.

for example

{
  "namespace": "Feature.Hero",
  "items": {
    "includes": [
      {
        "name": "templates",
        "path": "/sitecore/templates/Feature/Hero",
        "allowedPushOperations": "createUpdateAndDelete",
        "scope": "itemAndDescendants"
      },
      {
        "name": "layouts",

        "path": "/sitecore/layout/Renderings/Feature/Hero",
        "allowedPushOperations": "createUpdateAndDelete",
        "scope": "itemAndDescendants"
      }
    ]
  }
}

4. Don’t forget first-match-wins principle while defining the IA or base principle of the content sync strategy – this rule says when a content item matches a rule, all subsequent rules are ignored:

As per the Sitecore recommendation, we need Keep the following things in mind when we configure rules:

  • No path overlapping, If you follow the Helix principles I’m sure it will be much easier, otherwise it can be very hard to identify any path overlaps.
  • Again, Parent rules will override the child rule, example if you have mentioned a rule on parent item node, It will override any child rule configuration.
  • Rule scopes cannot be more inclusive than the root scope. For example, if the root scope is ItemAndChildren, the rule scope cannot be ItemAndDescendants.
  • The alias property in a rule replaces the root name property (the folder name in your file system) for this particular rule.
  • If you have configured an alias property and a scope property with an ignored value, the scope is used. Content items scoped to be ignored are not influenced by aliases.

For more details, please follow below links

I hope this blog will help you to think of a few fundamental considerations while starting to work with SCS on Sitecore.

Sitecore 10 Content Serialization and best practices – Part 2

Unicorn was the most popular plugin for content serialization. It was very straightforward and well managed; all the documents were very descriptive and easy to understand. Now we have Sitecore Content Serialization (SCS), I think we must understand what has changed. Are we losing or gaining any functionality? what changes are required to our existing setup? Re there any changes in terminology etc?

This blog has been split into three parts, and this is part two.

Below is the high-level comparison between Unicorn and SCS.

  1. SCS has an additional Visual Studio plugin to manage Content.

VS plugin provides the below options –

1. Option to push and pull changes
2. Differences between disk and database content
3. Option for selected item sync

SCS has Sitecore command line (CLI) Interface and Unicorn has it’s own page.

SCS configuration is based on JSON files and Unicorn configuration is based on XML.

The configuration file naming convention is different. The SCS configuration file names contain modules for identification and Unicorn configuration contains serialization – Although this is configurable.

The initial setup is different. For SCS we have to setup the package and to enable the CLI it’s required to install the packages.

Difference in global/shared configuration

Difference in project level configuration.

Difference in feature/module level configuration.

SCS provides more flexibility for rule based configuration, for each feature we can define a rule and each rule has the option to define the path, scope and allowed PushOperations etc.

There are changes in the configuration.

When using Unicorn we used to define the dependencies and extends options

<configuration name="Feature.Demo" description="Feature Demo" dependencies="Foundation.*" extends="Helix.Feature">

With SCS, we need to handle it while defining the feature itself and any overlap, for example if there is any specific overlap we need to make sure to put the most specific rule first.

Rule of Parent’s path override rule of children’s and dependent path.

Overall, I can see the SCS configuration is much easier and more flexible. However, I’m still looking for an option for pattern-based formats in SCS.

I hope this comparison will provide a basis to understand the difference between Unicorn and SCS.

Sitecore 10 Content Serialization and best practices – Part 1

Sitecore has introduced Sitecore Content Serialization (SCS) as part of version 10. In this blog, I will explain the basic concept of serialization and compare all Unicorn features, followed by steps for the basic setup and best practices.

This blog has split into three parts, and this is part 1.

Part 1 – Sitecore 10 SCS- Basic concept

Let’s first try to understand the definition, Serialization is the process of translating a data structure or object state into a format that can be stored (for example, in a file or memory data buffer) or transmitted (for example, across a computer network) and reconstructed later (possibly in a different computer environment) – Wikipedia

Sitecore Content Serialization (SCS) is a system for serializing, sharing, and deploying content items, as well as keeping them in version control – Sitecore

Now, we know the definition of serialization. I remember with the Sitecore 6.X Serialization guide we had an option to serialize the item tree and restore it, there were additional options to configure the serialization based on the events like item saved, created, deleted etc. and we were using SVN to store those serialized files.

Growing of TDS (Team Development for Sitecore) foundation

TDS was beneficial to manage the project and item files. I used TDS a lot with Sitecore 6.X versions. We were also using this as part of the deployment process as the underlying TDS was using the MSBuild project file to group the Sitecore items into a deployable project. Additionally to that, it has the below features which are not part of SCS.

  • File deployment into a local Sitecore instance
  • Web Deployment Package (WDP) generation
  • Code generation
  • Validators
  • Environment Validation

Note – Paid license is required for TDS and the cost was around USD 400

In my opinion it’s the end of the TDS era.

Growing of Unicorn (/unicorn.aspx)

Unicorn is a Sitecore utility and it is open source. It solves the issue of moving templates, renderings, and other database items between Sitecore instances. TDS is a monolithic product with commercial support, and marketing does a lot more than just serialization. Unicorn is relatively simple, free and open-source, and does one thing well.

I prefer using Unicorn instead of TDS. Generating the TDS code was not that easy and always needed to take care of the partial class, unnecessary field generation, etc. We can set up the template class following the helix principals.

For more details about the setup, Here is my blog post – Sitecore – Unicorn setup, patterns and tips.

In my opinion Sitecore content serialization would be a replacement of Unicorn.

Sitecore Content Serialization – Future with Sitecore 10 and current focus

SCS will do the out-of-the-box item serialization that lets you automate the synchronization of item changes. It has two options one is using the command-line interface (CLI) and the second Sitecore for Visual Studio (SVS)

Note – for using SVS it’s required to get the license and TDS and SVS are both offered under the same license.

Basic Settings and configurations

Out of the box there are three options to serialize content, The default serialization format (.Item)

  • Manually serialize, update, and revert items in the Content Editor.
  • Use Sitecore event handlers to automatically serialize items.
  • Use the Sitecore service page to serialize, update, and revert a whole database.

Item format

YAML format – using Unicorn and Sitecore content serialization.

This article is the first part to explain the basics of serialization, in the next Part 2- Compare SCS with Unicorn, I will explain the difference between Unicorn vs SCS setup.

I hope this article will help you to understand the basic concept of serialization.

Sitecore Power with ASP.NET Core and why it’s important.

Sitecore has recently introduced a development SDK with ASP.NET Core. In this blog, I will explain why it’s super important for the Business to start thinking about it and how it will change the way of Sitecore development.

In my view, technology is an essential part of running a successful business, and it keeps changing for a better purpose. It’s tough for the Business to make the right decision to choose the right technology and plan for the investment as there are a lot of factors involved like cost, technology choice, stability, future, support, extension, security, machine learning, AI, robotics etc.

Off Couse, every Business would prefer to make a one-time investment and to reuse that investment to cater to any new technology.

Is it possible today to make a one-time investment? I think it’s not, but a company like Microsoft and Sitecore they have been putting all efforts to make it happen and the release of Sitecore with ASP.NET core SDK is a big step towards that dream. In my opinion, The secret of success is to make the right choice at the right time, and don’t devote all energy in fixing the old guys.

Before getting into more details, Let’s understand the key part of the puzzle..

Why Sitecore with ASP.NET Core is so important?

Microsoft has started moving all the focus from the previous development framework (.NET Framework) to .NET Core, Why?, Okay, because .NET Framework 4.8, which was announced on 18th April 2019 will be the last major version of .NET Framework. The visual studio which is the primary IDE for the most of the development is itself is built-in .NET Framework, Although Microsoft will continue to provide the support, as I said in my first few lines, It’s a matter of making the right decision at the right time. below are some key features and needs for the changes.

  • Cross-platform & container support
  • High performance
  • Asynchronous via async/await
  • Unified MVC & Web API frameworks
  • Multiple environments and development mode
  • Dependency Injection
  • WebSockets & SignalR and  Cross-Site Request Forgery (CSRF) Protection
  • “Self hosted” Web Applications
  • Globalization and Localization
  • Swagger OpenAPI built in

SitecoreASP.NET Core rendering SDK enables SItecore headless development with ASP.NET core. This rendering SDK is in addition to the already existing Javascript Service rendering SDKs of React, Angular, Vue and JavaScript libraries. below is the flow diagram and it makes Sitecore solutions faster and easier to develop, maintain, scale, and upgrade by splitting them up into a Sitecore backend and a ASP.NET rendering host frontend. And we can build rendering hosts with the Sitecore ASP.NET Rendering SDK. That’s a fantastic option. here is a high level flow diagram.

Microsoft has already planned roadmap until 2023 releases, so this shows how important it’s that Sitecore goes with the .Net Core platform.

Source – https://dotnet.microsoft.com/platform/support/policy/dotnet-core

The most important part is, there are a lot of front end technology like Angular, React, Vue.jS, Flutter, Microsoft has launched the new platform called Blazor which will allow C# developer (Sitecore technology) stack to write the web interactive UI through the same language, WOW that’s really amazing, Microsoft has already unified the infrastructure with Azure Cloud provider, development technology with .Net Standard and front end technology through Blazor, so now to develop any complex code that includes Azure, backed like Machine learning , AU and front end all can be done through the same technology and Sitecore has release official SDK for that, so that’s the reason is very important for the business as well as for the development.

Let’s talk about the development and architecture

There are two main parts, One is rendering host front end and second is Sitecore instance backend.

  • Rendering Host – The rendering host front end is a web app made up of the Sitecore ASP.NET Rendering SDK code and static resources. The job of the rendering host is to respond to visitor requests.
  • The Sitecore instance– exposes a set of endpoints like web based native rendering hosts or third party integration
Source – https://doc.sitecore.com/developers/100/developer-tools/en/sitecore-headless-development.html

1. Setting up the sample project-

Below are the prerequisites for the installation.

Follow these steps in case of any error, Please see the reference in Troubleshooting section in the below page.

Below are simple command to setup the local environment.

dotnet new -i Sitecore.DevEx.Templates --nuget-source https://sitecore.myget.org/F/sc-packages/api/v3/index.json (Install template)

dotnet new sitecore.aspnet.gettingstarted -n MyProject (Create a new project)

.\init.ps1 -InitEnv -LicenseXmlPath "<path to your license.xml file>" -AdminPassword "<your Sitecore administrator password>“  (Prepare the container)

.\up.ps1 – (Download the Sitecore Docker images and install the containers)
Docker-compose up –d and Docker ps -a

Once you follow above steps, You should be able to see the working Sitecore instance running inside docker with ASP.NET core.

2. Below are the steps to setup the JSON rendering.

Setup the template in the project and add the standard value, As example below, Ref – https://doc.sitecore.com/developers/100/developer-tools/en/walkthrough–creating-a-simple-rendering-with-a-data-source.html

Add JSON rendering and placeholder settings As mention below.

Add a new component in the solution, A new model, View and register it.

Verify Traefik

  1. Reverse proxy
  2. Traefik provides the friendly URL for each of the instances.
  3. Low configuration setup.
  4. SSL termination

Benefit of using ASP.NET core with Sitecore.

  • Super fast.
  • Fully integrated with Visual Studio.
  • Sitecore headless development is based on ASP.NET Core, there are also fewer problems when doing the native integration

Below features are not supported.

  • Horizon
  • Edit frames
  • Sitecore Forms
  • Invocation of xConnect events, goals and outcomes from c#
  • Managed Cloud Standard and Managed Cloud Premium do not currently offer headless topologies for rendering hosts.

Helper

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass

Troubleshooting

  • First issue while the setup was ‘Invoke-WebRequest’ is not recognized as an internal or external command

Root cause analysis and Solution.

Need to update the default shell to PowerShell for dotnetsdk –

C:\Projects\RenderingSDK\MyProject\docker\build\dotnetsdk\Dockerfile

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
  • C:\Program Files\dotnet\sdk\5.0.100\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(241,5): error NETSDK1005: Assets file ‘C:\build\src\rendering\obj\project.assets.json’ doesn’t have a target for ‘netcoreapp3.1’. Ensure that restore has run and that you have included ‘netcoreapp3.1’ in the TargetFrameworks for your project. [C:\build\src\rendering\renderinghost.csproj]

Initially, I thought it’s related to version, As I had installed both dotnetcore SDK 3.1 and 5.0, but finally had to update above command.

Extension – In case if need any extension like xConnect events and to trigger a goals, there are always a way, We can Instantiate client in a non-Sitecore context, Reference Link and can add interaction like to trigger a goal

Finally, A few development tips.

  • How to check the files running inside the containers through the VIsual Studio.
  • Dotnet Sitecore Help command
 dotnet sitecore --help
  • Sitecore login command
  dotnet sitecore login 
  • Push the serialized items command – SCS (Sitecore content serialization)
 dotnet sitecore ser push 
  • SCS (Sitecore content serialization) Publish command
 dotnet sitecore publish

Git link for the ASP.NET core Helix

https://github.com/Sitecore/Helix.Examples/tree/master/examples/helix-basic-aspnetcore

I hope this will help to start the development with ASP.NET core with Sitecore 10

Video reference –

I have also presented in Sitecore User Group Pune – Nov 2020 and explain these details.

Page Speed – The Smaller 7th Pillar – Micro Boosts

You may have read my previous blog post: One Performance Blog to Rule them all – Combining the 6 Pillars of Speed

This is just a quick update to list out some further optimisations that might help you achieve a few extra points.


Prolong the Cache Expiry Setting

The default cache expiry settings is 7 days OOTB in Sitecore. This is a little short for the likes of GTMetrix but may be passable for Lighthouse. I found it best to bump it up to 30 days (if you can).

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
  <sitecore>
      <settings>
	  <setting name="MediaResponse.MaxAge" set:value="30.00:00:00"/>
      </settings>
  </sitecore>
</configuration>

Web.config and applicationHosts.config changes

These three changes are from a blog written by Sergio Gisbert

1) Add the ‘Accept-Encoding’ header to responses:

<httpProtocol>
    <customHeaders>
        <remove name="Vary"/>
        <add name="Vary" value="Accept-Encoding"/>
    </customHeaders>
</httpProtocol>

2) Enable Dynamic compression on IIS (this should already be done if you followed the Sitecore setup document) and then add in specific mime types that need coverage to web.config.

<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
    <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll" />
    <dynamicTypes>
        <add mimeType="text/*" enabled="true" />
        <add mimeType="message/*" enabled="true" />
        <add mimeType="application/javascript" enabled="true" />
        <add mimeType="application/x-javascript" enabled="true" />
        <add mimeType="application/json" enabled="true" />
        <add mimeType="image/jpeg" enabled="true" />
        <add mimeType="image/jpg" enabled="true" />
        <add mimeType="image/gif" enabled="true" />
        <add mimeType="image/png" enabled="true" />
        <add mimeType="application/vnd.ms-fontobject" enabled="true" />
        <add mimeType="application/x-font-truetype" enabled="true" />
        <add mimeType="image/svg+xml" enabled="true" />
        <add mimeType="*/*" enabled="false" />
    </dynamicTypes>
    <staticTypes>
        <add mimeType="text/*" enabled="true" />
        <add mimeType="message/*" enabled="true" />
        <add mimeType="application/javascript" enabled="true" />
        <add mimeType="application/x-javascript" enabled="true" />
        <add mimeType="image/jpeg" enabled="true" />
        <add mimeType="image/jpg" enabled="true" />
        <add mimeType="image/gif" enabled="true" />
        <add mimeType="image/png" enabled="true" />
        <add mimeType="application/vnd.ms-fontobject" enabled="true" />
        <add mimeType="application/x-font-truetype" enabled="true" />
        <add mimeType="image/svg+xml" enabled="true" />
        <add mimeType="application/json" enabled="true" />
        <add mimeType="application/x-woff" enabled="true" />
        <add mimeType="*/*" enabled="false" />
    </staticTypes>
</httpCompression>

3) Update applicationHosts.config to compress SVG and JSON payloads. As Sergio mentions in his blog this has to done in applicationHosts.config. (great find Sergio)

<add mimeType="image/svg+xml" enabled="true" />
<add mimeType="application/json" enabled="true" />

GZIP your main HTML document

Google Page Speed insights calls this criteria “Text Compression” but this does actually make a download size difference if your HTML payload is large. After doing this I witnessed my initial HTML delivery drop from 130KB to 40KB.

Inside your web.config and the <httpCompression> tags we added just previously add the mimeType for document into both staticTypes and dynamicTypes.

<add mimeType="document" enabled="true" />

Cleanup all missing fonts and 404s

Be sure to check you network tab and make sure any missing font references or external resources are not throwing 404s. This will result in a score reduction particularly on GTMetrics.

JSS and OKTA: Blog 2 – Login via embedded OKTA Form

This blog post is based on the OKTA samples @ https://developer.okta.com/quickstart-fragments/angular/default-example/ and the OKTA sign in widget that can be integrated into the page.

The branch mentioned above contains a working example that I will now run through in the rest of this blog. Once up and running your should get a login embedded into our JSS application that allows us to login via OKTA.


Overview

Firstly lets have a quick run through of the changes we made to the first blog in order to integrate the widget.

  1. OKTA configuration settings
    • These are stored in a settings file in the root of the JSS application: jss-okta-config.json
    • All settings to do with our OKTA instance can be added in here.
  2. Create the placeholder component to contain the widget
    • In JSS we scaffold up a new component
    • src\app\components\okta-sign-in\okta-sign-in.component.ts
    • Have a look at https://github.com/TomTyack/jssokta/blob/feature/okta-sign-in-widget/JSS/src/app/components/okta-sign-in/okta-sign-in.component.ts
      1. ngOnInit()
        1. Note how the code dynamically imports the OKTA sign in widget.
        • import('@okta/okta-signin-widget')
        • This is necessary as the library contains a reference to window. Which will break our Server Side code if imported normaly.
        • So in order to workaround this flaw we dynamically import the library only after verifying that this code is running client side.
      2. detectTranslationLoading()
        • Wait for the dictionary service to be loaded so that we can inject the Dictionary into the form.
      3. bootupSignin()
        • Initialise the OKTA widget configuration, inject labels and URLS
      4. injectWidgetPhase()
        • Render the widget
    • This contains the widget code and the has a matching from end HTML template in Angular.
      • The HTML file contains the following important tag
      •  <div id=”okta-signin-container”></div>
  3. Add the component to the /login route
  4. Adjust the navigation to include a new button for the widget
  5. Dictionary additions

Demo Video

To show you a video of this JSS example in action take a quick gander at the following video:


Demo Installation

  1. Clone the Repository
  2. Deploy the application. Follow the same instructions from the first blog. <<< UPDATE LINK
  3. Run the application. Follow the same instructions from the first blog. <<< UPDATE LINK
  1. Click on the “Login Embedded” link in the navigation
  2. Login to OKTA (if not already) using the details you registered with.
  3. You should arrive back on the profile page
  4. undefined
  5. Success!! hopefully 🙂
  6. Inside the OKTA Dashboard is a handy log that shows all login activity. This is a great way to see what is going on. Screenshot shown at the bottom.
    • undefined

Summary

That concludes the run through of how to integrate the OKTA Angular SDK and Embedded Widget into Sitecore JSS. OKTA is a leader in user authentication management and having the ability to integrate into our JSS applications is an exciting prospect. I hope this example is of use to you and your teams if your considering the same technology mix.


JSS and OKTA: Blog 1 – Login via External OKTA Form

This blog post is based on the OKTA samples @ https://developer.okta.com/quickstart-fragments/angular/default-example/

The OKTA samples makes use of the OKTA Angular SDK and allows you to set up a development OKTA cloud instance for testing the code.

For this blog I have integrated the OKTA example into the Angular JSS starter repository to for a new repository to accompany this blog. https://github.com/TomTyack/jssokta

This repository contains a working example that I will now run through in the rest of this blog. All you need to do is sign up for your own developer sandbox (OKTA) instance using a dummy user and test it out.


Overview

Firstly lets have a quick run through of the changes we made to the original examples in order to integrate them with the angular JSS application.

  1. OKTA configuration settings
  2. Provide the Login and Logout Buttons
  3. Create the Callback Handler
    • The callback handles integration in JSS takes place inside: src\app\routing\routing.module.ts
    • JSS Example: https://github.com/TomTyack/jssokta/blob/master/JSS/src/app/routing/routing.module.ts
    • In this case I made the route: /implicitcallback
    • Importantly the route must be added at the top of the list so that JSS routing doesn’t hijack the route before our OKTA module gets a chance. I spent a little while scratching my head over this one when I originally added it the bottom of the route config.
  4. Update your NgModule
    • This requires a little bit of adjustment from the original example.
    • Module integration is done via: src\app\app.module.ts
  5. Use the Access Token

Demo Video

To show you a video of this JSS example in action take a quick gander at the following video:

Note: In the video I started off the demo by running in Disconnected mode with localhost. Surprisingly this worked and it redirected back to the connected app domain. In reality a better test would have been to start on the same domain in integrated mode. I’m not sure that you could run this test end to end in disconnected.

Demo Installation

  1. Clone the Repository
  2. Sign up for an OKTA developer account
    • https://developer.okta.com/signup/
    • When it asks you what sort of application you want just click “Do this later”.
    • Confirm your email address and fill out the security questions and change your temporary password.
  3. In the top navigation withing the OKTA Dashboard
  4. Back in the JSS OKTA Repository (open it in VS Code or your editor of choice)
    • From the command line run: npm install
    • Open the file: jss-okta-config.json (in the root of the JSS Application)
      • issuer: Swtich out “INSERT-OKTA-ID” with the relevant ID from the same domain your viewing the OKTA portal in.
      • redirectUri: Replace ‘jssokta’ with ‘jss.okta.portal’ or whichever domain you set.
      • clientId: Found on the application > General tab. About 20 characters long.
  5. IIS
    • OKTA requires us to be running a domain with https, as such it makes it difficult to test this out in Disconnected mode.
    • Setup a Sitecore instance and make sure JSS is installed.
    • Add your new domain to the local hosts file and make sure its mapped to 127.0.0.1
    • Add the new domain to your Sitecore instance in IIS and make sure it capable of HTTPS. Use the developer certificate as a default.
  6. Back in the JSS OKTA Repository
    • Got to sitecore\config\JSSOkta.config
      • hostName: jss.okta.portal
    • From the command line run: JSS Deploy app
      • run through the setup as you would any JSS application so that it would connect with your Sitecore instance.
      • Sample config from my tests: See scjssconfig.json at the bottom of this blog
    • From the command line run: JSS Deploy config
    • From the command line run (again): JSS Deploy app -c -d
  7. Test out the deployed application:
    • Navigate to your domain: example: https://jss.okta.portal/ (must have SSL)
    • If prompted about the SSL security warning proceed and ignore. “Proceed to jss.okta.portal (unsafe)”
    • undefined
    • Click on the “Login” link in the navigation
    • Login to OKTA (if not already) using the details you registered with.
    • You should arrive back on the profile page
    • undefined
    • Success!! hopefully 🙂
    • Inside the OKTA Dashboard is a handy log that shows all login activity. This is a great way to see what is going on. Screenshot shown at the bottom.
      • undefined

Summary

That concludes the run through of how to integrating the OKTA Angular SDK in Sitecore JSS. OKTA is a leader in user authentication management and having the ability to integrate into our JSS applications is an exciting prospect. I hope this example is of use to you and your teams if your considering the same technology mix.


OKTA Setup Screenshots and Sample Config

I have included screenshots of all my OKTA settings below. As I know this can be difficult to diagnose at times.


scjssconfig.json

{
  "sitecore": {
    "instancePath": "C:\\inetpub\\wwwroot\\test.dev.local",
    "apiKey": "{FB95B118-E04F-4D5B-9465-01AE804A2F5A}",
    "deploySecret": "r6bnvuhv13beudhix1lxnej2ci38u0i6kxhnpy22i6ps",
    "deployUrl": "http://jss.okta.portal/sitecore/api/jss/import",
    "layoutServiceHost": "https://jss.okta.portal"
  }
}

Introduce YML Linting to your JSS Apps

Intro: This post shares how and why you might like to introduce a YML linter into the build process for your next Sitecore JSS project. Particularly if you are relying on the YML import process when building a new application. Shout out to David Huby (Solutions Architect) for introducing team Aceik to yaml-lint.

Why would you want to do this on a JSS project?

When running the JSS application and testing latest changes, we sometimes discovered some strange behaviour with dictionary items, or a page might not load properly.

A 404 page displayed after an invalid YML change was made

This can be caused by a small (incorrect) change in YML breaking individual routes. For example, lets say you have an incorrect tab or character in the wrong place. The YML syntax requires correct spacing and line returns to be valid but this is not always so obvious when done incorrectly. Sometimes only after you run the JSS application and test out the changes do you discover some strange behaviours or the page not loading properly.

To avoid this we found it handy to introduce a YML linter into the JSS build process. This solves the issue of someone making a small change to the YML files and breaking individual routes.

Here are the steps needed to introduce a YML linter into a node-based JSS project:

  1. Install yaml-lint (https://www.npmjs.com/package/yaml-lint)
  2. In the application root create the file .yaml-lint.json
  3. Update the package.json
    • Create a new script entry called yamllint
      • “yamllint”: “node ./scripts/yaml-lint.js”
    • Update the script called ‘build’
      • “build”: “npm-run-all yamllint –serial bootstrap:connected build:client build:server”,
  4. Download the following scripts file and place it in the /scripts folder
    1. https://github.com/TomTyack/jss/blob/feature/YAML-Linter/samples/react/scripts/yaml-lint.js

You can also see the pull request with the above changes at:

https://github.com/Sitecore/jss/pull/385/files

Demo

One Performance Blog to Rule them all – Combining the 6 Pillars of Speed

I have done a number of posts and talks at user groups on Page Speed and performance over the last few years. I have split the various topics into individual blog posts for the most part as performance is dependent on many factors. What has really been missing is a complete demo of how all the different techniques come together to give your site a really good score. So that’s what I intend to demo here is the combination of the 6 pillars of page speed in one Sitecore instance. To recap here are the 6 pillars of page speed performance in my opinion:

1) Introduce image lazy loading

2) Ensure a cache strategy is in place and verify its working. (must have adequately sized production servers)

3) Deploy image compression techniques

4) Use responsive images (must serve up smaller images sizes for mobile)

5) Introduce Critical CSS and deferred CSS files

6) Javascript is not a page speed friend. Defer Defer Defer

I have shown a subset of these previously but crucially three critical pillars to do with imaging were hard to achieve at the time. This is now possible due to being able to support Next Gen image compression (webp), which I wrote about in my previous blog. With a little more time and investigation Image Lazy Loading, responsiveness and image compression to give a more complete picture of how each pillar impacts page speed.

Here are the tools and blogs I will use to achieve each of these:

1) Image Lazy Loading – Blog post by MVP Sitecore SAM and https://github.com/thinker3197/progressively

2) SXA Cache Settings – SXA official documentation

3) Next Image (WEBP) Image Compression – https://github.com/Aceik/ImageCompression

4) SXA Responsive Images – SXA official documentation

5) Introduce Critical CSS and deferred CSS files – https://github.com/Aceik/Sitecore-Speedy

6) Javascript is not a page speed friend. Defer Defer Defer – https://github.com/Aceik/Sitecore-Speedy

Alternatives: Mark Gibbons (MVP) recently upgraded the Dianoga image library to support WEBP. Worth a look if you don’t want to use a third party API. It also supports a CDN. Also Vincent Lui (MVP) also pointed out in his recent SUGCON talk, you can achieve both image compression and image lazy loading via some of the modern CDN’s. That is a great (easy) option if you are retro fitting these techniques to a live website.

I’m not going to dive deep into exactly how to setup each of these things as I think the individual links have sufficient instructions. I will show in the Demo videos how each pillar impacts the HTML rendered. For the most part I am keen to demonstrate the impact of each of these line items and how each one will benefit your page speed score.

Before we begin its important to understand that the algorithm (Lighthouse) behind Google’s Page Speed insight doesn’t work in an exactly linear fashion. If you improve your score by ticking off one of the above, don’t expect ticking off another issue will have the same benefit. The last 20 points out of 100 (on the mobile scoring system) is that hardest to achieve based on what I have seen.

Live Demo Video Series that accompanies this blog:


Test Outline:

Google Page Speed Insights — Scores can fluctuate widely based on network latency. At time you will experience score fluctuations at different times of the day on the same site.

In general this is a guide

Here is the general outline of the VM that hosted the IIS instance for testing. I also put the VM under some basic load while running the tests.

  • All the test below used Sitecore 9.3 and the SXA habitat example site.
  • Test used the live Google Page Speed insights tool via the url: https://developers.google.com/speed/pagespeed/insights/
  • Sitecore was setup on an Azure VM with the specifications:undefined
  • The test was run 5 times, to get an average score.
  • The test page was the homepage of the Habitat site and the page was requested before running the test 5 times so that the instance could be considered warm.
  • EXM and XDB were not running on these test instances.
  • Test results are Mobile Page Speed scores only – This is the most important metric in today environment and good desktop scores are not really a challenge.
  • The default Habitat cache rendering for Navigation was left on for all tests. (without this the site fails under basic load altogether)
  • All tests were conducted under load in an attempt to replicate a production environment. For this I used a node package called loadtest.
  • SXA CSS/Javascript optimisations were turned on, but as I have mentioned before this has a minimal performance boost.

loadtest -c 10 –rps 10 http://baselinecd.dev.local/

10 requests per second with a concurrency of 10

Baseline Score

The Baseline score encompasses the habitat site installed with no modifications.

Result: 48 / 38 / 40 / 34 / 38 = 39.6/100 Average

Observation: Heavily penalised for CSS and Javscript loading times.


Image Lazy Loading

All images on the homepage were converted to be Lazily loaded. A single large blurred image was used as the placeholder for all images.

Result: 57 / 55 / 61 / 52 / 63 = 57.6/100 Average

Observation: Around the mid point of the scale, image lazy loading has around a 15 – 20 point impact.


Rendering Cache Strategy

I have blogged extensively about this in the past but setting up cache settings properly is so critical and has a major impact. Its also one of the easiest things to fix for a poorly performing Sitecore site. Also note the only way to accurately demonstrate the impact that Rendering cache has on a site is to test it under load.

This test was run with higher user per second: loadtest -c 10 –rps 30 http://baselinecd.dev.local/

With Cache Enabled:

49 / 56 / 41 / 54 / 54 = 50.8

Without Cache Enabled:

ERR_TIMED_OUT / ERR_TIMED_OUT / ERR_TIMED_OUT / ERR_TIMED_OUT / ERR_TIMED_OUT = You get the point 🙂

Observation: Rendering cache settings are critical and should be the first step in Page Load Speed refinement for a Sitecore site. 10 Point benefit observed once a site is stable under load.


Image Compression

Result: 60 / 58 / 61 / 62 / 62 = 60.6/100 Average

Observation: Around the mid point of the scale, image lazy loading has around a 20 point impact.


Critical CSS

Result: 74 / 78 / 79 / 81 / 81 = 78.6/100 Average

Observation: The combination of critical CSS in the head and Deferred styles provides a meaningful page speed boost. 25 Point observed benefit.


Deferred Javascript

Result: 92 / 94 / 93 / 94 / 94 = 93.4/100 Average

Observation: Javascript has a massive impact, reducing it drastically in the initial payload provides massive page speed improvements. 40 Point observed benefit.

You might think, hey I will just do Deferred Javascript and it will be all good. While this particular PIllar/Criteria does have the biggest impact. Every site is different and as mentioned earlier scores fluctuate. The upper part of the scoring system is the hardest to reach. So while this is a great starting point, ignore the other speed pillars at your peril.


Responsive Images

Result: 56 / 54 / 59 / 56 / 60 = 57/100 Average

Observation: Around the mid point of the scale converting images to be responsive (srcset support) has about a 10 point impact.


Results Summary

CriteriaAverage ScoreObserved Benefit
No Change (SXA Habitat Home OOTB)41.8 / 100
Image Lazy Loading57.6 / 10015 Points
Sitecore Rendering/HTML Cache Settings50.8 / 10010 Points
Image Compression (webp)60.6 / 10020 Points
Critical CSS78.6 / 10025 Points
Deferred Javascript93.4 / 10040 Points
Responsive Images57 / 10010 Points

The Pillars Combined

In isolation we can see the rough results of what each of the pillars might do to our Page Speed. The real question is what does combining all these pillars produce.

Result: 100 / 100 / 100 / 100 / 100 = 100/100 Average

Observation: Do I expect this on an actual production site realistically ? That is certainly the dream, but in reality you should be over the moon if you make it into the 90s and pat your self on the back if you get into the 80s as well. For any Sitecore site if you make it into the 90’s for mobile, your doing an amazing job.

Admittedly for the combined demo I skipped the responsive image pillar. SXA supports Responsive Images but not in combination with data attributes. It was going to be a bunch of work to write a custom SXA handler to support both lazy loading and responsiveness at the same time. That is not to say its not possible. Either way the impact was minimal.

Conclusion

Page speed is so critical to SEO and visitor conversion. A slow site instantly turns away users on mobile and tablet devices. Admittedly the final result shown above and in the video have required that all the right tools be available to the Sitecore community. Which up until recently you likely needed to bake your own solutions in order to get that over the line.

I think its now becoming possible to aim fairly high (90/100 on mobile) with our Page Speed scores, but it does require getting most if not all of the Architecture Pillars above working together. Its worth learning each of these and understanding the pitfalls and limitations if you want really great page speed. Good luck and feel free to get in touch with any questions.

Footnote

The combined pillars can produce great results but you still need to load test before going live. Checkout the video below where I search for the breaking point using the loadtest tool. Please note that this node based load test tool should just be used for a guide. Before go live I recommend using a hosted load tool solution that has multiple geographic locations. Tests done based on one network location or device will result in a network bottle neck and give you false positives.

Bonus Video: https://www.youtube.com/watch?v=96YcxyhYh0U

Next Gen Image Compression in Sitecore

Spoiler: This post is not a post about Dianoga, I take a deep dive into Tiny PNG and Kraken.IO integrations into Sitecore. The results are worth checking out at the bottom.


At the start of the year, I’ve picked up where I left off, on page speed. Last year I took a deep dive into attempting to improve the page speed on Sitecore SXA sites by using some of Google’s recommended techniques to structure the page. If you haven’t already seen it, head on over the Sitecore Speedy and see some of the results we achieved.

I’ll be the first to admit that getting really good page speed scores isn’t easy. It takes a lot of different factors to come together. Just as a reminder, here is the main list that I would consider you need to check off to be winning at this game.

1) Introduce image lazy loading

2) Ensure a cache strategy is in place and verify its working.

3) Dianoga is your friend for image compression

4) Use responsive images (must serve up smaller images sizes for mobile)

5) Introduce Critical CSS and deferred CSS files

6) Javascript is not a page speed friend. Defer Defer Defer

For this post, i’m going to look at an alternative to Dianoga. I’m a big fan of Dianoga and have used it over the years to crunch loads of oversized images introduced by Content Editors. I will, however, say that it can add complexity to deployments and CI/CD pipelines and while some claim to have had success in Azure Apps, others have not.

On the flip side, content editors love Tiny PNG, which is one of the most popular image compression website utilities going around. Tiny PNG also has a developer API, so we have used this to build in a compression tool that can be used directly from your Sitecore toolbar.

The button below is hooked up to chat to Tiny PNG API. It will send across your image data and receive a compressed image back for storage.


Full disclosure, I’m not the first person to hook up Tiny PNG to the image library. I could find two other implementations

One will allow you to run a powershell script to connect to the Tiny PNG API and the other is a module to connect to the API on upload.


This implementation of the Tiny PNG API introduces the following variances:

  • A button in the CMS to crunch any single image.
  • A scheduled task that will process any image not already processed.
  • Error handling for when the API limits are reached
  • Logging that outlines which images were processed.
  • Before and After compression information stored in any Image field of choice.
  • A feature toggle to turn the whole feature on/off

All the source code is available at: https://github.com/Aceik/ImageCompression

Now let’s jump in have a look at the results just from crunching a few images down:

Without image compression:

Click to Enlarge Image

To compress the images on the page, we head on over to the “Compress” button in the Media tab that we have introduced.

Click to enlarge

A few examples of compression results taken from homepage images:

Before: 158.4 KB | After: 110.6 KB

Before: 197.8 KB | After: 135.3 KB

Before: 640.0 KB | After: 120.7 KB

After compressing all the images on the page the saving can be seen below.

Click to enlarge

So our total image size saving is 2.4MB – 1.3MB = 1.1MB

A pretty decent saving from just pressing the compress button on 27 homepage images. Also, consider that the user won’t notice any difference in image quality as this method uses lossless compression.


The compression achieved is great for helping us tick off one of the requirements for fast pages with Google. But as we are about to find out Google will likely still complain about two other criteria. When it comes to Google Page Speed insights a page that does not have properly processed images will bring up the following three recommendations:

Here is a break down of how we address each one:

  1. Serve image in next-gen formats – Image formats like JPEG 2000, JPEG XR, and WebP often provide better compression than PNG or JPEG, which means faster downloads and less data consumption. Learn more.
  2. Properly Size images – Your CSS layouts should be responsive and use modern image retrieval techniques that adapt the image size requested based on screen size. Read More
  3. Efficiently encode images – The Tiny PNG integration above will take care of this. This is all about compressing the image to as small as it can get without a visible loss of quality.

So assuming you have already achieved number three using the Tiny PNG integration or another source, let us look at how we can solve the next-gen image requirement.

As a quick side note the testing I did after converting the images to next-gen also ticked item number two above. I don't think this should be relied on however and its best to incorporate responsive images into your projects from the beginning.  

When looking into how to convert images to a next-gen format I opted to target webp. Google has a nice little page explaining the format here.

WebP is natively supported in Google Chrome, Firefox, Edge, the Opera browser, and by many other tools and software libraries.

Once again I opted to look for an API that would provide the conversion for me so that Sitecore could easily connect, send the image and then store the result. All without any extra hosting requirements. I opted to go with Kraken.IO image APIs as they have a free 100MB trial offer and well free is a good price when building proof of concepts. The integration is all available on Aceik’s github repository. Just signup for your own API keys add them to the module settings (in the CMS) and start converting.

To test out just how much this would impact the image payload size for the whole page, I once again converted all the images on the SXA habitat homepage.

Here are the results:

Click to enlarge

So our total image size saving is now 2.4MB – 0.79MB = 1.61MB

The reduction in size from a non-compressed image to a webp formatted image is truly impressive.

A few examples:


Conclusion

I can only conclude by saying that if page speed is really an important factor for your Sitecore project take a look at Tiny PNG. If you want to go next level with your image formats and achieve great compression try out the Kraken.IO API integration as it could be well worth the small subscription fee.


Results

CompressionTotal Image SizeSaving
None2.4 MB
Tiny PNG1.3 MB1.1MB
Kraken.IO (webp)0.79MB1.61MB

Notes:

The module and code mentioned in this blog post are available on Aceik’s Github account. This also contains installations instructions.

GitHub: https://github.com/Aceik/ImageCompression

After installation, your content editors will simply be able to compress and convert images as needed from within the CMS.

Click to enlarge

The Github Readme contains a run down and the standard settings inside Sitecore as shown below: