Optimize SPFx Image render with Private CDN

Office 365 CDN

Office 365 CDN (content delivery network) played a vital role in reducing the network traffic and fastest rendering of the content. It comprises the Private origins CDN and Public origins CDN.

As images are now automatically managed in a SharePoint Online service-managed Private CDN, the manually configured Private CDN is being deprecated. This means that customers no longer need to configure. Reference article here.

Problem Statement

Custom Control (SPFx) added to the page, which renders or displays multiple images. It adds multiple network calls and causes performance issues.

Way to achieve the solution

Let's begin to enablement of Private CDN to optimize and reduce the network traffic and configure the codebase accordingly.

Step 1. To validate the Private CDN

  1. Get-SPOTenantCdnEnabled -CdnType Private: return True or False (false means not enabled)
  2. Get-SPOTenantCdnOrigins -CdnType Private: return the path of the origin (blank means not configured and doesn't exist)
  3. Get-SPOTenantCdnPolicies -CdnType Private: return the defined or configured policies.
    Optimize SPFx Image render with Private CDN

Step 2. Configure the Private CDN

  1. Set-SPOTenantCdnEnabled -CdnType Private
  2. Press A to confirm the CDN enablement at the Tenant Level
  3. Private CDN-enabled locations start appearing 
  4. Validate Private CDN enablement with Get-SPOTenantCdnEnabled -CdnType Private (True means private CDN enabled)
    Optimize SPFx Image render with Private CDN

Step 3. Create a List with an Image DataType

SharePoint Online List structure with the below columns

Column Name Data Type
Title (OOTB) Single Line of Text
Footer Url Hyperlink
IsActive Boolean
Oder  Number
Footer Image Image 

Optimize SPFx Image render with Private CDN

Step 4. List Image Storage

All List images under the image column get stored in Site Assets automatically. Once you navigate to Site Assets, Sub Folder will get created with the name Lists and a further subfolder with List ID with all images. 

Note. As Private CDN is enabled or enabled automatically, Site Assets origin is set CDN enabled library or folder.

Site Assets

Step 5. Get List Items into the TSX file

Create a state variable type array i.e. footeritems, and bind the list data within the array using setState.

  public constructor(props: IFooterProps) {
    super(props);
    this.state = {
      footerItems: [],
      isLoading: true,
    };  }

   async componentDidMount() : Promise<void>  { 
    this.sphelper = new SPOHelper(this.props.ctx);
    await this.getAllListItemsUsingSelectFilterOrderBy();   
  }

  public async getAllListItemsUsingSelectFilterOrderBy(): Promise<any[]> {
    let items: any[] = [];
    try {
        let listItems = await this.sphelper.getAllListItemsUsingSelectFilterOrderBy("footeritem", "Title,FooterUrl,FooterIcon,FooterImage,IsActive,Order", "Order", true, "IsActive eq 1");
        console.log(listItems);
        this.setState({ footerItems: listItems,isLoading: false });
    } catch (error)     }
    return items;  }

Step 6. To Convert the source Image Url to CDN, enable the URL using ImageHelper

import { ImageHelper } from "@microsoft/sp-image-helper";

Create a function that takes the source Url and returns the CDN-Enabled Url.

ImageCdnUrl(originalImageUrl : string)
{
    return ImageHelper.convertToImageUrl(
    {
        sourceUrl: originalImageUrl, // important
        width: 80  // up to requirement, size can be set
    } 
    ); 
}

Finally, Render Method.

public render(): React.ReactElement<IFooterProps> {
  return (<>
    {!this.state.isLoading ?
      <section className={`${styles.footer} ${this.props.hasTeamsContext ? styles.teams : ''}`}>
        <h1 className={`${styles.title}`}>{this.props.description}</h1>
        <div className={`${styles.socialMediaLinks}`}>
          {this.state.footerItems.map((fLink, i) => {
            return (
              <>
               {console.log(this.ImageCdnUrl(JSON.parse(fLink.FooterImage)?.serverRelativeUrl))}
                <a target="_blank" href={fLink.FooterUrl?.Url} data-interception="off"
                  rel="noreferrer">
                  <img alt={fLink["Title"]} src={this.ImageCdnUrl(JSON.parse(fLink.FooterImage)?.serverRelativeUrl)} />
                </a>
              </>
            ); }) }
        </div>
      </section>
      : <><Spinner label="Loading Footer..." size={SpinnerSize.medium} /></>}</>
  ); 
}

Step 7. Let's go with GulpServe and Validate the Image Url using console.log

All image URLs are redder from Private-Enabled CDN Path i.e. _api/V2.1/shares, which will cause one Network traffic call instead of multiple.

Footer  

Finally (Achieved), Let's build the package, deploy the solution to the app catalog, add a webpart to the page, and validate the Image render path.

I ran the below command to deploy the package.

  1. Gulp Build
  2. Gulp Bundle --ship
  3. Gulp Package-Solution --ship

Once the solution is deployed, the web part is added to the page. Inspect the images; we can see all control images redder from Private CDN. It will improve the network traffic with one call instead of multiple.

 Optimize SPFx Image render with Private CDN  

Hope you have learned something useful here.