Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazy loading of custom web parts in modern pages #6091

Closed
1 of 3 tasks
stchiew opened this issue Jul 22, 2020 · 48 comments
Closed
1 of 3 tasks

Lazy loading of custom web parts in modern pages #6091

stchiew opened this issue Jul 22, 2020 · 48 comments
Labels
area:spfx Category: SharePoint Framework (not extensions related) status:to-be-reviewed Issue needs to be reviewed by Microsoft for additional follow up / review. type:bug-suspected Suspected bug (not working as designed/expected). See “type:bug-confirmed” for confirmed bugs.
Milestone

Comments

@stchiew
Copy link

stchiew commented Jul 22, 2020

Category

  • 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
image

After scrolling to web part
image

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.
@msft-github-bot
Copy link
Collaborator

Thank you for reporting this issue. We will be triaging your incoming issue as soon as possible.

@AJIXuMuK
Copy link
Collaborator

Related issue in PnP Web Parts samples repo: #1375

Steps to reproduce

  1. Get the code from Page Sections Navigation sample
  2. Add Page Section Navigation web part on top of the page.
  3. 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
  4. Save the page
  5. 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);
      }
    }
  }

@andrewconnell andrewconnell added area:spfx Category: SharePoint Framework (not extensions related) Needs: Microsoft Review 👓 type:bug-suspected Suspected bug (not working as designed/expected). See “type:bug-confirmed” for confirmed bugs. and removed Needs: Triage 🔍 Awaiting categorization and initial review. labels Jul 31, 2020
@tgorgdotcom
Copy link

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!

@netti01
Copy link

netti01 commented Sep 2, 2020

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?

@pratk30
Copy link

pratk30 commented Sep 9, 2020

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.

@tgorgdotcom
Copy link

Hello @pratk30 Would you be able to try seeing if the OOTB Text webpart is lazy loaded on your end?

@pratk30
Copy link

pratk30 commented Sep 15, 2020

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.

@AdenKenny
Copy link

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.

@patmill
Copy link
Contributor

patmill commented Oct 1, 2020

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?

@AJIXuMuK
Copy link
Collaborator

AJIXuMuK commented Oct 1, 2020

@patmill I can confirm that Dynamic Data is not registering data sources until you scroll to them.

@patmill
Copy link
Contributor

patmill commented Oct 1, 2020

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.

@AJIXuMuK
Copy link
Collaborator

AJIXuMuK commented Oct 1, 2020

@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

@andrewconnell andrewconnell added status:to-be-reviewed Issue needs to be reviewed by Microsoft for additional follow up / review. and removed Needs: Microsoft Review 👓 labels Dec 4, 2020
@netti01
Copy link

netti01 commented Dec 29, 2020

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

@kmarwen
Copy link

kmarwen commented Jan 18, 2021

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

@TitanRobot
Copy link

Is there any update regarding this topic? We need a stable solution for this behaviour despite the workaround #dummyanchor..

@Ludwixix
Copy link

WebPart is not initialized until brought into view-port.

Unfortunately adding the anchor tag isn't a viable solution.

@shaipetel
Copy link
Contributor

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.

@TitanRobot
Copy link

Agree to @shaipetel - it causes a lot of trouble and it should be possible to be deactivated on demand

@patmill
Copy link
Contributor

patmill commented Aug 26, 2021

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?

@shaipetel
Copy link
Contributor

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.

@shaipetel
Copy link
Contributor

shaipetel commented Aug 26, 2021 via email

@shaipetel
Copy link
Contributor

shaipetel commented Aug 26, 2021 via email

@patmill
Copy link
Contributor

patmill commented Aug 26, 2021

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)

@shaipetel
Copy link
Contributor

shaipetel commented Aug 26, 2021 via email

@patmill
Copy link
Contributor

patmill commented Aug 26, 2021

OK, thanks @shaipetel - what about @TitanRobot / @kmarwen ?

@shaipetel
Copy link
Contributor

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.

@TitanRobot
Copy link

@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.)

@kmarwen
Copy link

kmarwen commented Aug 27, 2021

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

@salascz
Copy link

salascz commented Sep 17, 2021

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

@shaipetel
Copy link
Contributor

@salascz I believe his previous comment clearly said adding # at the end of the link worked for them.
But that it is not a viable solution, meaning not a solution that is acceptable in all other circumstances (where you might have this issue in more than 1-2 links, or where links are being sent in email, etc.)

BTW, adding the # while you are on the page does not fix this. you have to visit the page with # in the URL on the first time you visit it for this workaround to help.

@netti01
Copy link

netti01 commented Sep 20, 2021

A couple of weeks ago, we did some further investigation on this issue and found out that there is a ViewPortManager component in REACT which is most likely used by SPFX webparts as well. If you have a look at the REACT attributes of a webpart you will find the following stucture for _registeredComponents:

image

The registeredInViewport attribute informs you if the webpart has been allready rendered. If not, you can call the method onInViewport() which will than render the webpart.

As you can see, there is also an attribute forceInViewPort which is unfortunately false for all webparts. But perhaps there is a way for at least our custom webparts to set this to true by default.

@shaipetel
Copy link
Contributor

@netti01 thanks, but I'm not sure how this is helpful, being that even my web part's constructor isn't being called.
When my web part is not rendered - none of its logic/code is running, so I'm not sure how would I be able to make any calls on the page?

IMHO, the solution will need to be either declarative (so ppl can declare their webpart must run on every page) or by some sort of bypass for the lazy load mechanism.

Another use case that might be a huge issue, is a tracking web part. For example, imagine you are writing a webpart at the bottom of each page that shows how many people viewed it, or some other form of statistics.
By not loading that web part at all this would break this functionality and I don't see a way to fix it apart from providing developers a declarative way to opt in/out of the lazy loading feature...

Again, I see the point of trying to make things faster but I don't think this feature was well-executed or well thought-of in terms of the amount of un-intended bugs it creates for so many developers, who might not even notice it until they do end up with a very long content page...

@patmill
Copy link
Contributor

patmill commented Nov 18, 2021

(sorry for going dark. Still discussing this with various owning teams)

@SPDEVGUY
Copy link

This is an ongoing issue. We are experincing this with SP modern on-prem if we have any dynamic web parts at the base of the page when scrolling is involved the scrollbar isn't loaded and then loads after when we "jiggle" the page by resizing it. The lazy load counter changes from 2 to 0 and the scrollbars come back.

image
image

We need a fix or option to disable this for modern experiences on-prem as well.

@patrickblanc
Copy link

Hi there.
Imagine a page where you have lot of webparts in it. Then on one of the webpart you have an anchor image to copy the link to go directly to this section on the page. https://microsoft.sharepoint.com/sites/one/SitePages/myPage.aspx#my-webpart-anchor
Then you want to share this to someone in your company to allow him to directly access the content you want to share with him, so you sent hime : https://microsoft.sharepoint.com/sites/one/SitePages/myPage.aspx#my-webpart-anchor copied by clicking on the anchor icon of a custom webpart for example.
The guy received the link, click on it, but he will reach the top of the page because of lazy loading and the page itself does not find the anchor, right ? because it has not been loaded yet.
How to achieve that ?

@patrickblanc
Copy link

#6091 (comment)

See this is working there :) 👍

@shaipetel
Copy link
Contributor

I was under the impression that if you enter the page with anything in the hash the lazy load is disabled, exactly for that reason.
Isn't that the case on premises?

Not that it is a good solution, since you can't guarantee the hash will stay there. Some redirects will drop the hash for the users... especially if they hit a cold link in an email which opens the browser and needs to authenticate.

@AJIXuMuK
Copy link
Collaborator

Please, take a look at the discussion around this issue: #7918

@heinrich-ulbricht
Copy link
Contributor

heinrich-ulbricht commented Jul 6, 2022

Found this thread while handling a customer's issue regarding accessibility. When showing SharePoint pages at high zoom levels (> 400%) and/or on smaller screens usually no web parts are rendered until you scroll (since all you see initially is hardly more than the page title). This is also true for out-of-the-box web parts. A visually impaired person that is dependent on keyboard navigation and screen readers is not able to navigate the page. The expected behavior here would be that the page is fully loaded, enabling for easy keyboard navigation ("tabbing through the page").

I appreciate the selective effort on #7918 but still see a case for completely disabling lazy loading from an accessibility perspective (with to-be-defined scope (page/site/tenant)).

@HolgerLutz
Copy link

ts in it. Then on one of the webpart you have an anchor image to copy the link to go directly to this sectio

This is an ongoing issue. We are experincing this with SP modern on-prem if we have any dynamic web parts at the base of the page when scrolling is involved the scrollbar isn't loaded and then loads after when we "jiggle" the page by resizing it. The lazy load counter changes from 2 to 0 and the scrollbars come back.

image image

We need a fix or option to disable this for modern experiences on-prem as well.

@SPDEVGUY code changes for SharePoint 2019 and Subscription Edition have been recently released that might improve the situation.
SharePoint 2019 September 2022 PU -> https://aka.ms/sp2019/2022-09
SharePoint Subscription Edition July 2022 PU -> https://aka.ms/spse/2022-07

It would be great if you could check if it improved after installing the fixes. Thanks

@PieterHeemeryck
Copy link

I had a similar issue where web parts did not immediately load, even though they should as they are all above the fold. Programmatically scrolling 1px down & up works as a workaround to load the 'nearest' web parts (not all). I'm doing this at the end of the onInit method inside an application customizer (SPFx extension - header).

	const scrollElement = document.querySelector('[data-automation-id="contentScrollRegion"]');
	scrollElement.scrollBy(0, 1);

	setTimeout(() => {
		scrollElement.scrollBy(0, -1);
		console.log("Connect - scroll action complete");
	}, 0);

@AJIXuMuK AJIXuMuK added this to the 01-06-23 milestone Jan 4, 2023
@AJIXuMuK
Copy link
Collaborator

AJIXuMuK commented Jan 4, 2023

The issue has been addressed.
The changes will be rolled out in the next couple of weeks.
As a result - web parts that are initialized as data sources should be excluded from the lazy loading logic, similarly to the data sources connected using property pane UI.

@heinrich-ulbricht
Copy link
Contributor

@AJIXuMuK Is it possible to activate this for standard SharePoint web parts as well? Automated, e.g. via PowerShell? To e.g. build a table of contents from all text web part headlines.

And does the page load other web parts up to the last such non-lazy web part? Or does it really just load the non-lazy web parts and skips others inbetween?

And is there documentation yet, or tbd?

Thrilled about this new possibility!

@AJIXuMuK
Copy link
Collaborator

AJIXuMuK commented Jan 5, 2023

@heinrich-ulbricht,

Is it possible to activate this for standard SharePoint web parts as well? Automated, e.g. via PowerShell?

the functionality is related to Dynamic Data web parts only. You can't force any web part to be excluded from the lazy loading.

To e.g. build a table of contents from all text web part headlines.

Page Navigation is similar to TOC scenario. It should work with the changes.

And does the page load other web parts up to the last such non-lazy web part?

It doesn't load other web parts. So the "in-between" web parts are skipped.

And is there documentation yet, or tbd?

Why kind of documentation? There are no changes from developer side. You just use Dynamic Data features and they will work as expected.

@heinrich-ulbricht
Copy link
Contributor

@AJIXuMuK If there is not more to it then your comment is the documentation I asked for. Thank you :)

@AJIXuMuK
Copy link
Collaborator

This should be rolled out WW by now.

@ghost
Copy link

ghost commented Feb 1, 2023

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

@ghost ghost locked as resolved and limited conversation to collaborators Feb 1, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area:spfx Category: SharePoint Framework (not extensions related) status:to-be-reviewed Issue needs to be reviewed by Microsoft for additional follow up / review. type:bug-suspected Suspected bug (not working as designed/expected). See “type:bug-confirmed” for confirmed bugs.
Projects
None yet
Development

No branches or pull requests