Optimizing powerbi-client’s performance within Angular

In the previous post, I had explained how to use the powerbi-client library with Angular for embedding your Power BI reports in a web application. In this post, we will go over some optimizations that could be done to improve the performance of the application significantly. Let’s directly jump into it!

1. Importing powerbi-client through runtime globals

You would have seen the method below to import powerbi-client in Angular

import * as pbi from ‘powerbi-client’;

By importing it this way you are creating one copy of powebi-client in the browser’s memory for each component you import it in. So if you try to import powerbi-client into multiple components you will end up with a very laggy experience or worst just killing the browser. The solution to this problem is to create a single copy of the powerbi-client in the runtime global and refer to the same copy from each component.

// Add this in 'scripts' of the project's 'angular.json'
"scripts": [
"node_modules/powerbi-client/dist/powerbi.min.js"
]
// Import types as shown below inside any component
import { Report, models, service, IEmbedConfiguration } from 'powerbi-client';
// Use this powerbi variable for any embedding inside any component
declare var powerbi: service.Service;

2. Bootstrapping embedded report

Bootstrapping is a way to initialize your powerbi report container during the initial load of the component. The advantage of this step is you no longer need to wait for the embed token to arrive from the backend to start the embedding process. By bootstrapping your report you have all the required elements for creating the outline of the report already loaded into the browser's memory and you could fire an async API call to get the Embed token and pass it on to the embed function to get that report rendered on the UI.

// Example .ts for bootstrappingreport: Report;
@ViewChild('reportContainer', { static: true }) reportContainer: ElementRef;
ngOnInit() {
this.bootstrapPowerBi();
// Async call to get the embed token from backend, call showReport(Token) on success
}
bootstrapPowerBi() {
let settings: IEmbedSettings = {
filterPaneEnabled: false,
navContentPaneEnabled: false
};
powerbi.bootstrap(
this.reportContainer.nativeElement,
{
type: 'report',
embedUrl: environment.powerBI.reportBaseURL,
groupId: environment.powerBI.groupID,
settings: settings
}
);
}
showReport(Token) {
// Report Config
let config: IEmbedConfiguration = {
type: 'report',
tokenType: models.TokenType.Embed,
accessToken: Token["token"],
id: Token["reportId"],
bootstrapped: true
};
this.report = <Report>powerbi.embed(this.reportContainer.nativeElement, config); this.report.on("loaded", () => {
console.log("Report Loaded");
});
this.report.on("error", () => {
console.log("Error");
});
}

One thing to keep in mind while bootstrapping is that you need to call powerbi.embed() on the same report container which was used inside the powerbi.bootstrap() call.

3. Phased Embedding

If you want to perform some operations like setting filters, switching pages, etc. on the initial load of the report before the report is shown to the user you could use powerbi.load() instead of powerbi.embed(). This helps you to create a smooth rendering of the report and hiding the operations of applying filters or switching pages from the user.

// Modified showReport() for phased embedding
showReport(Token) {
// Report Config
let config: IEmbedConfiguration = {
type: 'report',
tokenType: models.TokenType.Embed,
accessToken: Token["token"],
id: Token["reportId"],
bootstrapped: true
};
this.report = <Report>powerbi.load(this.reportContainer.nativeElement, config); this.report.on("loaded", () => {
console.log("Report Loaded");
this.setPage(3); // Example operation
this.setFilter("Initial Filter"); // Example operation
report.render(); // Rendering report
});
this.report.on("rendered", () => {
console.log("Report Rendered");
});
this.report.on("error", () => {
console.log("Error");
});
}

Conclusion:

Those were the optimizations that I found while working with powerbi-client library, hope you will find them useful! Let me know in the comments below if they worked for you and also drop any additional technique which could be used to improve the performance.

Full Stack Web Developer and a tech enthusiast XD