sp-dev-docs
sp-dev-docs copied to clipboard
Lazy loading of custom web parts in modern pages
Category
- [x] Question
- [ ] Typo
- [ ] Additional article idea
Question
I am observing lazy loading of custom web parts in modern pages. A web part is not loaded/rendered until it is scrolled to. This was observed in both Targeted and Standard release tenants starting Jul 18. See snapshot of elements rendered of a HelloWorld webpart upon initial page load and then after it is scrolled into view.
My question: is there a way to override this behavior (either thru PS or even within spfx code) to render all webparts on page load?
My use case for this is in using dynamic data source web parts where the data source web part is at the bottom of a large page, while my destination/receiving web part is at the top. (Example: a navigation menu of various web parts in the page). Since the source is not rendered yet at the bottom, the top web part does not have any data coming from the source web parts. Prior to Jul 18, all web parts were renderd on page load, so my consumer web part was able to get all data from the source/publisher web parts at the bottom of the page.
Upon page load
After scrolling to web part
Environment details (development & target environment)
- Your Developer Environment: Windows 10
- Target Environment: SharePoint Online (Targeted and Standard release tenants)
- Framework: Node.js v6/v8/v10/v12]
- Browser(s): All
- Tooling: VS Code , SPFx v1.10.0
- Additional details: This was not observed prior to Jul 18. After Jul 18, the web parts are being wrapped around a <div data-viewport-id tag.
Thank you for reporting this issue. We will be triaging your incoming issue as soon as possible.
Related issue in PnP Web Parts samples repo: #1375
Steps to reproduce
- Get the code from Page Sections Navigation sample
- Add Page Section Navigation web part on top of the page.
- Add multiple Page Sections Navigation Anchor web parts on the page: some of them visible as soon as you open the page, some - invisible until you scroll down
- Save the page
- Only visible anchors are listed in the navigation
Expected behavior
All anchors are listed in the navigation
Additional context
The connection between navigation web part and anchor web part is done using Dynamic Data capability of SPFx.
Anchor web part is registered as a data source using this.context.dynamicDataSourceManager.initializeSource(this);
.
Navigation web part consumes dynamic data using API approach:
protected onInit(): Promise<void> {
//...
// getting data sources that have already been added on the page
this._initDataSources();
// registering for changes in available datasources
this.context.dynamicDataProvider.registerAvailableSourcesChanged(this._availableSourcesChanged);
//...
}
private _initDataSources(reRender?: boolean) {
// all data sources on the page
const availableDataSources = this.context.dynamicDataProvider.getAvailableSources();
for (let i = 0, len = availableDataSources.length; i < len; i++) {
let dataSource = availableDataSources[i];
if (!dataSource.getPropertyDefinitions().filter(pd => pd.id === 'anchor').length) {
continue; // we don't need data sources other than anchors
}
if (!dataSources || !dataSources.filter(ds => ds.id === dataSource.id).length) {
this.context.dynamicDataProvider.registerPropertyChanged(dataSource.id, 'anchor', this._onAnchorChanged);
}
}
}
Also experiencing this issue. I found that the OOTB Text webpart does not lazy load, I think due in part to allowing for headers to become anchors. If there's any way to expose that to webparts we create, that would be awesome!
We can also confirm that the OOTB Text webpart is directly loaded on the page, independent of it's position. Is there any setting/attribute that we can pass to our webparts in order to achieve the same behaviour?
I observed it is not working for OOTB webparts too. On a large page I have added 15 ListWebparts and one custom webpart on top of those webpart in same section. Custom webpart is applying some css through jQuery on each ListWebParts, but due to this issues only few ListWebparts are having that css. So I believe this is all due to lazy loading of OOTB webparts too.
Hello @pratk30 Would you be able to try seeing if the OOTB Text webpart is lazy loaded on your end?
Hello @pratk30 Would you be able to try seeing if the OOTB Text webpart is lazy loaded on your end?
@tgorgdotcom No, for this webpart this is not an issues. I mostly using document library OOTB webpart and having issues there. Only view port is created until you scrolled to webpart position.
We've also got this issue with attempting to implement anchor web parts with a navigation bar. The anchors that are out of the viewport will not be created and cannot be picked up by the receiving dynamic data source. If the page is scrolled to the bottom, the anchors will be picked up.
This isn't the best forum for general issues with lazy loading. However the issue around dynamic data not registering should be fixed. Can you confirm this aspect?
@patmill I can confirm that Dynamic Data is not registering data sources until you scroll to them.
Hmn, so what is supposed to be happening is that if we detect that a webpart in the viewport depends on one outside, that the webpart outside the viewport should load (so that it can get the contextual info). Also, can you tell what build your site is running (view page source, search for "buildNumber" ). If all of the parts are outside the viewport, then neither will load. The idea being that the webparts render correctly, but they don't load unless needed.
@patmill - what if I use the API approach to connect data sources and data consumers? The use case from the sample I linked here: We have a "navigation" web part and multiple "anchor" web parts. Navigation is a data consumer, anchors - data sources.
Navigation web part uses dynamicDataProvider
object to get all the anchor data sources from the page (getAvailableDataSources
) and registerAvailableSourcesChanged
to be notified when something is changed on the page.
BUT.
The navigation should know about all anchor web parts, even if they were not rendered yet.
So, I would expect, getAvailableDataSources
should return invisible web parts as well.
Build Number: sp-client-prod_2020-09-04.001
I just re-estimated some of our open issues of this year, and this has been one of them. Actually our anchor webparts did not work anymore for half a year now. But I really like to share one additional finding that may workaround this issue for some cases.
If you call your page with an anchor link that does not exist, somehow the browser searches for it within the page and this causes all spfx webparts to get loaded (skips lazy loading), so your anchors should all appear. Try it out! (for us it works at least in Chrome)
/sites/yourSite/SitePages/MyAnkerPage.aspx#THISANCHORDOESNOTEXIST
I just re-estimated some of our open issues of this year, and this has been one of them. Actually our anchor webparts did not work anymore for half a year now. But I really like to share one additional finding that may workaround this issue for some cases.
If you call your page with an anchor link that does not exist, somehow the browser searches for it within the page and this causes all spfx webparts to get loaded (skips lazy loading), so your anchors should all appear. Try it out! (for us it works at least in Chrome)
/sites/yourSite/SitePages/MyAnkerPage.aspx#THISANCHORDOESNOTEXIST
I was unable to see the webparts outside the viewport even when scrolling down
adding the #XXXXX worked well for me 💯 thank you
Is there any update regarding this topic? We need a stable solution for this behaviour despite the workaround #dummyanchor..
WebPart is not initialized until brought into view-port.
Unfortunately adding the anchor tag isn't a viable solution.
Any updates on this? Is someone from Microsoft looking at it, or considering to fix this? I can't ask all my customers to visit pages with a hash in the URL...
Although it is working - this is absurd... We need a way to be able to disable lazy loading on a page, programmatically, or better yet - disable this feature. It is causing so many issues that are very hard to trace and diagnose.
Agree to @shaipetel - it causes a lot of trouble and it should be possible to be deactivated on demand
It's unlikely that we will disable lazy-load. From the thread, it's hard to see if this is all scoped to dynamic data components, or if there is some other problem. Can you let me know what the problems you are facing are?
My issue is that our customers may add the same component several time to the page and each component needs to be aware of other instances for some internal display logic.
Another issue was if I want to have a TOC web part that will jump into content from another web part using the anchor/hash navigation. This doesn't work now since it only disables the lazy-load if the initial page load had a hash in it, not when you add a hash on a button click for example.
I'm sure there are many, many other examples/issues/reasons why this may cause problems.
And I'm not saying disable it always for everyone. I'm saying allow the web part on the page to set if it allows to be lazy-loaded or if it is required to load every time.
A simple web part property would do just fine, or any other way.
You guys can't break functionality without documenting it and just say "its unlikely we will disable it"... people are building solutions based on this framework... if that's the attitude, their solutions won't be reliable and people will move to more stable platforms. That's just my opinion.
I'm hoping this is addressed soon.
Sorry if my answer came across as flippant. The problem with loading and executing all webparts on a page is that it can have a very bad impact on page perf, and that makes end users unhappy. So - looking at options here - do you need knowledge of the parts, or do you need them executing? Would visibility into which webparts (but not running them through their life cycle) help unblock your scenarios?
If I have a “pre-init” event where they just get their properties but don’t render it’s good enough!
At first I hoped the constructor is called. But it’s not... and even if it did - it doesn’t have the properties so it’s not good enough sadly.
Unfortunately, pre-init / init can cause grief as well, particularly in the case of a) very large bundles or b) a lot of logic in the pre-init. However (thinking out loud), would seeing the list of webparts that are in the canvas and their config help? I don't know if a manifest level per-webpart-type setting would be a) possible or b) solve issues on things like anchors, etc. (again - brainstorming here)
Being able to query for all instances of a web part by ID, and get their saved properties is all I would need.
OK, thanks @shaipetel - what about @TitanRobot / @kmarwen ?
One more test case - printing.
We have a component that suppose to print the page with all content in it. Having this lazy loading was a huge pain, since web parts were just not loaded to the page.
So, again, in some cases we would just need the entire page to be rendered.
@patmill our main issue is the page section navigation (https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-page-sections-navigation)
On large sites we use the page section navigation to structure the site. Each area gets a heading with an anchor and then we use the anchor tags for navigation.
Unfortunatelly due to lazy loading not all anchors are present at the beginning. So the header navigation webpart cannot render all headings/anchors.
For us the solution would be, that all anchors are always known. As a workaround we are linking to these sites like: test.aspx#k but this is not working in all scenarios (search result, normal user sends link to site etc.)
OK, thanks @shaipetel - what about @TitanRobot / @kmarwen ?
Hi The issue for us was only about custom webparts. They were not loaded if we arrive to the page from a new tab or new session. The anchor with '#' at the end of the link worked for us and that what we deployed because we had only couple of links. I agree it's not a viable solution and Microsoft may provide a better workaround. Thank you
Hi @kmarwen, can you confirm the proposed workaround with '#' is working on your site?
We are facing the same issue with anchors to WebPart that was not rendered on the page yet (Anchors are included in 3rd party "Modern Script Editor" WebPart).
Thanks