簡體   English   中英

如何修復 NextJS 中的暗模式背景顏色閃爍?

[英]How to fix dark mode background color flicker in NextJS?

所以我的問題是 Next.js 無法訪問客戶端的localStorage ,因此將發送 HTML 默認情況下有或沒有class="dark"

這意味着當用戶重新加載頁面時, <html>暫時沒有class="dark" ,導致 flash 的背景色為淺色,然后執行一些 javascript 並將class="dark"添加到<html> 如果我使用class="dark"運送 HTML ,則會出現同樣的問題,但反過來:然后在class="dark"<html>中刪除之前,淺色模式用戶將體驗到深色背景顏色的 flash。

有沒有辦法在頁面呈現之前執行一些 javascript ? 然后我可以根據用戶的localStorage添加或不添加class="dark"<html>

當然,將noflash.js文件添加到您的公共目錄,其中包含以下內容

(function () {
    // Change these if you use something different in your hook.
    var storageKey = 'darkMode';
    var classNameDark = 'dark-mode';
    var classNameLight = 'light-mode';

    function setClassOnDocumentBody(darkMode) {
        document.body.classList.add(darkMode ? classNameDark : classNameLight);
        document.body.classList.remove(darkMode ? classNameLight : classNameDark);
    }

    var preferDarkQuery = '(prefers-color-scheme: dark)';
    var mql = window.matchMedia(preferDarkQuery);
    var supportsColorSchemeQuery = mql.media === preferDarkQuery;
    var localStorageTheme = null;
    try {
        localStorageTheme = localStorage.getItem(storageKey);
    } catch (err) {}
    var localStorageExists = localStorageTheme !== null;
    if (localStorageExists) {
        localStorageTheme = JSON.parse(localStorageTheme);
    }

    // Determine the source of truth
    if (localStorageExists) {
        // source of truth from localStorage
        setClassOnDocumentBody(localStorageTheme);
    } else if (supportsColorSchemeQuery) {
        // source of truth from system
        setClassOnDocumentBody(mql.matches);
        localStorage.setItem(storageKey, mql.matches);
    } else {
        // source of truth from document.body
        var isDarkMode = document.body.classList.contains(classNameDark);
        localStorage.setItem(storageKey, JSON.stringify(isDarkMode));
    }
})();

// https://github.com/donavon/use-dark-mode/blob/develop/noflash.js.txt

然后,將以下script src標記添加到包含在pages/_document文件的Head class 中的返回內容中

import Document, {
    Head,
    Html,
    Main,
    NextScript,
    DocumentContext
} from 'next/document';

class MyDocument extends Document {
    static async getInitialProps(ctx: DocumentContext) {
        const initialProps = await Document.getInitialProps(ctx);
        return { ...initialProps };
    }
    render() {
        return (
            <Html lang='en-US'>
                <Head>
                    <meta charSet='utf-8' />
                    <script type="text/javascript" src='/noflash.js' />
                </Head>
                <body className='loading'>
                    <Main />
                    <NextScript />
                </body>
            </Html>
        );
    }
}

export default MyDocument;

上述方法有效,但以下方法與 Nextv10+ 完美結合。 它只需要將以下配置添加到您的根目錄 next.config.js 文件中。

next.config.js

module.exports = {
  env: {
    noflash: fs.readFileSync('/noflash.js').toString()
  }
}

然后,更改pages/_document文件中的以下腳本標記,如下所示

before

//
        <Head>
            <meta charSet='utf-8' />
            <script type="text/javascript" src='/noflash.js' />
        </Head>
//

after

//
        <Head>
            <meta charSet='utf-8' />
            <script type="text/javascript" dangerouslySetInnerHTML={{ __html: process.env.noflash}} />
        </Head>
//

鏈接到我使用第一種方法的存儲庫(從 2020 年秋季開始,在 tailwindcss 內置暗模式支持之前)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM