|
2 | 2 |
|
3 | 3 | // Server entry point, for Webpack. This will spawn a Koa web server |
4 | 4 | // and listen for HTTP requests. Clients will get a return render of React |
5 | | -// or the file they have requested |
6 | | -// |
7 | | -// Note: No HTTP optimisation is performed here (gzip, http/2, etc). Node.js |
8 | | -// will nearly always be slower than Nginx or an equivalent, dedicated proxy, |
9 | | -// so it's usually better to leave that stuff to a faster upstream provider |
| 5 | +// or the file they have requested. |
10 | 6 |
|
11 | 7 | // ---------------------- |
12 | 8 | // IMPORTS |
@@ -163,7 +159,7 @@ export function createReactHandler(css = [], scripts = [], chunkManifest = {}) { |
163 | 159 | // store it in our empty `route` object |
164 | 160 | const components = ( |
165 | 161 | <StaticRouter location={ctx.request.url} context={routeContext}> |
166 | | - <ApolloProvider store={ctx.store} client={ctx.apollo}> |
| 162 | + <ApolloProvider store={ctx.store} client={ctx.apollo.client}> |
167 | 163 | <App /> |
168 | 164 | </ApolloProvider> |
169 | 165 | </StaticRouter> |
@@ -269,37 +265,56 @@ const app = new Koa() |
269 | 265 | ctx.body = 'There was an error. Please try again later.'; |
270 | 266 | } |
271 | 267 | } |
272 | | - }) |
| 268 | + }); |
273 | 269 |
|
| 270 | +if (config.enableTiming) { |
274 | 271 | // It's useful to see how long a request takes to respond. Add the |
275 | 272 | // timing to a HTTP Response header |
276 | | - .use(async (ctx, next) => { |
| 273 | + app.use(async (ctx, next) => { |
277 | 274 | const start = ms.now(); |
278 | 275 | await next(); |
279 | 276 | const end = ms.parse(ms.since(start)); |
280 | 277 | const total = end.microseconds + (end.milliseconds * 1e3) + (end.seconds * 1e6); |
281 | 278 | ctx.set('Response-Time', `${total / 1e3}ms`); |
282 | | - }) |
| 279 | + }); |
| 280 | +} |
283 | 281 |
|
284 | | - // Create a new Apollo client and Redux store per request. This will be |
285 | | - // stored on the `ctx` object, making it available for the React handler or |
286 | | - // any subsequent route/middleware |
287 | | - .use(async (ctx, next) => { |
288 | | - // Create a new server Apollo client for this request |
289 | | - ctx.apollo = createClient({ |
| 282 | +// Middleware to set the per-request environment, including the Apollo client. |
| 283 | +// These can be overriden/added to in userland with `config.addBeforeMiddleware()` |
| 284 | +app.use(async (ctx, next) => { |
| 285 | + ctx.apollo = {}; |
| 286 | + return next(); |
| 287 | +}); |
| 288 | + |
| 289 | +// Add 'before' middleware that needs to be invoked before the per-request |
| 290 | +// Apollo client and Redux store has instantiated |
| 291 | +config.beforeMiddleware.forEach(middlewareFunc => app.use(middlewareFunc)); |
| 292 | + |
| 293 | +// Create a new Apollo client and Redux store per request. This will be |
| 294 | +// stored on the `ctx` object, making it available for the React handler or |
| 295 | +// any subsequent route/middleware |
| 296 | +app.use(async (ctx, next) => { |
| 297 | + // Create a new server Apollo client for this request, if we don't already |
| 298 | + // have one |
| 299 | + if (!ctx.apollo.client) { |
| 300 | + ctx.apollo.client = createClient({ |
290 | 301 | ssrMode: true, |
291 | 302 | // Create a network request. If we're running an internal server, this |
292 | 303 | // will be a function that accepts the request's context, to feed through |
293 | 304 | // to the GraphQL schema |
294 | 305 | networkInterface: createNeworkInterface(ctx), |
| 306 | + ...ctx.apollo.options, |
295 | 307 | }); |
| 308 | + } |
296 | 309 |
|
297 | | - // Create a new Redux store for this request |
298 | | - ctx.store = createNewStore(ctx.apollo); |
| 310 | + // Create a new Redux store for this request, if we don't have one |
| 311 | + if (!ctx.store) { |
| 312 | + ctx.store = createNewStore(ctx.apollo.client); |
| 313 | + } |
299 | 314 |
|
300 | | - // Pass to the next middleware in the chain: React, custom middleware, etc |
301 | | - return next(); |
302 | | - }); |
| 315 | + // Pass to the next middleware in the chain: React, custom middleware, etc |
| 316 | + return next(); |
| 317 | +}); |
303 | 318 |
|
304 | 319 | /* FORCE SSL */ |
305 | 320 |
|
|
0 commit comments