From c54f3470bd5f84ea98a6de50fccd1a7aeb76fb1b Mon Sep 17 00:00:00 2001 From: arthur791004 Date: Fri, 16 Aug 2019 01:12:01 +0800 Subject: [PATCH] introduce apollo --- .env.sample | 1 + .eslintrc.js | 2 + .gitignore | 2 +- next.config.js | 9 ++ package.json | 7 ++ pages/_app.js | 33 ++++++- pages/index.js | 130 ++++++++++---------------- services/apollo/index.js | 47 ++++++++++ utils/index.js | 1 + yarn.lock | 192 ++++++++++++++++++++++++++++++++++++++- 10 files changed, 333 insertions(+), 91 deletions(-) create mode 100644 .env.sample create mode 100644 next.config.js create mode 100644 services/apollo/index.js create mode 100644 utils/index.js diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..0c6a33d --- /dev/null +++ b/.env.sample @@ -0,0 +1 @@ +GITHUB_TOKEN= \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 56a65e4..7cd35be 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -5,6 +5,7 @@ const config = { es6: true, }, globals: { + window: true, document: true, fetch: true, }, @@ -24,6 +25,7 @@ const config = { 'import/prefer-default-export': 0, 'no-else-return': 0, 'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }], + 'react/jsx-one-expression-per-line': 0, 'react/jsx-props-no-spreading': 0, 'react/jsx-wrap-multilines': [ 'error', diff --git a/.gitignore b/.gitignore index 922d92a..cea93e8 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,7 @@ # misc .DS_Store -.env* +.env # debug npm-debug.log* diff --git a/next.config.js b/next.config.js new file mode 100644 index 0000000..28d6db3 --- /dev/null +++ b/next.config.js @@ -0,0 +1,9 @@ +require('dotenv').config(); + +const config = { + env: { + GITHUB_TOKEN: process.env.GITHUB_TOKEN, + }, +}; + +module.exports = config; diff --git a/package.json b/package.json index 91c6d3c..214129c 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,13 @@ "lint-eslint": "eslint --ignore-path .gitignore" }, "dependencies": { + "@apollo/react-hooks": "~3.0.1", + "@apollo/react-ssr": "~3.0.1", + "apollo-boost": "~0.4.4", + "apollo-link-context": "~1.0.18", + "dotenv": "~8.0.0", + "graphql": "~14.4.2", + "isomorphic-unfetch": "~3.0.0", "next": "9.0.3", "react": "16.9.0", "react-dom": "16.9.0", diff --git a/pages/_app.js b/pages/_app.js index 29a6480..8d1536d 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -1,16 +1,45 @@ import React from 'react'; import App from 'next/app'; +import Head from 'next/head'; +import { ApolloProvider } from '@apollo/react-hooks'; +import { getDataFromTree } from '@apollo/react-ssr'; +import { createApolloClient } from '@/services/apollo'; import GlobalStyle from '@/components/GlobalStyle'; +const getInitialApolloState = async (AppTree, props) => { + const client = createApolloClient(); + + await getDataFromTree(); + + // getDataFromTree does not call componentWillUnmount + // head side effect therefore need to be cleared manually + Head.rewind(); + + return client.extract(); +}; + export default class MyApp extends App { + static async getInitialProps(context) { + const { AppTree } = context; + const props = App.getInitialProps ? await App.getInitialProps(context) : {}; + const apolloState = await getInitialApolloState(AppTree, props); + + return { ...props, apolloState }; + } + + constructor(props) { + super(props); + this.apolloClient = createApolloClient(props.apolloState); + } + render() { const { Component, pageProps } = this.props; return ( - <> + - + ); } } diff --git a/pages/index.js b/pages/index.js index 6599f48..93dfff3 100644 --- a/pages/index.js +++ b/pages/index.js @@ -1,91 +1,55 @@ import React from 'react'; -import Link from 'next/link'; -import Head from 'next/head'; -import Nav from '../components/nav'; +import { gql } from 'apollo-boost'; +import { useQuery } from '@apollo/react-hooks'; -const Home = () => ( -
- - Home - +const QUERY_REPOSITORIES = gql` + query repositories($type: SearchType!, $query: String!, $first: Int) { + search(type: $type, query: $query, first: $first) { + nodes { + ... on Repository { + id + nameWithOwner + description + updatedAt + url + stargazers { + totalCount + } + } + } + } + } +`; -
-); + return ( +
+ {data.search.nodes.map( + ({ id, nameWithOwner, description, updatedAt, url }) => ( +
+
{nameWithOwner}
+
{description}
+
{updatedAt}
+
{url}
+
+ ) + )} +
+ ); +}; export default Home; diff --git a/services/apollo/index.js b/services/apollo/index.js new file mode 100644 index 0000000..6ec4ac0 --- /dev/null +++ b/services/apollo/index.js @@ -0,0 +1,47 @@ +import { ApolloClient, InMemoryCache, HttpLink } from 'apollo-boost'; +import { setContext } from 'apollo-link-context'; +import fetch from 'isomorphic-unfetch'; +import { getIsBrowser } from '@/utils'; + +const GRAPHQL_URL = 'https://api.github.com/graphql'; +const isBrowser = getIsBrowser(); + +let client = null; + +const httpLink = new HttpLink({ + uri: GRAPHQL_URL, + fetch: !isBrowser && fetch, // eslint-disable-line global-require +}); + +const authLink = setContext((_, { headers }) => { + const token = process.env.GITHUB_TOKEN; + const authorization = token ? `Bearer ${token}` : ''; + + return { + headers: { + ...headers, + authorization, + }, + }; +}); + +const create = initialState => + new ApolloClient({ + ssrMode: !isBrowser, + link: authLink.concat(httpLink), + cache: new InMemoryCache().restore(initialState || {}), + }); + +export const createApolloClient = initialState => { + // create a new client for every server-side request so that data + // isn't shared between connections (which would be bad) + if (!isBrowser) { + return create(initialState); + } + + if (!client) { + client = create(initialState); // eslint-disable-line no-underscore-dangle + } + + return client; +}; diff --git a/utils/index.js b/utils/index.js new file mode 100644 index 0000000..5b0f1d1 --- /dev/null +++ b/utils/index.js @@ -0,0 +1 @@ +export const getIsBrowser = () => typeof window === 'undefined'; diff --git a/yarn.lock b/yarn.lock index 71c8a3b..4c0b6df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,30 @@ # yarn lockfile v1 +"@apollo/react-common@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@apollo/react-common/-/react-common-3.0.1.tgz#9c8f1433ddaddf80e471259126a76f1738dd4273" + dependencies: + ts-invariant "^0.4.4" + tslib "^1.10.0" + +"@apollo/react-hooks@^3.0.1", "@apollo/react-hooks@~3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@apollo/react-hooks/-/react-hooks-3.0.1.tgz#83869beddcbb06cba05d50ccf05097191d245a9c" + dependencies: + "@apollo/react-common" "^3.0.1" + "@wry/equality" "^0.1.9" + ts-invariant "^0.4.4" + tslib "^1.10.0" + +"@apollo/react-ssr@~3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@apollo/react-ssr/-/react-ssr-3.0.1.tgz#2d54182e378722314ad1b1b4b9ccfffb06a54c89" + dependencies: + "@apollo/react-common" "^3.0.1" + "@apollo/react-hooks" "^3.0.1" + tslib "^1.10.0" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" @@ -745,7 +769,7 @@ version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" -"@types/node@*": +"@types/node@*", "@types/node@>=6": version "12.7.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.2.tgz#c4e63af5e8823ce9cc3f0b34f7b998c2171f0c44" @@ -753,6 +777,10 @@ version "2.4.0" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" +"@types/zen-observable@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d" + "@webassemblyjs/ast@1.8.5": version "1.8.5" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" @@ -881,6 +909,19 @@ "@webassemblyjs/wast-parser" "1.8.5" "@xtuc/long" "4.2.2" +"@wry/context@^0.4.0": + version "0.4.4" + resolved "https://registry.yarnpkg.com/@wry/context/-/context-0.4.4.tgz#e50f5fa1d6cfaabf2977d1fda5ae91717f8815f8" + dependencies: + "@types/node" ">=6" + tslib "^1.9.3" + +"@wry/equality@^0.1.2", "@wry/equality@^0.1.9": + version "0.1.9" + resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.1.9.tgz#b13e18b7a8053c6858aa6c85b54911fb31e3a909" + dependencies: + tslib "^1.9.3" + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -1006,6 +1047,99 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" +apollo-boost@~0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/apollo-boost/-/apollo-boost-0.4.4.tgz#7c278dac6cb6fa3f2f710c56baddc6e3ae730651" + dependencies: + apollo-cache "^1.3.2" + apollo-cache-inmemory "^1.6.3" + apollo-client "^2.6.4" + apollo-link "^1.0.6" + apollo-link-error "^1.0.3" + apollo-link-http "^1.3.1" + graphql-tag "^2.4.2" + ts-invariant "^0.4.0" + tslib "^1.9.3" + +apollo-cache-inmemory@^1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.6.3.tgz#826861d20baca4abc45f7ca7a874105905b8525d" + dependencies: + apollo-cache "^1.3.2" + apollo-utilities "^1.3.2" + optimism "^0.10.0" + ts-invariant "^0.4.0" + tslib "^1.9.3" + +apollo-cache@1.3.2, apollo-cache@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.3.2.tgz#df4dce56240d6c95c613510d7e409f7214e6d26a" + dependencies: + apollo-utilities "^1.3.2" + tslib "^1.9.3" + +apollo-client@^2.6.4: + version "2.6.4" + resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.6.4.tgz#872c32927263a0d34655c5ef8a8949fbb20b6140" + dependencies: + "@types/zen-observable" "^0.8.0" + apollo-cache "1.3.2" + apollo-link "^1.0.0" + apollo-utilities "1.3.2" + symbol-observable "^1.0.2" + ts-invariant "^0.4.0" + tslib "^1.9.3" + zen-observable "^0.8.0" + +apollo-link-context@~1.0.18: + version "1.0.18" + resolved "https://registry.yarnpkg.com/apollo-link-context/-/apollo-link-context-1.0.18.tgz#9e700e3314da8ded50057fee0a18af2bfcedbfc3" + dependencies: + apollo-link "^1.2.12" + tslib "^1.9.3" + +apollo-link-error@^1.0.3: + version "1.1.11" + resolved "https://registry.yarnpkg.com/apollo-link-error/-/apollo-link-error-1.1.11.tgz#7cd363179616fb90da7866cee85cb00ee45d2f3b" + dependencies: + apollo-link "^1.2.12" + apollo-link-http-common "^0.2.14" + tslib "^1.9.3" + +apollo-link-http-common@^0.2.14: + version "0.2.14" + resolved "https://registry.yarnpkg.com/apollo-link-http-common/-/apollo-link-http-common-0.2.14.tgz#d3a195c12e00f4e311c417f121181dcc31f7d0c8" + dependencies: + apollo-link "^1.2.12" + ts-invariant "^0.4.0" + tslib "^1.9.3" + +apollo-link-http@^1.3.1: + version "1.5.15" + resolved "https://registry.yarnpkg.com/apollo-link-http/-/apollo-link-http-1.5.15.tgz#106ab23bb8997bd55965d05855736d33119652cf" + dependencies: + apollo-link "^1.2.12" + apollo-link-http-common "^0.2.14" + tslib "^1.9.3" + +apollo-link@^1.0.0, apollo-link@^1.0.6, apollo-link@^1.2.12: + version "1.2.12" + resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.12.tgz#014b514fba95f1945c38ad4c216f31bcfee68429" + dependencies: + apollo-utilities "^1.3.0" + ts-invariant "^0.4.0" + tslib "^1.9.3" + zen-observable-ts "^0.8.19" + +apollo-utilities@1.3.2, apollo-utilities@^1.3.0, apollo-utilities@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.3.2.tgz#8cbdcf8b012f664cd6cb5767f6130f5aed9115c9" + dependencies: + "@wry/equality" "^0.1.2" + fast-json-stable-stringify "^2.0.0" + ts-invariant "^0.4.0" + tslib "^1.9.3" + aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -1912,6 +2046,10 @@ domain-browser@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" +dotenv@~8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.0.0.tgz#ed310c165b4e8a97bb745b0a9d99c31bda566440" + duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" @@ -2609,6 +2747,16 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: version "1.0.1" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" +graphql-tag@^2.4.2: + version "2.10.1" + resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.1.tgz#10aa41f1cd8fae5373eaf11f1f67260a3cad5e02" + +graphql@~14.4.2: + version "14.4.2" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.4.2.tgz#553a7d546d524663eda49ed6df77577be3203ae3" + dependencies: + iterall "^1.2.2" + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -3058,6 +3206,17 @@ isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" +isomorphic-unfetch@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-unfetch/-/isomorphic-unfetch-3.0.0.tgz#de6d80abde487b17de2c400a7ef9e5ecc2efb362" + dependencies: + node-fetch "^2.2.0" + unfetch "^4.0.0" + +iterall@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7" + js-levenshtein@^1.1.3: version "1.1.6" resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" @@ -3615,7 +3774,7 @@ nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" -node-fetch@2.6.0: +node-fetch@2.6.0, node-fetch@^2.2.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" @@ -3826,6 +3985,12 @@ opencollective-postinstall@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89" +optimism@^0.10.0: + version "0.10.2" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.10.2.tgz#626b6fd28b0923de98ecb36a3fd2d3d4e5632dd9" + dependencies: + "@wry/context" "^0.4.0" + optionator@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" @@ -4907,7 +5072,7 @@ supports-color@^5.3.0, supports-color@^5.5.0: dependencies: has-flag "^3.0.0" -symbol-observable@^1.1.0: +symbol-observable@^1.0.2, symbol-observable@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" @@ -5041,7 +5206,13 @@ trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" -tslib@^1.9.0: +ts-invariant@^0.4.0, ts-invariant@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.4.4.tgz#97a523518688f93aafad01b0e80eb803eb2abd86" + dependencies: + tslib "^1.9.3" + +tslib@^1.10.0, tslib@^1.9.0, tslib@^1.9.3: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" @@ -5073,7 +5244,7 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -unfetch@4.1.0: +unfetch@4.1.0, unfetch@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.1.0.tgz#6ec2dd0de887e58a4dee83a050ded80ffc4137db" @@ -5337,3 +5508,14 @@ y18n@^4.0.0: yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" + +zen-observable-ts@^0.8.19: + version "0.8.19" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.19.tgz#c094cd20e83ddb02a11144a6e2a89706946b5694" + dependencies: + tslib "^1.9.3" + zen-observable "^0.8.0" + +zen-observable@^0.8.0: + version "0.8.14" + resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.14.tgz#d33058359d335bc0db1f0af66158b32872af3bf7"