From b13c8259b338c41ac70d08fd0423f963974dea77 Mon Sep 17 00:00:00 2001 From: Jake Jarvis Date: Thu, 6 Jul 2023 10:37:51 -0400 Subject: [PATCH] attempt to make edge functions a tad bit lighter --- components/Link/Link.tsx | 4 +- components/ThemeScript/ThemeScript.tsx | 69 ++++++++++++++------------ components/ThemeScript/client.js | 31 ++++-------- contexts/ThemeContext.tsx | 28 +++++------ lib/config/constants.ts | 13 ----- lib/config/index.js | 1 - lib/config/seo.ts | 8 +-- lib/helpers/build-feed.ts | 19 ++++--- lib/helpers/compile-note.ts | 18 +++---- lib/helpers/parse-notes.ts | 45 ++++++++++------- next.config.js | 5 +- pages/_app.tsx | 2 +- pages/_document.tsx | 4 +- pages/api/contact.ts | 3 +- pages/notes/[slug].tsx | 4 +- pages/robots.txt.ts | 3 +- pages/sitemap.xml.ts | 10 ++-- 17 files changed, 121 insertions(+), 146 deletions(-) delete mode 100644 lib/config/constants.ts diff --git a/components/Link/Link.tsx b/components/Link/Link.tsx index 06d4907d..69df65be 100644 --- a/components/Link/Link.tsx +++ b/components/Link/Link.tsx @@ -1,7 +1,6 @@ import NextLink from "next/link"; import objStr from "obj-str"; import { styled, theme, stitchesConfig } from "../../lib/styles/stitches.config"; -import { baseUrl } from "../../lib/config"; import type { ComponentProps } from "react"; const StyledLink = styled(NextLink, { @@ -43,7 +42,8 @@ const Link = ({ href, rel, target, prefetch = false, underline = true, openInNew // This component auto-detects whether or not this link should open in the same window (the default for internal // links) or a new tab (the default for external links). Defaults can be overridden with `openInNewTab={true}`. const isExternal = - typeof href === "string" && !(href.startsWith("/") || href.startsWith("#") || href.startsWith(baseUrl)); + typeof href === "string" && + !(href.startsWith("/") || href.startsWith("#") || (process.env.BASE_URL && href.startsWith(process.env.BASE_URL))); if (openInNewTab || isExternal) { return ( diff --git a/components/ThemeScript/ThemeScript.tsx b/components/ThemeScript/ThemeScript.tsx index 7fe793db..12b42ce0 100644 --- a/components/ThemeScript/ThemeScript.tsx +++ b/components/ThemeScript/ThemeScript.tsx @@ -1,51 +1,57 @@ -import { useMemo } from "react"; +import { memo } from "react"; import { minify } from "uglify-js"; -import { clientScript } from "./client"; -import { IS_DEV_SERVER } from "../../lib/config/constants"; +import type { MinifyOutput } from "uglify-js"; -export type ThemeScriptProps = JSX.IntrinsicElements["script"] & { +import { clientScript } from "./client.js"; + +export type ThemeScriptProps = { themeClassNames: { [themeName: string]: string; }; themeStorageKey: string; }; -const ThemeScript = ({ key, themeClassNames, themeStorageKey, ...rest }: ThemeScriptProps) => { - const minified = useMemo(() => { - // since the client function will end up being injected as a plain dumb string, we need to set dynamic values here: - const functionString = String(clientScript) - .replace('"__MEDIA_QUERY__"', `"(prefers-color-scheme: dark)"`) - .replace('"__STORAGE_KEY__"', `"${themeStorageKey}"`) - .replace('"__CLASS_NAMES__"', JSON.stringify(themeClassNames)); +// eslint-disable-next-line react/display-name +const ThemeScript = memo(({ themeClassNames, themeStorageKey }) => { + const minified = (() => { + // since the client function will end up being injected as a static hard-coded string, we need to determine all of + // the dynamic values within it *before* generating the final script. + const source = String(clientScript) + .replace("__MEDIA_QUERY__", "(prefers-color-scheme: dark)") + .replace("__STORAGE_KEY__", themeStorageKey) + .replace("__CLASS_NAMES__", Object.values(themeClassNames).join('","')); // turn the raw function into an iife - const unminified = `(${functionString})()`; + const unminified = `(${source})()`; - // skip minification if running locally to save a few ms - if (IS_DEV_SERVER) { + // minify the final code. this approach is a bit janky but is ONLY used at build time, so there's essentially no + // risk of breaking the entire site and/or accidentally bundling uglify-js clientside (bad). + let minified: MinifyOutput | undefined; + try { + minified = minify(unminified, { + toplevel: true, + compress: { + negate_iife: false, + }, + parse: { + bare_returns: true, + }, + }); + } catch (error) { + // fail somewhat silenty by returning the unminified version + console.warn("Failed to minify inline theme script:", error); return unminified; } - // minify the final code, a bit hacky but this is ONLY done at build-time, so uglify-js is never bundled or sent to - // the browser to execute. - const minified = minify(unminified, { - toplevel: true, - compress: { - negate_iife: false, - }, - parse: { - bare_returns: true, - }, - }); - - // fail somewhat silenty by returning the unminified version + // same as the catch block above, but in some cases (not really sure when), minify() doesn't throw an actual error + // and instead just returns undefined and an "error" string, so we need to check for both. if (!minified || minified.error) { - console.warn("Failed to minify inline theme script:", minified.error); + console.warn("Failed to minify inline theme script. uglify-js output:", minified.error); return unminified; } return minified.code; - }, [themeClassNames, themeStorageKey]); + })(); // the script tag injected manually into `` in _document.tsx to prevent FARTing: // https://css-tricks.com/flash-of-inaccurate-color-theme-fart/ @@ -54,14 +60,13 @@ const ThemeScript = ({ key, themeClassNames, themeStorageKey, ...rest }: ThemeSc // TODO: using next/script *might* be possible after https://github.com/vercel/next.js/pull/36364 is merged. return (