From ea14aa9c464e08e6e877a7b8c23a04685ff93f85 Mon Sep 17 00:00:00 2001 From: paco <34928425+pacocoursey@users.noreply.github.com> Date: Tue, 12 Mar 2024 20:40:49 -0700 Subject: [PATCH 1/3] move inline script to a separate file for free minificaiton --- examples/example/pages/dark.js | 6 +- examples/example/pages/index.js | 8 +-- examples/example/pages/light.js | 6 +- next-themes/src/index.tsx | 107 ++++++++------------------------ next-themes/src/script.ts | 61 ++++++++++++++++++ next-themes/src/types.ts | 9 ++- 6 files changed, 96 insertions(+), 101 deletions(-) create mode 100644 next-themes/src/script.ts diff --git a/examples/example/pages/dark.js b/examples/example/pages/dark.js index facac2c..ee715d6 100644 --- a/examples/example/pages/dark.js +++ b/examples/example/pages/dark.js @@ -1,11 +1,7 @@ import Link from 'next/link' const Page = () => { - return ( - - Go back home - - ) + return Go back home } Page.theme = 'dark' diff --git a/examples/example/pages/index.js b/examples/example/pages/index.js index 0b318c1..3e68f6e 100644 --- a/examples/example/pages/index.js +++ b/examples/example/pages/index.js @@ -24,13 +24,7 @@ const Index = () => {
- - Forced Dark Page - {' '} - •{' '} - - Forced Light Page - + Forced Dark Page • Forced Light Page
) diff --git a/examples/example/pages/light.js b/examples/example/pages/light.js index 2deacd6..26c6bfe 100644 --- a/examples/example/pages/light.js +++ b/examples/example/pages/light.js @@ -1,11 +1,7 @@ import Link from 'next/link' const Page = () => { - return ( - - Go back home - - ) + return Go back home } Page.theme = 'light' diff --git a/next-themes/src/index.tsx b/next-themes/src/index.tsx index eb07351..d02f61b 100644 --- a/next-themes/src/index.tsx +++ b/next-themes/src/index.tsx @@ -2,6 +2,7 @@ import * as React from 'react' import type { UseThemeProps, ThemeProviderProps } from './types' +import { script } from './script' const colorSchemes = ['light', 'dark'] const MEDIA = '(prefers-color-scheme: dark)' @@ -158,7 +159,6 @@ const Theme = ({ attribute, value, children, - attrs, nonce }} /> @@ -177,88 +177,31 @@ const ThemeScript = React.memo( enableColorScheme, defaultTheme, value, - attrs, + themes, nonce - }: ThemeProviderProps & { attrs: string[]; defaultTheme: string }) => { - const defaultSystem = defaultTheme === 'system' - - // Code-golfing the amount of characters in the script - const optimization = (() => { - if (attribute === 'class') { - const removeClasses = `c.remove(${attrs.map((t: string) => `'${t}'`).join(',')})` - - return `var d=document.documentElement,c=d.classList;${removeClasses};` - } else { - return `var d=document.documentElement,n='${attribute}',s='setAttribute';` - } - })() - - const fallbackColorScheme = (() => { - if (!enableColorScheme) { - return '' - } - - const fallback = colorSchemes.includes(defaultTheme) ? defaultTheme : null - - if (fallback) { - return `if(e==='light'||e==='dark'||!e)d.style.colorScheme=e||'${defaultTheme}'` - } else { - return `if(e==='light'||e==='dark')d.style.colorScheme=e` - } - })() - - const updateDOM = (name: string, literal: boolean = false, setColorScheme = true) => { - const resolvedName = value ? value[name] : name - const val = literal ? name + `|| ''` : `'${resolvedName}'` - let text = '' - - // MUCH faster to set colorScheme alongside HTML attribute/class - // as it only incurs 1 style recalculation rather than 2 - // This can save over 250ms of work for pages with big DOM - if (enableColorScheme && setColorScheme && !literal && colorSchemes.includes(name)) { - text += `d.style.colorScheme = '${name}';` - } - - if (attribute === 'class') { - if (literal || resolvedName) { - text += `c.add(${val})` - } else { - text += `null` - } - } else { - if (resolvedName) { - text += `d[s](n,${val})` - } - } - - return text - } - - const scriptSrc = (() => { - if (forcedTheme) { - return `!function(){${optimization}${updateDOM(forcedTheme)}}()` - } - - if (enableSystem) { - return `!function(){try{${optimization}var e=localStorage.getItem('${storageKey}');if('system'===e||(!e&&${defaultSystem})){var t='${MEDIA}',m=window.matchMedia(t);if(m.media!==t||m.matches){${updateDOM( - 'dark' - )}}else{${updateDOM('light')}}}else if(e){${ - value ? `var x=${JSON.stringify(value)};` : '' - }${updateDOM(value ? `x[e]` : 'e', true)}}${ - !defaultSystem ? `else{` + updateDOM(defaultTheme, false, false) + '}' : '' - }${fallbackColorScheme}}catch(e){}}()` - } - - return `!function(){try{${optimization}var e=localStorage.getItem('${storageKey}');if(e){${ - value ? `var x=${JSON.stringify(value)};` : '' - }${updateDOM(value ? `x[e]` : 'e', true)}}else{${updateDOM( - defaultTheme, - false, - false - )};}${fallbackColorScheme}}catch(t){}}();` - })() - - return