上一篇文章我们成功在 WordPress 安装 WPGraphQL plugin,启动了 GraphQL API,现在我们要来在 Next.js 部落格前端串接它,抓取文章列表资料,并呈现在首页。
这部分实作我们会参照 Next.js 官方这 2 套 sample code:
第一个 cms-wordpress 是 demo 如何在 Next.js 串接 WordPress GraphQL API,里面使用 fetch function 呼叫 GraphQL API 抓取文章资料,用来显示首页的文章列表、及文章细节页的文章内容。我们可以参考这范例里用到哪些 GraphQL 栏位,我们也将用差不多的栏位来实作各页面。
而因为第一个范例是使用单纯 fetch 函式来呼叫 GraphQL API,功能上稍嫌不足,後续若要加入更多判断或功能,像是 pagination 分页功能(一页显示 10 篇文章之类)的话,需要自己实作重造轮子,所以这部分我们会参考第二个 with-apollo 范例,改安装 apollo-client 来执行 GraphQL API call,里面就帮我们处理了很多常见功能,像是 loading state、error state、client-side cache、fetch more function 等等,让我们能用更多元的方式使用 GraphQL API。
这部分我们参照 with-apollo 范例来安装,主要安装 @apollo/client、graphql 这两个套件当作 GraphQL client,并且额外安装 deepmerge、lodash 来处理资料
yarn add @apollo/client graphql deepmerge lodash
接着新建 /lib/apolloClient.js 档案,它提供了 useApollo function,让我们等等能在整个 Next.js 专案套上 ApolloClient:
// Mainly follow this example
// https://github.com/vercel/next.js/tree/canary/examples/with-apollo
import { useMemo } from 'react'
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client'
import { concatPagination } from '@apollo/client/utilities'
import merge from 'deepmerge'
import isEqual from 'lodash/isEqual'
import { NEXT_PUBLIC_GRAPHQL_ENDPOINT } from '../constants/envValues'
export const APOLLO_STATE_PROP_NAME = '__APOLLO_STATE__'
let apolloClient
function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === 'undefined',
link: new HttpLink({
uri: NEXT_PUBLIC_GRAPHQL_ENDPOINT, // Server URL (must be absolute)
credentials: 'same-origin', // Additional fetch() options like `credentials` or `headers`
}),
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
posts: concatPagination(),
},
},
},
}),
})
}
export function initializeApollo(initialState = null) {
const _apolloClient = apolloClient ?? createApolloClient()
// If your page has Next.js data fetching methods that use Apollo Client, the initial state
// gets hydrated here
if (initialState) {
// Get existing cache, loaded during client side data fetching
const existingCache = _apolloClient.extract()
// Merge the existing cache into data passed from getStaticProps/getServerSideProps
const data = merge(initialState, existingCache, {
// combine arrays using object equality (like in sets)
arrayMerge: (destinationArray, sourceArray) => [
...sourceArray,
...destinationArray.filter((d) => sourceArray.every((s) => !isEqual(d, s))),
],
})
// Restore the cache with the merged data
_apolloClient.cache.restore(data)
}
// For SSG and SSR always create a new Apollo Client
if (typeof window === 'undefined') return _apolloClient
// Create the Apollo Client once in the client
if (!apolloClient) apolloClient = _apolloClient
return _apolloClient
}
export function addApolloState(client, pageProps) {
if (pageProps?.props) {
pageProps.props[APOLLO_STATE_PROP_NAME] = client.cache.extract()
}
return pageProps
}
export function useApollo(pageProps) {
const state = pageProps[APOLLO_STATE_PROP_NAME]
const store = useMemo(() => initializeApollo(state), [state])
return store
}
接着修改 /pages/_app.js,用刚刚的 useApollo 以及 @apollo/client package 提供的 ApolloProvider 包住整个 Next.js app,这样之後才能在各个 page 或 component 内呼叫 GraphQL API:
import { ApolloProvider } from '@apollo/client'
import { useApollo } from '../lib/apolloClient'
import '../styles/globals.css'
export default function App({ Component, pageProps }) {
const apolloClient = useApollo(pageProps)
return (
<ApolloProvider client={apolloClient}>
<Component {...pageProps} />
</ApolloProvider>
)
}
在先前的 apolloClient.js 里,建立 client 时需指定 GraphQL API endpoint,常规做法是会把路径抽成环境变数,在这个专案我把它命名成 NEXT_PUBLIC_GRAPHQL_ENDPOINT。
注意它有 NEXT_PUBLIC_ 这个前缀,这是因为我们希望这个环境变数在浏览器端也能看到,因为在後面几篇文章我们要实作分页功能时,抓取第二页的文章列表,这动作是做在 client-side 的,因此浏览器也要知道我们 API_ENDPOINT 为何。在 Next.js 就是透过前缀决定浏览器是否看得到,可参阅相关文件,类似 Create-react-app 的 REACT_APP_ 前缀
我习惯将环境变数集中到一支 JavaScript 档案,集中 export 出去,这样方便我们一眼看出专案有哪些环境变数,在这里我们建立 /constants/envValues.js:
export const NEXT_PUBLIC_GRAPHQL_ENDPOINT = process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT
再来在 Next.js local 开发过程,环境变数设定通常是用建立环境变数档方式设定的,启动 Next.js dev server 时会自动来读取特定名称的档案,通常叫做 .env.local,所以让我们建立 /.env.local,後面 endpoint 网址替换成你自己的网址,通常用 WPGraphQL 启用的话都会是在你的 WordPress domain 里的 /graphql 路径:
NEXT_PUBLIC_GRAPHQL_ENDPOINT=https://xxxxxx.mybluehost.me/graphql
到此我们成功在 Next.js 安装 ApolloClient 了,不过还没完,下一篇文章我们会继续使用刚安装的 ApolloClient 从 WordPress 抓取文章资料,在首页显示文章列表!
关於这篇文章的改动可以参考这支 commit
<<: DAY23 搞样式--CSS Gird小进阶(间隔/fr)
>>: Day9:今天来讲一下Microsoft Defender for Endpoint的装置调查
在许多网页中我们都可以看到动态变更网页内容的身影,像是我们按下一个按钮,它就会做出相对应的事情呈现在...
错误版 正确版 比对两个,发现哪里有bug了吗? 对就是,鼠标移开後,样式应该变回原本的,但它没有。...
Golang 测试 转换一下心情,来尝试看看单元测试好了 在golang上要跑测试的话,可以考虑先试...
文章写到第 25 篇,从这样的过程也稳固了自己不少观念,今天依然搅进脑汁将查找的资料尽量用自己的话写...
在 Web Component 中有些特别的 css styling 可以设定 , ex : 如果我...