graphql / graphql-playground

๐ŸŽฎ GraphQL IDE for better development workflows (GraphQL Subscriptions, interactive docs & collaboration)
MIT License
8.77k stars 735 forks source link

Animating the first loading screen #250

Closed xavxyz closed 6 years ago

xavxyz commented 6 years ago

What's up?

๐Ÿ‘‹ hey there!

Awesome job on the playground folks, this is awesome!!

I've come up with a new loading flow for the Playground, thanks @schickling & @julianbauer for the design reviews! ๐ŸŽฉ

It has been made with care to:

Current state

Before opening a PR to potentially integrate it to the codebase, I'd like to see with you what should be done.

It appears that the approximately same loading screen has 3 different implementations at the moment:

So...?

Should a PR about the Loading component be targeted only at the web app or include the other packages?

If it should include the other packages:

Voilร , I'd love to help on that, and even other things! โœ‹

Prototype: https://codepen.io/xavcz/pen/bYReeM/left?editors=0010

screencast of the prototype

schickling commented 6 years ago

This is absolutely amazing @xavcz! Great work on the details. The last iteration has really improved it a lot!

does the electron app need a Loading component? It doesn't rely on a loading state at the moment and uses directly the Playground component, not App.

No, the loading component is just needed for the web version

should all render-playground-page.ts pages be unified somehow? if yes, should this page use an already bundled component to avoid loading react & react-dom from a cdn like graphiql?

@timsuchanek that's a question for you! :)

timsuchanek commented 6 years ago

Hey @xavcz, thanks for this awesome work so far! You correctly uncovered a big mess in the current loading components :D I think the main use-case besides being an electron App for the Playground is being used as a middleware.

Then we have to understand, where the loading time is actually spent:

  1. Loading the js assets / starting React
  2. Loading the schema

Mostly time is spent on loading the assets. But it would be nice if the loading screen is still there while loading and initializing the schema. 2 solutions to this: 1. only render when the schema is loader, this approach is implemented in apollo-client/server for server-side rendering. 2. first render the animation with html/css/svg only (everything served in the index.html), then continue with a React-based approach.

If the loader is implemented with styled-components, showing the loader before having the assets will be hard. Because without having react ready, we can't render the styled components. I currently see 2 ways to handle this:

  1. Use code splitting, send only what is needed for showing the animation
  2. Implementing the animation with pure html/css/svg I currently favor 2., because it's faster (we only send what is absolutely needed) and splitting code complicates the build process, that can be a huge time sink if it's broken. Implementing the html/css/svg only version, however, takes more time to implement.

We may want to load React + styled-components via cdn, that could also speed it up.

Regarding the loader mess: We should only have one place where this is implemented. We should add a package graphql-playground-middleware that includes the render-playground-page.ts and is being required by the other packages.

What are your thoughts on this?

Looking forward to awesome animations :)

xavxyz commented 6 years ago

Yay, thanks @timsuchanek: excellent explanation of the whole thing, it makes a lot of sense! ๐Ÿ‘Œ

Agree with you! Let's implement the animation in the most straightforward way for the most efficiency: loader implemented in pure html/css/svg ๐Ÿš€

But it would be nice if the loading screen is still there while loading and initializing the schema.

Yeah definitely, I believe we can get rid of the Loading component, and get React (= the Playground component when mounted?) to communicate with the node where the HTML loader is hosted.

Thus we could avoid this behavior: HTML Loader -> React Loader -> Playground

ex

We should add a package graphql-playground-middleware that includes the render-playground-page.ts and is being required by the other packages.

Let's go for all that, I'll work on a PR!

morajabi commented 6 years ago

We should add a package graphql-playground-middleware

What do you mean @timsuchanek?

xavxyz commented 6 years ago

Heads up, the fancy part of the animation, dots scaling & lines drawing, is too long to actually be seen compared to the time to load the JS! (over-engineering? ๐Ÿ˜…)

Here is another GIF, ๐Ÿค“ meh

I got this working with static html/css/svg rendered from render-playground-page.ts. That's a good solution so far!

The goal is to have a good experience, without having users to wait too long: I'll get rid of the fancy part and spread over time a short period of time the apparition of the text, rectangle & graphql logo.

We should add a package graphql-playground-middleware

As far as I understand, an export of the render-playground-page.ts file that can be re-used by Express, Koa & cie, so it's just one file to maintain instead of 4 ๐Ÿ™‚

It could may be reused as the webapp html entrypoint too, somehow? ๐Ÿค”

schickling commented 6 years ago

@xavcz note that loading these resources over the internet takes quite a bit longer, so the loading times should be "bad enough" (we could even think of deactivating the loader for localhost).

kbrandwijk commented 6 years ago

Otherwise, I would slow the loading down in favor of the animation ๐Ÿ˜„ Form before function ๐Ÿ˜‰

schickling commented 6 years ago

@xavcz can you provide a demo link for the PR so we can try it out already?

xavxyz commented 6 years ago

So here is the PR https://github.com/graphcool/graphql-playground/pull/281 ๐Ÿ‘

For a demo link, I'm having trouble to test. Let's say I want to deploy the basic example of the Express middleware. The deploy will reach NPM to get the middleware, not my local build with "linked" dependencies.

How would you do? I'm genuinely interested in the process you are using to test such things!

schickling commented 6 years ago

Yeah, this is in general a tricky topic. Here are two (hacky) ways how you could handle this (maybe someone knows a better method?):

  1. Publish your fork on NPM as @xavcz/graphql-playground
  2. Deploy your local setup to AWS Lambda via Serverless (which uploads your actual node_modules)