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

First time navigation doesn't fire enhancedload or DOMContentLoaded events when page is loaded. #59780

Open
1 task done
htmlsplash opened this issue Jan 8, 2025 · 3 comments
Labels
area-blazor Includes: Blazor, Razor Components Needs: Attention 👋 This issue needs the attention of a contributor, typically because the OP has provided an update.

Comments

@htmlsplash
Copy link

htmlsplash commented Jan 8, 2025

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Environment:
.net 9
Blazor Static SSR page
Visual Studio: 17.12.3

When navigating to a page for the first time using a simple hyperlink the wired up event handlers to DOMContentLoaded or enhancedload are not invoked, ie. one of these should run, but neither runs.

Blazor.addEventListener('enhancedload', () => {
	console.log('enhancedload!');
});

document.addEventListener('DOMContentLoaded', function() {
	console.log('Document is fully loaded!');
});

To view the event handler trace, you need to open dev tools console.

To reproduce:
Go to this repo: https://github.com/htmlsplash/BlazorWebAppTest
Launch project
Open browser dev console
Select "Nav test 1" option from the left nav.
Check the console to see traces.
The source page of interest for this bug report is: NavTest1.razor

NOTE;
This bug is very tricky to reproduce. If you do observe the traces, select "Home" link, press F5 (while on the home page), then go back and select Nav test 1 option.

UPDATE 1:
Read my update comments below.

Expected Behavior

One of the registered handlers for DOMContentLoaded or enhancedload should be invoked.

Steps To Reproduce

See problem description.

Exceptions (if any)

No response

.NET Version

.net 9

Anything else?

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-blazor Includes: Blazor, Razor Components label Jan 8, 2025
@htmlsplash
Copy link
Author

htmlsplash commented Jan 8, 2025

UPDATE:

I made a discovery which makes it appear that my JS in the script tags is not executed at all, it is skipped. This means the event handlers are never registered!

You can test this by adding a console.log call inside the script tags outside any event handler/function.

@javiercn
Copy link
Member

javiercn commented Jan 9, 2025

@htmlsplash thanks for contacting us.

Can you try disabling enhanced navigation and see if it works that way?

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  Blazor.start({
    ssr: { disableDomPreservation: true }
  });
</script>

We believe what's happening here is that the script is being brought in as part of an enhanced navigation request. <script> tags aren't supported during enhanced navigation as the scripts bring in side-effects when they re-execute.

The recommendation is to use a JS module or an alternative solution like https://github.com/[MackinnonBuck/blazor-js-components](https://github.com/MackinnonBuck/blazor-js-components)

@javiercn javiercn added the Needs: Author Feedback The author of this issue needs to respond in order for us to continue investigating this issue. label Jan 9, 2025
@htmlsplash
Copy link
Author

htmlsplash commented Jan 9, 2025

@javiercn Disabling enhanced nav fixes the problem, but:

  1. I do not want to compromise and disable enhanced navigation for the entire site.
  2. I am really confused now how to reference JS in Blazor. In your documentation "JavaScript location in ASP.NET Core Blazor apps (https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/location-of-javascript?view=aspnetcore-9.0)" you tell us that we can place script tags at the end of the body element, now you're saying script tags are not allowed because of how enhanced navigation works.
    There's no clear story here, just lots of hoop jumping to make things work. I would recommend re-thinking the design at this point, in order to paint a consistent story how and where we should place our JS. The model should be consistent and simple to use, currently it is challenging to work with Javascript in Blazor amid all the render modes, specifically when using static SSR.
    PS.
    Please clarify this statement: "script tags aren't supported during enhanced navigation". Are you referring to any script tag, like using a script tag to include a JS file or just script tags with JavaScript code in them?
    Please also explain: "as the scripts bring in side-effects when they re-execute" - Does this applying to any JS? How about just registering event handlers, that should be allowed, what side-effect would that bring?

I did look at your recommendation (from MackinnonBuck), and I tried it, but it will not work in my scenario because of timing:
I need to wire up my enhanced load before it happens but it appears that my script/logic is loaded after enhanced load. Technically speaking, I could alter my code and wire up the events when the script gets loaded, instead of on enhanced load or DOMContentLoaded.

To sum it up:
Currently, for components rendered using "static SSR render mode" we do not have a reliable way to include JavaScript on the page.

My Workaround (that works):
One thing that did work is by moving my java script from the component to a separate JS file (collocated js file) and then including the JS file using script tag. Just below the include, I ran the single line of JS code before the closing body tag. This does seem to work in all cases on my environment.
In terms of what is different is that the java script code is not placed via section outlet, instead it is loaded using JS file. Why does the inline JS code run, and before it did not? This is confusing.'

Working Example - App.razor

`<script src="./Components/Pages/pimarc/FormViewControl.razor.js"></script>

<script> FormViewControl_init(); </script>`

Observations:

Even though this works, the problem is that this script will be included on every page, even though the component for which this script is for is not present on the page.

UPDATE:
After extensive testing I can confirm that using Section Outlet to place your scripts screws things up, but by including JS directly below closing body tag (in the app component) works.

@dotnet-policy-service dotnet-policy-service bot added Needs: Attention 👋 This issue needs the attention of a contributor, typically because the OP has provided an update. and removed Needs: Author Feedback The author of this issue needs to respond in order for us to continue investigating this issue. labels Jan 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components Needs: Attention 👋 This issue needs the attention of a contributor, typically because the OP has provided an update.
Projects
None yet
Development

No branches or pull requests

2 participants