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

next/script does not trigger onLoad callback when used with beforeInteractive strategy #33191

Closed
gabrielpioto opened this issue Jan 11, 2022 · 16 comments
Assignees
Labels
bug Issue was opened via the bug report template. please verify canary The issue should be verified against next@canary. It will be closed after 30 days of inactivity Script (next/script) Related to Next.js Script Optimization.

Comments

@gabrielpioto
Copy link

Run next info (available from version 12.0.8 and up)

No response

What version of Next.js are you using?

11.1.2

What version of Node.js are you using?

14.15

What browser are you using?

Chrome

What operating system are you using?

Linux

How are you deploying your application?

next dev

Describe the Bug

According to the docs, onLoad callback of next/script component can be used either with beforeInteractive and afterInteractive strategies. But when using with beforeInteractive strategy, onLoad callback never gets called.

Expected Behavior

Expect onLoad callback to be called when loading script with beforeInteractive strategy

To Reproduce

Using the same example of the docs, with stripe script: hasLoaded is never set to true and stripe has loaded never gets printed.
I get the same behavior in the latest version of next.

Here is a minimal reproducible repo: https://github.com/loft-br/before-interactive-on-load-bug
image

@gabrielpioto gabrielpioto added the bug Issue was opened via the bug report template. label Jan 11, 2022
@gabrielpioto gabrielpioto changed the title <Script /> does not trigger onLoad callback when used with strategy=beforeInteractive next/script does not trigger onLoad callback when used with beforeInteractive strategy Jan 11, 2022
@balazsorban44
Copy link
Member

This is expected. See #26343 (comment)

Also related #28889

@gabrielpioto
Copy link
Author

gabrielpioto commented Jan 11, 2022

Sorry if I'm missing something, but this is not about inline scripts at all. It is a third party script just like the example in the docs.
Perhaps this part of the docs should be updated then if this is expected

Some third-party scripts require users to run JavaScript code after the script has finished loading in order to instantiate content or call a function. If you are loading a script with either beforeInteractive or afterInteractive as a loading strategy, you can execute code after it has loaded using the onLoad property:

@balazsorban44 balazsorban44 reopened this Jan 11, 2022
@balazsorban44
Copy link
Member

The documentation does not use strategy="beforeInteractive" when loading a third-party, but your example did.

Removing that prop loads it correctly. So just curious if it was a misunderstanding or just a bad reproduction?

What is your use case by the way? What kind of third-party script do you try embedding with the beforeInteractive strategy?

@gabrielpioto
Copy link
Author

gabrielpioto commented Jan 12, 2022

We are trying to use google optimize script with beforeInteractive strategy so it can apply DOM changes as soon as possible.

However, because we are using SSR, this is not enough to prevent flickering, so we tried to use antiflicker script provided by Google but it sets opacity:0 to the whole page and this hurts web vitals (mainly LCP).

We are trying to implement the anti-flicking algorithm by ourselves so it can be used per component / section of the page

@akselinurmio
Copy link

akselinurmio commented Jan 17, 2022

Me and my team are struggling with this exact issue right now. I created the issue #33402 on documentation inconsistencies, but would also like to see some sort of a resolve to this.

Our use case is following: we use two next/script elements to load two external scripts: the first one loads a cookie consent SDK and the second loads our analytics library. Both of the script elements have their own onLoads for initialization.

The problem is that the analytics library depends on the cookie consent SDK, so we need to load and initialize that one first. Also, both of these scripts need to be initialized before any React useEffect hooks are run, because that's where the tracking functions of the analytics library are to be used.

Now, because onLoads for these scripts are just silently ignored, we can't do initialization on neither of these libraries.

@hemmachat
Copy link

We are having the same issue with beforeInteractive and onLoad as the code inside onLoad had never being executed.

Here is the sample code inside _app.tsx:

Screen Shot 2022-01-19 at 2 57 28 pm

With a simple code inside script1.js to be

console.log('loading script1.js');

And script2.js:

console.log('loading script2.js');

Then we have the output of

loading script1.js
loading script2.js
afterInteractive onLoad()

@dmudro
Copy link

dmudro commented Feb 10, 2022

ability to usebeforeInteractive with onLoad strategy is a pretty common use case with 3rd parties, i. e. cookie consent managers, analytics, etc.

a suggested solution is to execute the onLoad only on the client side instead of ignoring it - which happens now.

I can confirm the documentation is slightly confusing as it does not clarify you cannot have beforeInteractive + onLoad, it only mentions inline scripts.

@hessnd
Copy link

hessnd commented Feb 28, 2022

ability to usebeforeInteractive with onLoad strategy is a pretty common use case with 3rd parties, i. e. cookie consent managers, analytics, etc.

a suggested solution is to execute the onLoad only on the client side instead of ignoring it - which happens now.

I can confirm the documentation is slightly confusing as it does not clarify you cannot have beforeInteractive + onLoad, it only mentions inline scripts.

Is it safe to assume that using onError with beforeInteractive would also not work?

@pascuflow
Copy link

Having the problem, any solutions? I need to load two scripts in order, onLoad not working with beforeInteractive is a dealbreaker, don't want to force a refresh.

@sandruky85
Copy link

Is any progress on this? I'm having the same issue. onLoad is working only with afterInteractive.

@david-sautet
Copy link

Yes any update of this issue?
The documentation mention that OnLoad callback works with both before and after interactive stategies, but from the tests we ran, it is never called for beforeInteractive strategie.

@davidbarker
Copy link
Contributor

davidbarker commented Apr 19, 2022

I'm also facing this issue.

My use case is to load the scripts to access the Google APIs (https://accounts.google.com/gsi/client and https://apis.google.com/js/api.js). I need to run some initialization code once those scripts have loaded, however if strategy="beforeInteractive", there doesn't appear to be a way to run code once the scripts have loaded.

Additionally, as previous commenters have mentioned, the documentation made me think there was a bug as it mentions running code after a library has loaded and the immediate example underneath it loads an external Stripe script with an onLoad. It wasn't until I found this issue that I noticed the Stripe example doesn't use strategy="beforeInteractive".


In fact, reading over the documentation once again, surely this sentence is incorrect (or at least, incomplete)?

If you are loading a script with either beforeInteractive or afterInteractive as a loading strategy, you can execute code after it has loaded using the onLoad property

If this doesn't apply for external Scripts, it should probably be included in the documentation.


It gets even more confusing now I found that the API documentation for Script actually does point this out, but the Basic Features documentation (which is what I was looking at) doesn't. I've created #36261 to add this.

kodiakhq bot pushed a commit that referenced this issue Apr 19, 2022
#33097 adds a note to the `Script` documentation explaining that `onLoad` cannot be used with the `beforeInteractive` strategy. However, this note was missing in the [Basic Features](https://nextjs.org/docs/basic-features/script) documentation, causing some confusion. This adds the note there too.

This will hopefully fix a lot of confusion noted in #33191.
@housseindjirdeh
Copy link
Collaborator

Sorry for all the confusion folks.

@davidbarker you are indeed correct that the documentation is wrong.onLoad does not work when used with the beforeInteractive strategy. Thanks for creating #36261 to add a note for this, we also have #36453 in the pipeline to fix that incorrect sentence.

@jankaifer jankaifer added the please verify canary The issue should be verified against next@canary. It will be closed after 30 days of inactivity label Jan 13, 2023
@github-actions
Copy link
Contributor

Please verify that your issue can be recreated with next@canary.

Why was this issue marked with the please verify canary label?

We noticed the provided reproduction was using an older version of Next.js, instead of canary.

The canary version of Next.js ships daily and includes all features and fixes that have not been released to the stable version yet. You can think of canary as a public beta. Some issues may already be fixed in the canary version, so please verify that your issue reproduces by running npm install next@canary and test it in your project, using your reproduction steps.

If the issue does not reproduce with the canary version, then it has already been fixed and this issue can be closed.

How can I quickly verify if my issue has been fixed in canary?

The safest way is to install next@canary in your project and test it, but you can also search through closed Next.js issues for duplicates or check the Next.js releases. You can also use the GitHub template (preferred), or the CodeSandbox or StackBlitz templates to create a reproduction with canary from scratch.

My issue has been open for a long time, why do I need to verify canary now?

Next.js does not backport bug fixes to older versions of Next.js. Instead, we are trying to introduce only a minimal amount of breaking changes between major releases.

What happens if I don't verify against the canary version of Next.js?

An issue with the please verify canary that receives no meaningful activity (e.g. new comments that acknowledge verification against canary) will be automatically closed and locked after 30 days.

If your issue has not been resolved in that time and it has been closed/locked, please open a new issue, with the required reproduction, using next@canary.

I did not open this issue, but it is relevant to me, what can I do to help?

Anyone experiencing the same issue is welcome to provide a minimal reproduction following the above steps. Furthermore, you can upvote the issue using the 👍 reaction on the topmost comment (please do not comment "I have the same issue" without repro steps). Then, we can sort issues by votes to prioritize.

I think my reproduction is good enough, why aren't you looking into it quicker?

We look into every Next.js issue and constantly monitor open issues for new comments.

However, sometimes we might miss one or two due to the popularity/high traffic of the repository. We apologize, and kindly ask you to refrain from tagging core maintainers, as that will usually not result in increased priority.

Upvoting issues to show your interest will help us prioritize and address them as quickly as possible. That said, every issue is important to us, and if an issue gets closed by accident, we encourage you to open a new one linking to the old issue and we will look into it.

Useful Resources

@balazsorban44
Copy link
Member

This issue has been automatically closed because it wasn't verified against next@canary. If you think it was closed by accident, please leave a comment. If you are running into a similar issue, please open a new issue with a reproduction. Thank you.

@github-actions
Copy link
Contributor

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue was opened via the bug report template. please verify canary The issue should be verified against next@canary. It will be closed after 30 days of inactivity Script (next/script) Related to Next.js Script Optimization.
Projects
None yet
Development

No branches or pull requests