-
-
Save alinzk/593cbf0e79fa0a54111388a64dd9e480 to your computer and use it in GitHub Desktop.
/* | |
NOTE: This modifies next.js internal api behavior and may break your application. | |
Tested on next.js version: 9.2.1 | |
*/ | |
import React from 'react'; | |
import { compact, flatten } from 'lodash'; | |
import { NextScript } from 'next/document'; | |
class NextScriptCustom extends NextScript { | |
render() { | |
const orgNextScripts = flatten(super.render().props.children); | |
const scripts = compact( | |
orgNextScripts.map((child) => { | |
if (child.props.id === '__NEXT_DATA__') { | |
return { | |
props: { ...child.props }, | |
content: child.props.dangerouslySetInnerHTML.__html | |
}; | |
} | |
if (child?.type === 'script') { | |
return { | |
props: { ...child.props }, | |
content: '' | |
}; | |
} | |
return null; | |
}) | |
); | |
const initialFilterer = props => !props.src || !props.src.includes('chunk'); | |
const initialLoadScripts = scripts.filter(({ props }) => initialFilterer(props)); | |
const chunkedScripts = scripts.filter(({ props }) => !initialFilterer(props)); | |
const jsContent = ` | |
var chunkedScripts = ${JSON.stringify(chunkedScripts)}; | |
setTimeout(() => { | |
chunkedScripts.map((script) => { | |
if (!script || !script.props) return; | |
try { | |
var scriptTag = document.createElement('script'); | |
scriptTag.src = script.props.src; | |
scriptTag.async = script.props.async; | |
scriptTag.defer = script.props.defer; | |
if (script.props.id) scriptTag.id = script.props.id; | |
if (script.content) scriptTag.innerHTML = script.content; | |
document.body.appendChild(scriptTag); | |
} | |
catch(err) { | |
console.log(err); | |
} | |
}); | |
// 1800ms seems like when PageSpeed Insights stop waiting for more js | |
}, 1800); | |
`; | |
return ( | |
<> | |
{initialLoadScripts.map(({ props }) => ( | |
<script key={props.id} {...props} src={props.src} /> | |
))} | |
<script id="__NEXT_SCRIPT_CUSTOM" defer dangerouslySetInnerHTML={{ __html: jsContent }} /> | |
</> | |
); | |
} | |
} | |
export default NextScriptCustom; |
@anawaz42 why don't to load scripts in window.onload
instead of setTimeout of 1800ms?
Hi @kartikag01, glad to know that this helped you. And yes, it will affect user interactions, for my team we added script to enable important interactions instantly, but other stuff takes a bit of time (1800ms) as you noted in the other comment.
window.onload
can be longer than 1800ms in some cases (slow network etc.) but after multiple tests my team came up with this number that doesn't affect the UX much and also makes the page speed test happy.
Hi @anawaz42, I am getting an error props not defined in NextScriptCustom.js
I am not sure what props to pass from _document.js.
Can you share your _document.js file code ?
Hi @dipakkr, try this:
`
import React from "react";
import {compact, flatten} from "lodash";
import {NextScript} from "next/document";
class NextScriptCustom extends NextScript {
render() {
const orgNextScripts = compact(flatten(super.render().props.children));
const scripts = compact(
orgNextScripts.map((child) => {
if (child.props.id === "__NEXT_DATA__") {
return {
props: {...child.props},
content: child.props.dangerouslySetInnerHTML.__html,
};
}
if (child.type === "script") {
return {
props: {...child.props},
content: "",
};
}
return null;
}),
);
const initialFilterer = (props) => !props.src || !props.src.includes("chunk");
const initialLoadScripts = scripts.filter((item) => initialFilterer(item.props));
const chunkedScripts = scripts.filter((item) => !initialFilterer(item.props));
const jsContent = `
var chunkedScripts = ${JSON.stringify(chunkedScripts)};
setTimeout(() => {
chunkedScripts.map((script) => {
if (!script || !script.props) return;
try {
var scriptTag = document.createElement('script');
scriptTag.src = script.props.src;
scriptTag.async = script.props.async;
scriptTag.defer = script.props.defer;
if (script.props.id) scriptTag.id = script.props.id;
if (script.content) scriptTag.innerHTML = script.content;
document.body.appendChild(scriptTag);
}
catch(err) {
console.log(err);
}
});
// 1800ms seems like when PageSpeed Insights stop waiting for more js
}, 1800);
`;
return (
<>
{initialLoadScripts.map(({props}, index) => (
<script key={index} {...props} src={props.src} />
))}
<script id="__NEXT_SCRIPT_CUSTOM" defer dangerouslySetInnerHTML={{__html: jsContent}} />
</>
);
}
}
export default NextScriptCustom;
`
My version of the next.js is v9.3.5
Hi @anawaz42,
Can we add Next-AMP tag in between this code to get pass in AMP VALIDATOR online..?
Next-AMP Tags:- https://nextjs.org/docs/api-reference/next/amp
AMP Validator: - https://search.google.com/test/amp
As of now it get reported as error in AMP Validator.
Hello All,
I have been using it but found that it is been avoided by Google Insights Page Speed New Update v8.0.0.
Anyone if used and passed Google Page Speed with Good Score. Please let me know.
Hello @anawaz42,
Hope you noted above comments for AMP and Google Page Speed v8.0.0 with Next JS v11.0.0 to share your inputs for the same..!!
I am facing same errors.
Error occurred prerendering page "/nextScriptCustom". Read more: https://nextjs.org/docs/messages/prerender-error
TypeError: Cannot destructure property 'assetPrefix' of 'this.context' as it is null.
at NextScriptCustom.render (G:\Projects\ArkaSoftwares\React\arka-react.next\server\chunks\6859.js:880:17)
at NextScriptCustom.render (G:\Projects\ArkaSoftwares\React\arka-react.next\server\pages\nextScriptCustom.js:34:82)
at d (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:35:231)
at bb (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:36:16)
at a.b.render (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:42:43)
at a.b.read (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:41:83)
at Object.exports.renderToString (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:52:138)
at Object.renderPage (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\next\dist\server\render.js:686:46)
at Object.defaultGetInitialProps (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\next\dist\server\render.js:316:51)
at Function.getInitialProps (G:\Projects\ArkaSoftwares\React\arka-react.next\server\chunks\6859.js:515:20)
[== ] info - Generating static pages (182/426)
Error occurred prerendering page "/ar/nextScriptCustom". Read more: https://nextjs.org/docs/messages/prerender-error
TypeError: Cannot destructure property 'assetPrefix' of 'this.context' as it is null.
at NextScriptCustom.render (G:\Projects\ArkaSoftwares\React\arka-react.next\server\chunks\6859.js:880:17)
at NextScriptCustom.render (G:\Projects\ArkaSoftwares\React\arka-react.next\server\pages\nextScriptCustom.js:34:82)
at d (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:35:231)
at bb (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:36:16)
at a.b.render (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:42:43)
at a.b.read (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:41:83)
at Object.exports.renderToString (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:52:138)
at Object.renderPage (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\next\dist\server\render.js:686:46)
at Object.defaultGetInitialProps (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\next\dist\server\render.js:316:51)
at Function.getInitialProps (G:\Projects\ArkaSoftwares\React\arka-react.next\server\chunks\6859.js:515:20)
Error occurred prerendering page "/en/nextScriptCustom". Read more: https://nextjs.org/docs/messages/prerender-error
TypeError: Cannot destructure property 'assetPrefix' of 'this.context' as it is null.
at NextScriptCustom.render (G:\Projects\ArkaSoftwares\React\arka-react.next\server\chunks\6859.js:880:17)
at NextScriptCustom.render (G:\Projects\ArkaSoftwares\React\arka-react.next\server\pages\nextScriptCustom.js:34:82)
at d (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:35:231)
at bb (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:36:16)
at a.b.render (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:42:43)
at a.b.read (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:41:83)
at Object.exports.renderToString (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:52:138)
at Object.renderPage (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\next\dist\server\render.js:686:46)
at Object.defaultGetInitialProps (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\next\dist\server\render.js:316:51)
at Function.getInitialProps (G:\Projects\ArkaSoftwares\React\arka-react.next\server\chunks\6859.js:515:20)
info - Generating static pages (426/426)
Build error occurred
Error: Export encountered errors on following paths:
/nextScriptCustom
/nextScriptCustom: /ar/nextScriptCustom
/nextScriptCustom: /en/nextScriptCustom
at G:\Projects\ArkaSoftwares\React\arka-react\node_modules\next\dist\export\index.js:500:19
at runMicrotasks ()
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Span.traceAsyncFn (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\next\dist\trace\trace.js:74:20)
at async G:\Projects\ArkaSoftwares\React\arka-react\node_modules\next\dist\build\index.js:987:17
at async Span.traceAsyncFn (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\next\dist\trace\trace.js:74:20)
at async G:\Projects\ArkaSoftwares\React\arka-react\node_modules\next\dist\build\index.js:861:13
at async Span.traceAsyncFn (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\next\dist\trace\trace.js:74:20)
at async Object.build [as default] (G:\Projects\ArkaSoftwares\React\arka-react\node_modules\next\dist\build\index.js:82:25)
@anawaz42 this is a great solution for SSR pages, with this our page score directly goes to 95+.
Shouldn't it impact react time user performance or TTI, any idea around this?