Apollo graphqlクライアント-react.jsでの同型(ユニバーサル)アプリケーションの開発

以前の投稿では、 Apollo graphqlクライアントを使用して、純粋なクライアントアプリケーションを開発しました。 Apollo graphqlクライアントのドキュメントには、サーバーレンダリングと同形アプリケーションに関する(非常に簡潔な)セクションがあります。



react.jsでのサーバーレンダリングの課題の1つは、非同期データの読み込みの必要性です。 react.jsでのサーバーレンダリング-同期操作。 たとえば、next.jsフレームワークはこれに特別なページコンポーネントを使用することを提案します。このコンポーネントは、追加のstatic async getInitialProps()



メソッドを実装し、非同期データロードの実行を提案します。 このソリューションには欠陥がないわけではありません。 たとえば、このメソッドは静的であるため、コンポーネントインスタンスにアクセスできません。このメソッドは最上位のコンポーネントにのみ実装され、ネストされたコンポーネントには存在しません。 Apollo graphqlクライアントを使用したソリューションは、あらゆるレベルのネストのコンポーネントに使用できます。



前のメッセージで検討されたプロジェクトを引き続き使用します 。 サーバーコードには2つの重要なポイントがありますApolloProvider client={client}



コンポーネントをルート要素として使用し、 await getDataFromTree(App)



関数でデータを非同期で受信します。 ApolloProviderは、舞台裏で、選択されたルートを考慮してコンポーネントをレンダリングするために実行する必要がある要求を決定し、これらの要求を実行し、レンダリング中にコンポーネントにデータを転送します。



 ... import AppRouter from './AppRouter'; import assets from '../build/asset-manifest.json'; module.exports = async (req, res, next) => { const client = new ApolloClient({ ssrMode: true, link: createHttpLink({ uri: 'https://api.graph.cool/simple/v1/ciyz901en4j590185wkmexyex', headers: { cookie: req.header('Cookie'), }, fetch, }), cache: new InMemoryCache(), }); const context = {}; const App = <ApolloProvider client={client}> <StaticRouter location={req.url} context={context}> <AppRouter /> </StaticRouter> </ApolloProvider>; await getDataFromTree(App) const html = ReactDOMServer.renderToString((App)); const initialState = client.extract(); res.write(` <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Conduit</title> <link rel="stylesheet" href="/${assets['main.css']}"> </head> <body> <script> // WARNING: See the following for security issues around embedding JSON in HTML: // http://redux.js.org/docs/recipes/ServerRendering.html#security-considerations window.__APOLLO_STATE__ = ${JSON.stringify(initialState, null, 2).replace(/</g, '\\u003c')}; </script> <div id="app">${html}</div> <script src="/${assets['main.js']}"></script> </body> </html> `); res.end(); }
      
      







したがって、クライアント上のデータを復元するには、パラメーターをクライアントコンストラクターに渡すことによってクライアントの状態を復元する必要があります: cache: new InMemoryCache().restore(window.__APOLLO_STATE__)







 import App from './App'; import { ApolloClient } from 'apollo-client'; import { HttpLink } from 'apollo-link-http'; import { onError } from 'apollo-link-error'; import { ApolloLink } from 'apollo-link'; import { InMemoryCache } from "apollo-cache-inmemory"; const client = new ApolloClient({ link: ApolloLink.from([ onError(({ graphQLErrors, networkError }) => { if (graphQLErrors) graphQLErrors.map(({ message, locations, path }) => console.log( `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`, ), ); if (networkError) console.log(`[Network error]: ${networkError}`); }), new HttpLink({ uri: 'https://api.graph.cool/simple/v1/ciyz901en4j590185wkmexyex', // credentials: 'same-origin' }) ]), cache: new InMemoryCache().restore(window.__APOLLO_STATE__), }); hydrate(<App client={client} />, document.getElementById('app'));
      
      







この例のコードをリポジトリのssrブランチに配置しました。



したがって、Apollo graphqlクライアントを使用したサーバー側レンダリングとユニバーサルアプリケーションの実装は非常に簡潔で、純粋なクライアント側レンダリングの実装とほとんど変わりません。 grqphql APIがSSRが実装されているのと同じサーバーに実装されている場合、ネットワークを介したAPI要求を回避し(ほとんどの場合、普遍的なアプリケーションが行うように)、node.js内で直接呼び出すことで必要なgrqphql関数を要求できます。



apapacy@gmail.com

2018年5月20日。



All Articles