You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js中useSWR+getServerSideProps+GraphQL在JS禁用时渲染异常

问题分析与解决方案

问题描述

使用Next.js的pages/api功能搭配graphql-yoga搭建GraphQL接口(地址:http://localhost:3000/api/graphql),通过mongoose获取数据。目标是结合getServerSideProps()与useSWR实现SSR页面,当前功能已实现,但在Chrome禁用JavaScript并刷新页面后,数据与CSS无法正常渲染。

问题原因

  1. SWR缓存Key不匹配:getServerSideProps中返回的fallback使用graphqlUrl作为缓存Key,但useSWR的缓存Key是booksQuery,两者不匹配。禁用JS时,SWR无法找到对应的fallback数据,导致组件停留在“Loading...”状态,无法渲染数据。
  2. CSS依赖JavaScript加载:若使用的CSS方案需要JS动态注入(如部分CSS-in-JS库、动态添加的style标签),禁用JS后CSS无法被正确加载到页面中,导致样式失效。

解决方案

1. 修正SWR Fallback的缓存Key

确保getServerSideProps中fallback的Key与useSWR的缓存Key完全一致,将Key从graphqlUrl改为booksQuery:

修改pages/index.js中的getServerSideProps:

export async function getServerSideProps() {
    const repoInfo = await fetcher(booksQuery);
    return {
        props: {
            fallback: {
                // 与useSWR的第一个参数(缓存Key)保持一致
                [booksQuery]: repoInfo
            }
        }
    };
}

2. 确保CSS在无JS环境下生效

  • 使用Next.js内置CSS支持:直接导入.css文件或CSS模块,Next.js会将CSS打包为静态资源并在HTML中直接引入,无需JS即可生效。可在pages/_app.js中全局导入全局CSS,或在组件内导入CSS模块。
  • 配置CSS-in-JS的SSR支持:若使用styled-components等CSS-in-JS库,需安装babel-plugin-styled-components并在项目配置中启用,确保服务端渲染时CSS能被正确注入到HTML中。
  • 避免动态CSS:不要通过useEffect等JS逻辑动态添加style标签,改用静态CSS或支持SSR的样式方案。

3. 优化无JS环境下的组件渲染逻辑

直接将getServerSideProps获取的初始数据传递给组件,即使SWR因禁用JS无法工作,也能直接渲染数据:

修改pages/index.js的组件部分:

export async function getServerSideProps() {
    const repoInfo = await fetcher(booksQuery);
    return {
        props: {
            initialData: repoInfo,
            fallback: {
                [booksQuery]: repoInfo
            }
        }
    };
}

function Repo({ initialData }) {
    // 使用initialData作为兜底数据
    const { data = initialData, error } = useSWR(booksQuery, fetcher, { initialData });
    if (error) return "An error has occurred.";
    // 有初始数据时直接跳过加载状态
    if (!data) return "Loading...";
    const { books } = data
    return <Home data={books} />
}

export default function Index({ initialData, fallback }) {
    return (
        <SWRConfig value={{ fallback }}>
            <Repo initialData={initialData} />
        </SWRConfig>
    )
}

内容的提问来源于stack exchange,提问作者Billy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 21:09:31