Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apollo 2 - Improvements #2171

Open
23 of 42 tasks
eric-burel opened this issue Jan 4, 2019 · 4 comments
Open
23 of 42 tasks

Apollo 2 - Improvements #2171

eric-burel opened this issue Jan 4, 2019 · 4 comments
Labels

Comments

@eric-burel
Copy link
Contributor

eric-burel commented Jan 4, 2019

Waiting for a fix in a 3rd party lib

Can't fix/improve those parts right now, would need improvements in Apollo, graphiql and GraphQL Playground.

Possible improvements

  • migrate away from Apollo Link State (not much used yet anyway) : https://www.apollographql.com/docs/react/essentials/local-state#migrating
  • deprecate webAppConnectHandlersUse patch that changes middlewares order and makes /graphql requests fail (but before that, check why we needed this patch in the first place)
  • create a callback to enhance the initial context
  • create a callback to enhance the context on every request. Right now we have a customContextFromReq option (which is not really public), but that would make more sense to use a callback
  • handle SSR errors. I've added a try/catch around renderToStringWithData, which triggers the SSR render, but the error it produces are still a bit cryptic, you can't get which component is faulty
  • Investigate apollo-link-state asynchronicity. It seems to be async, even though it calls a local cache (so I would have expected to be sync), so the returned values can be undefined even when setting a default. See withMessages for example: messages can be undefined during loading.
  • Add safeguards to avoid this issue (making introspection queries async by accident, while they must be kept sync) generateSchemaHash doesn't await execution result apollographql/apollo-server#1935
  • Create a specific vulcan:apollo package? This would make it easier for future improvements.
  • Fix withSingle / SmartForm on edit SSR is broken #2111 (Form SSR/withSingle HOC is broken)
  • integrate advanced features of vulcan:routing (options, callbacks, etc.)? Some of them are now unnecessary, to be tested
  • write. tests. many tests.
  • handle errors. For the moment if the render fails we only display an error client side. In production you'd want the error to be caught and fallback to client side rendering, with maybe a console.warn (to be discussed). In dev mode you'd like the error to print nicely. Try for example to trigger an error in the default_resolvers, it will be hard to debug.
    I've added the ErrorLink server side to Apollo client but I don't know what it should do.
    Edit: ErrorLink does not work server side (does not import), it is meant for client errors.
  • Investigate using Data Sources instead of DataLoader to pass the collection to the resolvers. We agreed that keeping the current api (context.YourCollection) for now is a good idea. We can introduce Data Sources in a next version, while keeping the current syntax as a legacy for a while, there is no emergency. Also beware, the update might be trickier as it seems as there is caching involved.
  • Using State Link is very verbose, any input welcome to simplify syntax (we should especially try to rely on a 3rd party lib for this). See withMessages for example.
  • Check server side cache. Try the example-forms, fill a new Customer but do not add an address: you'll get crappy error messages about the cache (cache.readData is not defined) + error handling is broken. Sometimes the error is correct, sometimes it's weird.
    If you add an address it will correctly save the data however.
  • WebApp (Express) middlewares can't seem to enhance the request object passed to the meteor/server-render onPageLoad callback. The middleware runs correctly, but the sink.request object is still the initial request. See Add additional details to the server-render sink object meteor/meteor-feature-requests#174 (comment) for more details (example with Cookies)

Done so far

  • Fixed user and userId in context. Now we use meteor/apollo getUser, which encapsulate the logic that was need in v1 (checking the token and so on). I noticed that sometimes the authorization header is "null" (as a String, not the null object`, because a JSON was stringified) though, this is not very clean, maybe we can improve the client part.
  • Take a look at [Resolved, but with possible security hole] Cordoba client can't access http://xx.xx.xx.xx:3000/graphql. Apollo server CORS config problem #1662 and handle CORS correctly
  • Allow to configure the server. See for example PR Allow user to customize apollo json parser options #2147 (and the relevant code in Apollo2). See registerApolloServerOptions and registerApolloApplyMiddlewareOptions methods.
  • create an Apollo client for the server (it fetches all the data it can during SSR). It relies on SchemaLink for the moment. Thus the server does not need to request himself using HTTP, it directly calls resolvers.
  • render the App as HTML server side.
  • Reenable inject_data. This allow to pass down data from the SSR rendering to the client, for example to fix Vulcan-using sites break when loaded inside archive.org #2218 by comparing the URL used during render and the client URL
  • populate the document using Helmet
  • inject the Apollo state
  • return the rendered HTML on requests
    Previously we relied on dynamicHead, that is then used by the template-web.browser.js file of _boilerplate-generator. Do we still need this? Instead I use meteor/server-render features to append content to the request body.
    This first set of features is enough to render a basic page like the getting-started first steps. Following features allow more complex usage, based on the example-forms app.
  • handle Apollo Link State server side. The stateLink API is now available client side and server side.
  • Define context of the SchemaLink, which is in turn passed to the resolvers and is necessary to actually get data.
    This context is then used in 2 places, as the context option of the server (using for each query), and as the context option of the SchemaLink (used during the initial SSR render). It is recomputed for every request.
  • Cookies. Could be improved though, as universal-cookies middleware does not seem to be taken in to account (see issue with meteor/server-render and meteor/webapp below.
  • Add auth with Cookie. On first page load, the Authorization header can't be set, so you can't authenticate. Solution is to rely on a cookie instead, and then only on the Authorization header when it is set. The cookie is updated on client startup based on the localStorage token. I uncommented existing code in auth.js and updated it, it seems fine.
  • Created a vulcan-redux package. It allows legacy app to work by simply loading this package and imporing addAction, addReducer etc. directly from there. It allowed me to test the router.xxx.wrapper callbacks.
  • router.server.wrapper: allow to wrap the App component, for example to add a Redux store. Added to AppGenerator.jsx (untested though).
  • router.client.wrapper: same but client side
  • router.server.postRender (used to injectJSS for example): now takes the sink object + context as param instead of req/res. vulcan-material-ui will need a very small update to handle this breaking change, see https://docs.meteor.com/packages/server-render.html
  • Added a vulcan:styled-components independent package
  • Other router.server.preRender, router.server.html can be safely ignored, at least for the moment. They are not used in major packages/open source Vulcan example. wrapper and postRender already provides enough flexibility to add a complex lib such as Styled Components or Redux, including SSR.
  • Fix meteor_login_token cookie issue. The cookie must be set everytime the localStorage token is updated, see auth.js
  • Allow to register custom links/terminating links (used by vulcan:files for uploading)
  • Allow disabling SSR (one the server it's a one liner, on the client we need to prevent rehydratation I think)
@SachaG
Copy link
Contributor

SachaG commented Jan 4, 2019

Pretty amazing. I feel like you've almost completely refactored Vulcan's back-end! Really excited to work with the new Apollo packages moving forward :)

@SachaG
Copy link
Contributor

SachaG commented Jan 5, 2019

Here's some notes on what I had to do to upgrade properly:

  • update apollo-client
  • update apollo-server-express
  • update graphql
  • update react-apollo
  • update react-router
  • update react-router-bootstrap
  • update body-parser
  • update express
  • npm i graphql-voyager --save-dev
  • npm i apollo-server
  • npm i apollo-cache-inmemory
  • npm i apollo-link-schema
  • npm i apollo-link-state
  • npm i apollo-link-error
  • npm i react-router-dom
  • npm i apollo-link-watched-mutation
  • npm i apollo-link-http

React Router 4

  • link is now imported from react-router-dom
  • no more props.location.query

Issues

  • tmeasday:check-npm-versions -> wrong version of apollo meteor package

@SachaG SachaG added the apollo2 label Jan 5, 2019
@eric-burel
Copy link
Contributor Author

eric-burel commented Jan 7, 2019

A few additional notes for RR4 update:

  • IndexLink no longer exists. Use <NavLink exact ... > instead
  • Link and NavLink are now imported from react-router-dom (instead of react-router)
  • Only NavLink tolerate styling, eg with activeClassName prop. Link are now simple <a> tags as a default.
  • onlyActiveOnIndex can be replaced by exact.
  • this.props.router.isActive(path) becomes matchPath(this.props.location.pathname, { path }) (matchPath is provided by react-router)

@SachaG
Copy link
Contributor

SachaG commented Jan 18, 2019

Some more issues I've noticed:

  • Event tracking is broken:
TypeError: getRenderContext is not a function
    at trackInternal (internal-client.js:6)
    at track (events.js:21)
  • queryOne/runGraphQL is broken? (Error: Expected undefined to be a GraphQL schema)
  • GraphQL errors don't appear in the terminal (only in devtools network tab)
  • i18n doesn't work for GraphQL content
  • current user is not logged in after hot code reloading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants