1
- import ApolloClient , { createNetworkInterface } from 'apollo-client'
1
+ import 'isomorphic-unfetch'
2
+ import ApolloClient from 'apollo-client'
3
+ import { HttpLink } from 'apollo-link-http'
4
+ import { ApolloLink } from 'apollo-link'
5
+ import { InMemoryCache } from 'apollo-cache-inmemory'
2
6
import { ApolloProvider , getDataFromTree } from 'react-apollo'
3
7
import React from 'react'
4
- import { defaultProps } from 'recompose'
5
- import { createStore as createReduxStore , combineReducers , applyMiddleware } from 'redux'
6
8
7
9
let client = null
8
- let store = null
9
10
10
- const createClient = ( uri , opts ) => {
11
- const networkInterface = createNetworkInterface ( {
11
+ const getBrowserClient = ( uri , cacheOpts , initialData ) => {
12
+ const link = new HttpLink ( {
12
13
uri,
13
- opts : {
14
- credentials : 'include'
15
- }
14
+ credentials : 'include'
15
+ } )
16
+ const cache = new InMemoryCache ( cacheOpts )
17
+ if ( initialData ) {
18
+ cache . restore ( initialData )
19
+ }
20
+ return new ApolloClient ( {
21
+ link,
22
+ cache,
16
23
} )
17
- return new ApolloClient ( Object . assign ( { } , opts , {
18
- networkInterface
19
- } ) )
20
24
}
21
25
22
- const createSSRClient = ( uri , cookies , opts ) => {
23
- const networkInterface = createNetworkInterface ( {
26
+ const getServerClient = ( uri , cookies , cacheOpts ) => {
27
+ let link = new HttpLink ( {
24
28
uri
25
29
} )
26
- networkInterface . use ( [ {
27
- applyMiddleware ( req , next ) {
28
- if ( ! req . options . headers ) {
29
- req . options . headers = { }
30
- }
31
- req . options . headers [ 'Cookie' ] = Object . keys ( cookies ) . map ( key => `${ key } =${ cookies [ key ] } ` ) . join ( '; ' )
32
- next ( )
33
- }
34
- } ] )
35
- return new ApolloClient ( Object . assign ( { } , opts , {
30
+ if ( cookies && Object . keys ( cookies ) . length ) {
31
+ const middlewareLink = new ApolloLink ( ( operation , forward ) => {
32
+ operation . setContext ( {
33
+ headers : {
34
+ Cookie : Object . keys ( cookies ) . map ( key => `${ key } =${ cookies [ key ] } ` ) . join ( '; ' ) ,
35
+ } ,
36
+ } )
37
+ return forward ( operation )
38
+ } )
39
+ link = middlewareLink . concat ( link ) ;
40
+ }
41
+
42
+ const cache = new InMemoryCache ( cacheOpts )
43
+
44
+ return new ApolloClient ( {
36
45
ssrMode : true ,
37
- networkInterface
38
- } ) )
46
+ link,
47
+ cache,
48
+ } )
39
49
}
40
50
41
- const initClient = ( uri , cookies , opts ) => {
51
+ const getClient = ( uri , cookies , cacheOpts , initialData ) => {
42
52
if ( ! process . browser ) {
43
53
// on server, create a new client for each request
44
- return createSSRClient ( uri , cookies , opts )
54
+ return getServerClient ( uri , cookies , cacheOpts )
45
55
} else {
46
56
// on client, create singleton
47
57
if ( ! client ) {
48
- client = createClient ( uri , opts )
58
+ client = getBrowserClient ( uri , cacheOpts , initialData )
49
59
}
50
60
return client
51
61
}
52
62
}
53
63
54
- const createStore = ( client , initialState ) => {
55
- return createReduxStore (
56
- combineReducers ( {
57
- apollo : client . reducer ( )
58
- } ) ,
59
- initialState ,
60
- applyMiddleware ( client . middleware ( ) )
61
- )
62
- }
63
-
64
- const initStore = ( client , initialState ) => {
65
- if ( ! process . browser ) {
66
- // on server, create a new store for each request
67
- return createStore ( client , initialState )
68
- } else {
69
- // on client, create singleton
70
- if ( ! store ) {
71
- store = createStore ( client , initialState )
72
- }
73
- return store
74
- }
75
- }
76
-
77
64
module . exports = ( { url, opts} ) => {
78
65
return ( Component ) => (
79
66
class extends React . Component {
80
67
static getInitialProps ( ctx ) {
81
68
const cookies = ctx . req && ctx . req . cookies
82
- const client = initClient ( url , cookies , opts )
83
- const store = initStore ( client , client . initialState )
69
+ const client = getClient ( url , cookies , opts )
84
70
85
71
return Promise . resolve ( Component . getInitialProps ? Component . getInitialProps ( ctx ) : { } )
86
72
. then ( props => {
@@ -93,41 +79,30 @@ module.exports = ({url, opts}) => {
93
79
asPath : ctx . asPath
94
80
}
95
81
const app = (
96
- < ApolloProvider client = { client } store = { store } >
82
+ < ApolloProvider client = { client } >
97
83
< Component url = { url } { ...props } />
98
84
</ ApolloProvider >
99
85
)
100
86
return getDataFromTree ( app )
101
87
}
102
88
} )
103
89
. then ( ( ) => {
104
- const state = store . getState ( )
105
-
106
- return Object . assign ( {
107
- initialState : Object . assign (
108
- { } ,
109
- state ,
110
- {
111
- apollo : {
112
- data : client . getInitialState ( ) . data
113
- }
114
- }
115
- )
116
- } , props )
90
+ return {
91
+ initialData : client . cache . extract ( ) ,
92
+ }
117
93
} )
118
94
} )
119
95
}
120
96
121
97
constructor ( props ) {
122
98
super ( props )
123
99
// On server, this client won't be doing any work, because all work has been done in getInitialProps
124
- this . client = initClient ( url , { } , opts )
125
- this . store = initStore ( this . client , props . initialState )
100
+ this . client = getClient ( url , { } , opts , props . initialData )
126
101
}
127
102
128
103
render ( ) {
129
104
return (
130
- < ApolloProvider client = { this . client } store = { this . store } >
105
+ < ApolloProvider client = { this . client } >
131
106
< Component { ...this . props } />
132
107
</ ApolloProvider >
133
108
)
@@ -136,4 +111,4 @@ module.exports = ({url, opts}) => {
136
111
)
137
112
}
138
113
139
- module . exports . clear = ( ) => client = null
114
+ module . exports . clear = ( ) => client = null
0 commit comments