Skip to content

Commit

Permalink
Refactor experimental-script component (#24940)
Browse files Browse the repository at this point in the history
  • Loading branch information
janicklas-ralph authored May 10, 2021
1 parent 59d50ff commit 8682705
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 100 deletions.
47 changes: 9 additions & 38 deletions packages/next/client/experimental-script.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const ScriptCache = new Map()
const LoadCache = new Set()

export interface Props extends ScriptHTMLAttributes<HTMLScriptElement> {
strategy?: 'defer' | 'lazy' | 'dangerouslyBlockRendering' | 'eager'
strategy?: 'afterInteraction' | 'lazy' | 'beforeInteraction'
id?: string
onLoad?: () => void
onError?: () => void
Expand Down Expand Up @@ -93,8 +93,8 @@ const loadScript = (props: Props): void => {
}

function handleClientScriptLoad(props: Props) {
const { strategy = 'defer' } = props
if (strategy === 'defer') {
const { strategy = 'afterInteraction' } = props
if (strategy === 'afterInteraction') {
loadScript(props)
} else if (strategy === 'lazy') {
window.addEventListener('load', () => {
Expand Down Expand Up @@ -122,8 +122,7 @@ function Script(props: Props): JSX.Element | null {
src = '',
onLoad = () => {},
dangerouslySetInnerHTML,
children = '',
strategy = 'defer',
strategy = 'afterInteraction',
onError,
preload = false,
...restProps
Expand All @@ -133,7 +132,7 @@ function Script(props: Props): JSX.Element | null {
const { updateScripts, scripts } = useContext(HeadManagerContext)

useEffect(() => {
if (strategy === 'defer') {
if (strategy === 'afterInteraction') {
loadScript(props)
} else if (strategy === 'lazy') {
loadLazyScript(props)
Expand All @@ -144,42 +143,14 @@ function Script(props: Props): JSX.Element | null {
return null
}

if (strategy === 'dangerouslyBlockRendering') {
const syncProps: Props = { ...restProps }

for (const [k, value] of Object.entries({
src,
onLoad,
onError,
dangerouslySetInnerHTML,
children,
})) {
if (!value) {
continue
}
if (k === 'children') {
syncProps.dangerouslySetInnerHTML = {
__html:
typeof value === 'string'
? value
: Array.isArray(value)
? value.join('')
: '',
}
} else {
;(syncProps as any)[k] = value
}
}

return <script {...syncProps} />
} else if (strategy === 'defer') {
if (strategy === 'afterInteraction') {
if (updateScripts && preload) {
scripts.defer = (scripts.defer || []).concat([src])
scripts.afterInteraction = (scripts.afterInteraction || []).concat([src])
updateScripts(scripts)
}
} else if (strategy === 'eager') {
} else if (strategy === 'beforeInteraction') {
if (updateScripts) {
scripts.eager = (scripts.eager || []).concat([
scripts.beforeInteraction = (scripts.beforeInteraction || []).concat([
{
src,
onLoad,
Expand Down
2 changes: 1 addition & 1 deletion packages/next/next-server/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ export type DocumentProps = DocumentInitialProps & {
unstable_runtimeJS?: false
unstable_JsPreload?: false
devOnlyCacheBusterQueryString: string
scriptLoader: { defer?: string[]; eager?: any[] }
scriptLoader: { afterInteraction?: string[]; beforeInteraction?: any[] }
locale?: string
}

Expand Down
40 changes: 23 additions & 17 deletions packages/next/pages/_document.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ export class Head extends Component<
})

return [
...(scriptLoader.eager || []).map((file) => (
...(scriptLoader.beforeInteraction || []).map((file) => (
<link
key={file.src}
nonce={this.props.nonce}
Expand All @@ -282,7 +282,7 @@ export class Head extends Component<
}
/>
)),
...(scriptLoader.defer || []).map((file: string) => (
...(scriptLoader.afterInteraction || []).map((file: string) => (
<link
key={file}
nonce={this.props.nonce}
Expand All @@ -304,14 +304,18 @@ export class Head extends Component<

React.Children.forEach(children, (child: any) => {
if (child.type === Script) {
if (child.props.strategy === 'eager') {
scriptLoader.eager = (scriptLoader.eager || []).concat([
if (child.props.strategy === 'beforeInteraction') {
scriptLoader.beforeInteraction = (
scriptLoader.beforeInteraction || []
).concat([
{
...child.props,
},
])
return
} else if (['lazy', 'defer'].includes(child.props.strategy)) {
} else if (
['lazy', 'afterInteraction'].includes(child.props.strategy)
) {
scriptLoaderItems.push(child.props)
return
}
Expand Down Expand Up @@ -664,18 +668,20 @@ export class NextScript extends Component<OriginProps> {
getPreNextScripts() {
const { scriptLoader } = this.context

return (scriptLoader.eager || []).map((file: ScriptLoaderProps) => {
const { strategy, ...props } = file
return (
<script
{...props}
nonce={this.props.nonce}
crossOrigin={
this.props.crossOrigin || process.env.__NEXT_CROSS_ORIGIN
}
/>
)
})
return (scriptLoader.beforeInteraction || []).map(
(file: ScriptLoaderProps) => {
const { strategy, ...props } = file
return (
<script
{...props}
nonce={this.props.nonce}
crossOrigin={
this.props.crossOrigin || process.env.__NEXT_CROSS_ORIGIN
}
/>
)
}
)
}

getScripts(files: DocumentFiles) {
Expand Down
12 changes: 6 additions & 6 deletions test/integration/script-loader/pages/_document.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ export default class MyDocument extends Document {
href="https://fonts.googleapis.com/css?family=Voces"
/>
<Script
id="documentDefer"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=documentDefer"
strategy="defer"
id="documentAfterInteraction"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=documentAfterInteraction"
strategy="afterInteraction"
></Script>
<Script
id="documentLazy"
Expand All @@ -36,9 +36,9 @@ export default class MyDocument extends Document {
strategy="dangerouslyBlockRendering"
></Script>
<Script
id="documentEager"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=documentEager"
strategy="eager"
id="documentBeforeInteraction"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=documentBeforeInteraction"
strategy="beforeInteraction"
></Script>
</Head>
<body>
Expand Down
4 changes: 2 additions & 2 deletions test/integration/script-loader/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ const Page = () => {
return (
<div class="container">
<Script
id="scriptDefer"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptDefer"
id="scriptAfterInteraction"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptAfterInteraction"
preload
></Script>
<div>index</div>
Expand Down
6 changes: 3 additions & 3 deletions test/integration/script-loader/pages/page1.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ const Page = () => {
return (
<div class="container">
<Script
id="scriptEager"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptEager"
strategy="eager"
id="scriptBeforeInteraction"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteraction"
strategy="beforeInteraction"
></Script>
<div>page1</div>
</div>
Expand Down
16 changes: 0 additions & 16 deletions test/integration/script-loader/pages/page2.js

This file was deleted.

25 changes: 8 additions & 17 deletions test/integration/script-loader/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('Script Loader', () => {
stopApp(server)
})

it('priority defer', async () => {
it('priority afterInteraction', async () => {
let browser
try {
browser = await webdriver(appPort, '/')
Expand All @@ -58,10 +58,10 @@ describe('Script Loader', () => {
expect(endPreloads.length).toBe(0)
}

// Defer script in page
await test('scriptDefer')
// Defer script in _document
await test('documentDefer')
// afterInteraction script in page
await test('scriptAfterInteraction')
// afterInteraction script in _document
await test('documentAfterInteraction')
} finally {
if (browser) await browser.close()
}
Expand Down Expand Up @@ -96,7 +96,7 @@ describe('Script Loader', () => {
}
})

it('priority eager', async () => {
it('priority beforeInteraction', async () => {
const html = await renderViaHTTP(appPort, '/page1')
const $ = cheerio.load(html)

Expand Down Expand Up @@ -130,17 +130,8 @@ describe('Script Loader', () => {
).toBeGreaterThan(0)
}

test('scriptEager')
test('documentEager')
})

it('priority dangerouslyBlockRendering', async () => {
const html = await renderViaHTTP(appPort, '/page2')
const $ = cheerio.load(html)

// Script is inserted in place
expect($('.container #scriptBlock').length).toBeGreaterThan(0)
expect($('head #documentBlock').length).toBeGreaterThan(0)
test('scriptBeforeInteraction')
test('documentBeforeInteraction')
})

it('onload fires correctly', async () => {
Expand Down

0 comments on commit 8682705

Please sign in to comment.