FYI, TLDR: I added comment which summarizes the main problem here https://github.com/SharePoint/sp-dev-docs/issues/3259#issuecomment-454753467.
I will start with the question first and provide some details later.
How can I use third party libraries (as well as our own, private node package [DLL]) and make sure they are only loaded/initialized once, even when there are multiple component types (web parts, application customizer) on a page?
I would expect external dependencies to be loaded (and initialized) only once, even if they are used in several components on one page. This doesn't seem to be the case, for example we get warnings like there are multiple mobx instances active.
We are building an intranet solution that contains web parts (extend BaseClientSideWebPart) as well as some components in header and footer (extend BaseApplicationCustomizer).
We have common code coming from our own, private npm module that is referenced in the package.json of our SharePoint app. I will refer to this as "our library". Our library uses external dependencies like mobx, styled-components and several others. Some of these dependencies are bundled directly in to our library, others are loaded by SPFx (specified as externals in config.json).
Basically everything works. I.e. it works if we are
But we have problems when there are both component types on the same page. Some of the problems we get are
[mobx] Warning: there are multiple mobx instances active. This might lead to unexpected results. See https://github.com/mobxjs/mobx/issues/1082 for details.Long story short: I need a solution for this. I found and tried several different things:
externals in config.json and by specifying it as a globalDependencies of our library. After this, the application still worked as before, i.e. nothing broke, but the initial problems were still here.Thank you for reporting this issue. We will be triaging your incoming issue as soon as possible.
This is kind of related to issues https://github.com/SharePoint/sp-dev-docs/issues/467 and https://github.com/SharePoint/sp-dev-docs/issues/2388
@VesaJuvonen, @pgonzal : I'm replying to your comments from #467 as that issue is closed.
We have exactly that situation: We want to share code (from a bundling/network/loading/performance perspective) as well as from a runtime perspective (only one instance of singletons, external dependencies, etc.):
To be honest I am surprised that there aren't more customers that have requirements like this.
Update: I found a couple of resources that create one bundle for different web parts (the default behavior is that for every component an own bundle is created), e.g. this one: https://www.eliostruyf.com/creating-multi-component-bundles-in-sharepoint-framework-solutions/
I now did the same, with following result:
config.json)there are multiple mobx instances active, etc.This means, as far as I understand, that SPFx somehow executes the whole script again, leading to multiple instances/contexts being created. But only when there are application customizers _and_ web parts on the page. Is this correct? Is there anyway to work around this? Can I share code between an application customizer and a web part?
Ok, after some further analysis I would like to summarize my findings:
When a web part (BaseClientSideWebPart) and a application customizer (BaseApplicationCustomizer) are placed on the same page, they are both instantiated independently. This means they run in completely unrelated contexts. So for example
export const foo = Math.rand() will be executed once for the web part and once for the application customizer. From a naive developer perspective I would expect this to be executed only once per solution.As far as I understand, the SPFx team is aware of this (https://github.com/SharePoint/sp-dev-docs/issues/467#issuecomment-321548410 and others) since one and a half years, but are not sure if this is an actual problem.
I see this as a major problem, as it prevents developers from reliably sharing code between the different components on the page. Sure, one could argue that libraries like styled-components should be able to deal with multiple instance on a page (especially if it is the same version), on the other hand I believe that SPFx should only initialize the code once, due to the other, above mentioned problems.
Some related resources are:
@patmill, @VesaJuvonen Is there any work around for this? Or are the any plans to change this in the near future?
There is a _solution_ for this currently under dev / in the roadmap that you can monitor & vote up in uservoice. In summary, it adds a new component of type library that multiple components can depend on.
However, you can implement this today... nothing specific to SharePoint IMHO... it's a pattern that's common in normal web dev. Create a separate library and publish it as an NPM package. You can then get that library hosted in a CDN (one you maintain, or public one if you have enough 👍 / ⭐. Then just make sure you included it as an external reference. This will tell the hosted SPFx implementation of system.js to only load the module once on the page.
So... there's a solution to this challenge today, but MSFT is also working on a solution for SPFx-specific scenarios.
Thanks for your reply @andrewconnell. I already up voted in the user voice and am aware of the library type. And I am also aware of the "npm package" approach, as this is exactly what we are doing:
config.jsonAbove behavior made me create a very simple dummy project to show this without having any dependencies: https://github.com/PzYon/spfx-code-share
Basically what i do there is I have following line of code:
export const SimpleConstValue = Math.random();
This is rendered by a react component that is used by a web part and the application customizer. When I add the web part twice to the page, this is the outcome:

As you can see, the value (i.e. Math.random()) is executed twice, once for the Application Customizer and once for the Web Part. And for the two web part instances, it's the same value.
And I believe that's the problem. So it isn't related to externals, etc. but to the way that SPFx (or system.js) loads and initializes the different component types available in SPFx. It appears that the context or scope or however you want to call it is shared, but only per component type.
Can you confirm this? Or am I doing something wrong?
We have the same problem.
And it's annoying because some libraries just don't work :/
Problem (and solution) is understood. Not ignoring the thread, we just can't mark it as fixed at the moment.
Ok. So that means that's just the way it is and there is no workaround at this moment. Correct? Do you have any idea, when this will be fixed, as I understand you already know the solution.
Any updates on this? It's causing us a lot of problems in the meanwhile...
The scenario should now be possible through the Library feature we introduced in the latest release of SPFx.
Can you please confirm it and, if yes, close this issue?
This issue has been automatically marked as stale because it has marked as requiring author feedback but has not had any activity for 7 days. It will be closed if no further activity occurs within next 7 days of this comment. Thank you for your contributions to SharePoint Developer activities.
Closing issue due no response from original author. If this issue is still occurring, please open a new issue with additional details. Notice that if you have included another related issue as additional comment on this, please open that also as separate issue, so that we can track it independently.
Issues that have been closed & had no follow-up activity for at least 7 days are automatically locked. Please refer to our wiki for more details, including how to remediate this action if you feel this was done prematurely or in error: Issue List: Our approach to locked issues