Recently I was looking at the logging package in the @PNP/pnpjs library.

To summarize how the logging infrastructure works.

You use the Logger class to configure and subscribe your logger instance.

import {
} from "@pnp/logging";

const LOG_SOURCE: string = 'MyAwesomeWebPart';
Logger.subscribe(ConsoleListener(LOG_SOURCE, {color:'#0b6a0b',warningColor:'magenta'}));
Logger.activeLogLevel = LogLevel.Info;

Then you can just use the same Logger class anywhere in your web part to write a message to the subscribed loggers.

Logger.write("My special message");
Logger.write("A warning!", LogLevel.Warning);

Considering there is no dependency injection involved this seems to point to Logger being a global class (that acts similar to a C# static). This is confirmed by its typescript definition

export declare class Logger {
    private static _instance;
     * Gets or sets the active log level to apply for log filtering
    static activeLogLevel: LogLevel;
    private static readonly instance;
    // more code here....

But... if this was the case then multiple web parts on the same page using the library would end up in multiple subscribed loggers... and each write operation would write to EVERY logger.

The issue

I was therefore trying to understand how the logger was supposed to work. And I stumbled up this page on github;

I'm interested to understand how the static Logger class handles usage in multiple SPFx components on the same page.
If we have a custom LogListener that's registered via the Logger's subscribe method, what is the scope of that subscription array?
For example, if the custom LogListener is defined with data specific to the calling web part, will it's data ever be used if the Logger static class is called in another context, e.g. another SPFx web part on the same page?

Patrick answer then mentions something interesting.

Each SPFx web part is itself a closure, meaning anything instantiated within that container is only present in that container. So your webparts wouldn't know that others were even using the same logging framework.

Each SPFx web part is itself a closure. I understand what they must mean: SharePoint has a way to encapsulate a web part code so that its "global" variables are actually accessible only to that specific web part instance.
What I don't get is how SharePoint does that.

I tried looking at the available documentation but as usual I couldn't find anything useful.

My question is therefore this: can anyone provide me with some references to any (preferably official) material that describe this "closure" behaviour in SharePoint (SPFX only?) web parts?

1 Answer 1


This behavior is not unique to SharePoint but is a fundamental concept in JavaScript, which SharePoint SPFx web parts are built upon.

In JavaScript, a closure is a function that has access to its own scope, the outer function’s scope, and the global scope. This allows for data privacy, as variables defined within a function cannot be accessed from outside the function, unless exposed through a public method.

Unfortunately, there doesn’t seem to be any official documentation that specifically describes this “closure” behavior in SharePoint SPFx web parts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.