fix: <Script> with beforeInteractive strategy ignores additional attributes in App Router (#59779)

### What?

Currently, `next/script` in the App Router does not behave as the docs
describe in the [Additional
Attributes](https://nextjs.org/docs/app/building-your-application/optimizing/scripts#additional-attributes)
section – it does not pass on all additional attributes when
`strategy="beforeInteractive"`
([#49830](https://github.com/vercel/next.js/issues/49830)).

### Why?

The props from the `<Script>` component were not passed on to the
underlying script loader (`self.__next_s`).

### How?

I've added the missing props to the object that is `push`ed to
`self.__next_s`.

NEXT-1304
Fixes #49830
This commit is contained in:
Zane Bauman 2024-01-03 14:48:55 -05:00 committed by GitHub
parent df16698a8c
commit 37a09891f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 1 deletions

View file

@ -334,7 +334,7 @@ function Script(props: ScriptProps): JSX.Element | null {
dangerouslySetInnerHTML={{
__html: `(self.__next_s=self.__next_s||[]).push(${JSON.stringify([
0,
{ ...restProps },
{ ...restProps, id },
])})`,
}}
/>
@ -353,6 +353,7 @@ function Script(props: ScriptProps): JSX.Element | null {
dangerouslySetInnerHTML={{
__html: `(self.__next_s=self.__next_s||[]).push(${JSON.stringify([
src,
{ ...restProps, id },
])})`,
}}
/>

View file

@ -33,6 +33,22 @@ export default function Page() {
`,
}}
/>
<Script
strategy="beforeInteractive"
src="/noop-test.js"
id="script-with-src-noop-test"
data-extra-prop="script-with-src"
/>
<Script
strategy="beforeInteractive"
dangerouslySetInnerHTML={{
__html: `
console.log('noop-test-dangerouslySetInnerHTML')
`,
}}
id="script-without-src-noop-test-dangerouslySetInnerHTML"
data-extra-prop="script-without-src"
/>
</div>
)
}

View file

@ -1751,6 +1751,26 @@ createNextDescribe(
return 'yes'
}, 'yes')
})
it('should pass on extra props for beforeInteractive scripts with a src prop', async () => {
const browser = await next.browser('/script')
const foundProps = await browser.eval(
`document.querySelector('#script-with-src-noop-test').getAttribute('data-extra-prop')`
)
expect(foundProps).toBe('script-with-src')
})
it('should pass on extra props for beforeInteractive scripts without a src prop', async () => {
const browser = await next.browser('/script')
const foundProps = await browser.eval(
`document.querySelector('#script-without-src-noop-test-dangerouslySetInnerHTML').getAttribute('data-extra-prop')`
)
expect(foundProps).toBe('script-without-src')
})
}
it('should insert preload tags for beforeInteractive and afterInteractive scripts', async () => {

View file

@ -0,0 +1 @@
console.log('test-noop')