Skip to content

Commit

Permalink
Reverse engineer next/script with lazyOnLoad strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
zainfathoni committed Jul 9, 2021
1 parent e4da93e commit 3aceb74
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 2 deletions.
57 changes: 57 additions & 0 deletions components/Script.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/** Reversed engineerd from next/script
* https://github.com/vercel/next.js/blob/9f1d5d7fca55f909a3c1b60b1996e6c2124702a5/packages/next/client/script.tsx#L31
*/

import { ScriptHTMLAttributes, useEffect } from "react";
import { requestIdleCallback } from "./request-idle-callback";

const loadScript = (props: ScriptHTMLAttributes<HTMLScriptElement>): void => {
const { dangerouslySetInnerHTML } = props;

const el = document.createElement("script");

if (dangerouslySetInnerHTML) {
el.innerHTML = dangerouslySetInnerHTML.__html || "";
}

document.body.appendChild(el);
};

type RequestIdleCallbackHandle = any;
type RequestIdleCallbackOptions = {
timeout: number;
};
type RequestIdleCallbackDeadline = {
readonly didTimeout: boolean;
timeRemaining: () => number;
};

declare global {
interface Window {
requestIdleCallback: (
callback: (deadline: RequestIdleCallbackDeadline) => void,
opts?: RequestIdleCallbackOptions
) => RequestIdleCallbackHandle;
cancelIdleCallback: (handle: RequestIdleCallbackHandle) => void;
}
}

function loadLazyScript(props: ScriptHTMLAttributes<HTMLScriptElement>) {
if (document.readyState === "complete") {
requestIdleCallback(() => loadScript(props));
} else {
window.addEventListener("load", () => {
requestIdleCallback(() => loadScript(props));
});
}
}

export function Script(
props: ScriptHTMLAttributes<HTMLScriptElement>
): JSX.Element | null {
useEffect(() => {
loadLazyScript(props);
}, [props]);

return null;
}
42 changes: 42 additions & 0 deletions components/request-idle-callback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/** From https://github.com/vercel/next.js/blob/0af3b526408bae26d6b3f8cab75c4229998bf7cb/packages/next/client/request-idle-callback.ts */

type RequestIdleCallbackHandle = any;
type RequestIdleCallbackOptions = {
timeout: number;
};
type RequestIdleCallbackDeadline = {
readonly didTimeout: boolean;
timeRemaining: () => number;
};

declare global {
interface Window {
requestIdleCallback: (
callback: (deadline: RequestIdleCallbackDeadline) => void,
opts?: RequestIdleCallbackOptions
) => RequestIdleCallbackHandle;
cancelIdleCallback: (id: RequestIdleCallbackHandle) => void;
}
}

export const requestIdleCallback =
(typeof self !== "undefined" && self.requestIdleCallback) ||
function (
cb: (deadline: RequestIdleCallbackDeadline) => void
): NodeJS.Timeout {
let start = Date.now();
return setTimeout(function () {
cb({
didTimeout: false,
timeRemaining: function () {
return Math.max(0, 50 - (Date.now() - start));
},
});
}, 1);
};

export const cancelIdleCallback =
(typeof self !== "undefined" && self.cancelIdleCallback) ||
function (id: RequestIdleCallbackHandle) {
return clearTimeout(id);
};
2 changes: 1 addition & 1 deletion netlify.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
performance = 0.85
accessibility = 1
best-practices = 0.93
seo = 0.92
seo = 0.85
pwa = 0.3

[plugins.inputs]
Expand Down
3 changes: 2 additions & 1 deletion pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Head from "next/head";
import { Script } from "../components/Script";

type Props = {
html: string;
Expand All @@ -15,7 +16,7 @@ export default function Home(props: Props) {
return (
<>
<Head>
<script
<Script
dangerouslySetInnerHTML={{
__html: `(function(w,d,s,l,i){w[l] = w[l] || [];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
Expand Down

0 comments on commit 3aceb74

Please sign in to comment.