SharePoint Framework Extension: Preallocate space for an Application Customizer

Overview

 
An application customizer allows adding structures and content to the predefined placeholders on modern SharePoint sites. The application customizers often load asynchronously and cause the movement of the page after loading. This often observed as a flickering effect on the users. SharePoint Framework now allows to pre-allocate space for an application customizer to avoid the flickering behavior by pre-allocating the area on the server side when the page is rendered.
 
In this article, we will explore the new capability of an application customizer to avoid flickering, and few considerations during implementation.
 

Develop SPFx extension to Pre-allocate space for an Application Customizer

 
Follow the below steps to develop the SPFx solution:
 
1. Open a command prompt. Create a directory for the SPFx solution.
  1. md spfx-applicationextension-preallocate-space  
2. Navigate to the directory.
  1. cd spfx-applicationextension-preallocate-space  
3. Run the Yeoman SharePoint Generator to create the solution.
  1. yo @microsoft/sharepoint  
4. Yeoman generator will present you with the wizard by asking questions about the solution to be created.
 
 
When prompted-
  • Accept the default spfx-applicationextension-preallocate-space as your solution name, and then select Enter.
  • Select SharePoint Online only (latest), and then select Enter.
  • Select Use the current folder as the location for the files.
  • Select N to allow a solution to be deployed to all sites immediately.
  • Select N on the question if the solution contains unique permissions.
  • Select Extension as the client-side component type to be created.
  • Select Application Customizer as the extension type to be created.
  • Name the extension as PreallocateSpace.
  • Provide the description as Avoid page movement.
5. Yeoman generator will perform the scaffolding process to generate the solution. The scaffolding process will take a significant amount of time.
 
6. Once the scaffolding process is completed, lock down the version of the project dependencies by running below command.
  1. npm shrinkwrap  
7. In the command prompt type below command to open the solution in the code editor of your choice.
  1. code .  

Implement Application Customizer

 
Follow the below steps to implement top content place holder in an application customizer:
 
1. Open file src\extensions\preallocateSpace\PreallocateSpaceApplicationCustomizer.ts
 
2. To get access to placeholders on the page, use the below imports.
  1. import {    
  2.   BaseApplicationCustomizer,    
  3.   PlaceholderContent,    
  4.   PlaceholderName    
  5. } from '@microsoft/sp-application-base';  
3. Update the interface IPreallocateSpaceApplicationCustomizerProperties to include Top property.
  1. export interface IPreallocateSpaceApplicationCustomizerProperties {  
  2.   Top: string;  
  3. }  
4. Implement OnInit method.
  1. private _topPlaceholder: PlaceholderContent | undefined;  
  2.   
  3. @override  
  4. public onInit(): Promise<void> {  
  5.   Log.info(LOG_SOURCE, `Initialized ${strings.Title}`);    
  6.   
  7.   // Added to handle possible changes on the existence of placeholders.    
  8.   this.context.placeholderProvider.changedEvent.add(thisthis._renderPlaceHolders);    
  9.       
  10.   // Call render method for generating the HTML elements.    
  11.   this._renderPlaceHolders();    
  12.   
  13.   return Promise.resolve();    
  14. }  
5. Implement _renderPlaceHolders method. 
  1. private _renderPlaceHolders(): void {  
  2.   // Handling the top placeholder    
  3.   if (!this._topPlaceholder) {  
  4.     this._topPlaceholder =  
  5.       this.context.placeholderProvider.tryCreateContent(  
  6.         PlaceholderName.Top,  
  7.         { onDispose: this._onDispose }  
  8.       );  
  9.   
  10.     // The extension should not assume that the expected placeholder is available.    
  11.     if (!this._topPlaceholder) {  
  12.       console.error('The expected placeholder (Top) was not found.');  
  13.       return;  
  14.     }  
  15.   
  16.     if (this.properties) {  
  17.       let topString: string = this.properties.Top;  
  18.       if (!topString) {  
  19.         topString = '(Top property was not defined.)';  
  20.       }  
  21.   
  22.       if (this._topPlaceholder.domElement) {  
  23.         this._topPlaceholder.domElement.innerHTML = `    
  24.           <div>    
  25.             <div class="ms-bgColor-themeDark ms-fontColor-white">    
  26.               <i class="ms-Icon ms-Icon--Info" aria-hidden="true"></i> ${escape(topString)}    
  27.             </div>    
  28.           </div>`;  
  29.       }  
  30.     }  
  31.   }  
  32. }  
6. Implement _onDispose method.
  1. private _onDispose(): void {  
  2.   console.log('[PreallocateSpaceApplicationCustomizer._onDispose] Disposed custom top placeholder.');  
  3. }  
At this point, we have set up a minimal application customizer to add the placeholder to the top of the SharePoint page. Now, let's start adding some business logic to it.
 

Add Processing to an Application Customizer

 
We will now add business processing to an Application Customizer. Be it any business scenario to implement (for e.g. reading data from SharePoint using REST APIs or maybe accessing some Graph API), it might take a few seconds to process.
 
Let us implement a method to assume some processing time (e.g. 2 seconds) for the business logic.
  1. public getTopMessage(): Promise<string> {  
  2.   return new Promise<string>((resolve, reject): void => {  
  3.     setTimeout(() => resolve(this.properties.Top), 2000);  
  4.   });  
  5. }  
This method will return us the text to be added to the Top placeholder. Now, let us use this method inside _renderPlaceHolders. 
  1. private _renderPlaceHolders(): void {  
  2. .  
  3. .  
  4. .  
  5. if (this._topPlaceholder.domElement) {  
  6.           this.getTopMessage().then((topMessage: string) => {  
  7.             this._topPlaceholder.domElement.innerHTML = `    
  8.             <div>    
  9.               <div class="ms-bgColor-themeDark ms-fontColor-white">    
  10.                 <i class="ms-Icon ms-Icon--Info" aria-hidden="true"></i> ${topMessage}    
  11.               </div>    
  12.             </div>`;  
  13.           });  
  14.         }  
  15. .  
  16. .  
  17. .  
  18. }   

Deploy an Application Customizer to SharePoint

 
Deploy the application customizer to SharePoint site by following below steps,
 
On the command prompt, execute below commands-
 
1. Generate bundles in the dist folder.
  1. gulp bundle --ship  
2. Generate .sppkg file to be deployed in the SharePoint app catalog.
  1. gulp package-solution --ship  
3. Deploy the application customizer app to the SharePoint site.
 
4. Refresh the SharePoint site. You will observe the movement of the page (flickering).
 
 
 

How to avoid the movement of the page?

 
To pre-allocate space, below HostProperties configuration properties can be used:
  • preAllocatedApplicationCustomizerTopHeight - Pre-allocated height for the top placeholder
  • preAllocatedApplicationCustomizerBottomHeight - Pre-allocated height for the bottom placeholder
Pre-allocation can be defined either in the elements.xml or in the ClientSideInstance.xml files.
 
Pre-allocation for site scoped deployment
 
For site scoped deployment, pre-allocation can be defined as HostProperties entry in elements.xml file under sharepoint\assets folder.
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <Elements xmlns="http://schemas.microsoft.com/sharepoint/">  
  3.     <CustomAction  
  4.         Title="PreallocateSpace"  
  5.         Location="ClientSideExtension.ApplicationCustomizer"  
  6.         ClientSideComponentId="d1a63535-2e2a-4cb9-8e78-f29d4743c396"  
  7.         ClientSideComponentProperties="{"Top":"Test message"}"  
  8.         HostProperties="{"preAllocatedApplicationCustomizerTopHeight":"50","preAllocatedApplicationCustomizerBottomHeight":"50"}">  
  9.     </CustomAction>  
  10. </Elements>  
The above configuration will define the default height to 50 pixels.
 
Pre-allocation for tenant-wide deployment
 
For tenant-wide deployment, pre-allocation can be defined as HostProperties entry in ClientSideInstance.xml file under sharepoint\assets folder.
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <Elements xmlns="http://schemas.microsoft.com/sharepoint/">  
  3.     <ClientSideComponentInstance  
  4.         Title="PreallocateSpace"  
  5.         Location="ClientSideExtension.ApplicationCustomizer"  
  6.         ComponentId="d1a63535-2e2a-4cb9-8e78-f29d4743c396"  
  7.         Properties="{"Top":"Test message"}"  
  8.         HostProperties="{"preAllocatedApplicationCustomizerTopHeight":"50","preAllocatedApplicationCustomizerBottomHeight":"50"}">  
  9.     </ClientSideComponentInstance>  
  10. </Elements>  

Test the Pre-allocated Space

 
An application customizer pre-allocates the defined space on the server side as shown below,
 
  

Key Considerations

 
Below are few key considerations while pre-allocating the space-
  • This option is only available in SharePoint Online.
  • If you pre-allocate the placeholder place but do not create any placeholder in the code, the server-side allocated space will remain on the page.
  • If the pre-allocated height is more, the div will have an extra space.
  • If the pre-allocated height is less, the div will get compressed.

Summary

 
SharePoint Framework now allows to pre-allocate space for an application customizer to avoid the flickering behavior by pre-allocating the area on the server-side when the page is rendered. Pre-allocation can be defined as HostProperties configuration property either in the elements.xml or in the ClientSideInstance.xml files.
 

Code Download

 
The code developed during this article can be downloaded from Github.