Gatsby集成Apollo Mutation后构建根路径静态HTML失败如何解决
问题解答
1. 报错是否和SSR有关
是。Gatsby在构建阶段会在Node.js环境预渲染所有页面的静态HTML,此时你的代码直接调用了未适配SSR环境的Apollo Mutation组件,既没有导入依赖,也没有初始化Apollo上下文,预渲染阶段直接执行失败,导致静态HTML生成报错。
2. 现有代码存在的问题
- 未导入
Mutation组件,也未初始化Apollo Client实例、未给根组件套ApolloProvider提供上下文,不管是构建阶段还是浏览器运行阶段都会报错 - 导入的
graphq拼写错误,正确应为graphql,且当前页面没有用到Gatsby静态查询,该导入可直接删除 - 使用了已不推荐的Apollo Mutation render props写法,新版Apollo Client推荐使用
useMutationHook,适配性更好
3. 正确实现步骤
3.1 安装必要依赖
npm install @apollo/client graphql cross-fetch
3.2 初始化适配SSR的Apollo Client
新建src/apollo/client.js文件:
import { ApolloClient, InMemoryCache, createHttpLink } from "@apollo/client" import fetch from "cross-fetch" // 替换为你自己的GraphQL接口地址 const GRAPHQL_API_URL = "https://your-graphql-api-endpoint.com" const httpLink = createHttpLink({ uri: GRAPHQL_API_URL, fetch, }) export const createApolloClient = () => { return new ApolloClient({ // 构建阶段为Node环境,开启SSR模式 ssrMode: typeof window === "undefined", link: httpLink, cache: new InMemoryCache(), }) }
3.3 全局注入ApolloProvider
在项目根目录新建gatsby-browser.js和gatsby-ssr.js两个文件,二者内容一致:
import React from "react" import { ApolloProvider } from "@apollo/client" import { createApolloClient } from "./src/apollo/client" const client = createApolloClient() export const wrapRootElement = ({ element }) => ( <ApolloProvider client={client}>{element}</ApolloProvider> )
3.4 改写首页代码
替换你的src/pages/index.js内容如下:
import React, { useState } from "react" import gql from "graphql-tag" import { useMutation } from "@apollo/client" const CONTACT_MUTATION = gql` mutation CreateSubmissionMutation( $clientMutationId: String! $message: String! ) { createSubmission( input: { clientMutationId: $clientMutationId message: $message } ) { success data } } ` const HomePage = () => { const [messageValue, setMessageValue] = useState("") const [createSubmission, { loading, error, data }] = useMutation(CONTACT_MUTATION) return ( <main> <form onSubmit={event => { event.preventDefault() createSubmission({ variables: { clientMutationId: "example", message: messageValue, }, }) }} > <label htmlFor="messageInput">Message: </label> <textarea id="messageInput" value={messageValue} onChange={e => setMessageValue(e.target.value)} /> <button type="submit">Send it!</button> </form> <div style={{ padding: "20px" }}> {loading && <p>Loading...</p>} {error && <p>An unknown error has occured, please try again later...</p>} {data && <p>yeah boi</p>} </div> </main> ) } export default HomePage
4. 能否使用Apollo实现该需求
完全可以,上述方案就是Gatsby项目中使用Apollo Client调用Mutation的标准实现,适配构建阶段的SSR逻辑,不会再出现静态HTML生成失败的报错。
内容的提问来源于stack exchange,提问作者Greed94
相关产品推荐
相关产品推荐

