OneGraph / graphiql-explorer

Explorer plugin for GraphiQL
MIT License
907 stars 97 forks source link

Ability to use explorer without build step #29

Open matystl opened 5 years ago

matystl commented 5 years ago

We are currently using graphiql without build step. We have dynamic django template generating customized html that import libs from cdn.jsdelivr.net. I try to add graphiql-explorer but had problem with error:

react-dom.production.min.js:117 Error: Cannot use GraphQLNonNull "[attack!]!" from another module or realm.

Ensure that there is only one instance of "graphql" in the node_modules
directory. If different versions of "graphql" are the dependencies of other
relied on modules, use "resolutions" to ensure only one version is installed.
...

Maybe i am doing something wrong or it is not possible. At end is example HTML reproducing error. In that example i let let graphiql do introspection and just set schema from it to graphiql-explorer. In example graphiql-explorer-example i see that maybe i need to use graphql as dependency and do introspection schema by it but looking at build of graphql@14.5.8 i dont see anything published that i can use without build step.

Here is simple html that reproduce error just open it and see console for error.

<!DOCTYPE html>
<html>
  <head>
    <style>
      html,
      body {
        height: 100%;
        margin: 0;
        overflow: hidden;
        width: 100%;
      }

      #graphiql {
        height: 100vh;
      }
    </style>
    <link
      href="https://cdn.jsdelivr.net/npm/graphiql@0.12.0/graphiql.css"
      rel="stylesheet"
      crossorigin="anonymous"
    />
    <script
      src="https://cdn.jsdelivr.net/npm/whatwg-fetch@2.0.3/fetch.min.js"
      integrity="sha384-dcF7KoWRaRpjcNbVPUFgatYgAijf8DqW6NWuqLdfB5Sb4Cdbb8iHX7bHsl9YhpKa"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://cdn.jsdelivr.net/npm/react@16.8.6/umd/react.production.min.js"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://cdn.jsdelivr.net/npm/react-dom@16.8.6/umd/react-dom.production.min.js"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://cdn.jsdelivr.net/npm/graphiql@0.12.0/graphiql.min.js"
      crossorigin="anonymous"
    ></script>
    <script
      src="https://cdn.jsdelivr.net/npm/graphiql-explorer@0.4.5/graphiqlExplorer.min.js"
      crossorigin="anonymous"
    ></script>
  </head>
  <body>
    <div id="graphiql"></div>

    <script>
      var parameters = {};

      var fetchURL = "https://graphql-pokemon.now.sh/";

      // Defines a GraphQL fetcher using the fetch API.
      function graphQLFetcher(graphQLParams) {
        var headers = {
          Accept: "application/json",
          "Content-Type": "application/json"
        };

        return fetch(fetchURL, {
          method: "post",
          headers: headers,
          body: JSON.stringify(graphQLParams)
        })
          .then(function(response) {
            return response.text();
          })
          .then(function(responseBody) {
            try {
              return JSON.parse(responseBody);
            } catch (error) {
              return responseBody;
            }
          });
      }

      function onEditQuery(newQuery) {
        parameters.query = newQuery;
      }

      function AppComponent() {
        var state = React.useState(undefined);
        var schema = state[0];
        var setSchema = state[1];
        window.setSchema = setSchema;

        return React.createElement(
          "div",
          { style: { height: "100%", display: "flex" } },
          [
            React.createElement(
              "div",
              { style: { width: "300px" } },
              React.createElement(GraphiQLExplorer.Explorer, {
                query: parameters.query,
                onEdit: onEditQuery,
                explorerIsOpen: true,
                schema: schema
              })
            ),
            React.createElement(GraphiQL, {
              fetcher: graphQLFetcher,
              onEditQuery: onEditQuery,
              query: parameters.query,
              ref: function(ref) {
                window._graphiql = ref;
              }
            })
          ]
        );
      }

      // Render <GraphiQL /> into the body.
      ReactDOM.render(
        React.createElement(AppComponent),
        document.getElementById("graphiql")
      );

      function trySetSchemaFromGraphiqlToGraphiqlExplorer() {
        setTimeout(function() {
          if (
            window._graphiql &&
            window._graphiql.state &&
            window._graphiql.state.schema
          ) {
            window.setSchema(window._graphiql.state.schema);
          } else {
            trySetSchemaFromGraphiqlToGraphiqlExplorer();
          }
        }, 500);
      }
      trySetSchemaFromGraphiqlToGraphiqlExplorer();
    </script>
  </body>
</html>
pavelloz commented 4 years ago

Yeah, I'm also banging my head against the wall using both example in this repo and graphiql-with-extensions. No positive results.

I managed to build everything with webpack on my own, but after seeing 1500 errors from fetch, react, babel plugins I gave up.

matystl commented 4 years ago

@pavelloz You should probably look at https://github.com/OneGraph/graphiql-with-extensions for temporary solution. Here are snippets of imports you want to put inside head of static html

<link href="https://cdn.jsdelivr.net/npm/graphiql-with-extensions@0.14.3/graphiqlWithExtensions.css" rel="stylesheet" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/whatwg-fetch@2.0.3/fetch.min.js" integrity="sha384-dcF7KoWRaRpjcNbVPUFgatYgAijf8DqW6NWuqLdfB5Sb4Cdbb8iHX7bHsl9YhpKa" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/react@16.8.6/umd/react.production.min.js" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/react-dom@16.8.6/umd/react-dom.production.min.js" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/graphiql-with-extensions@0.14.3/graphiqlWithExtensions.min.js" crossorigin="anonymous"></script>

Add some fetcher, optionaly additional things like kee query in url, maybe keep authorization in cookies/localstorage according to your curent app needs

And than render graphiql like this

    // Render <GraphiQL /> into the body.
    ReactDOM.render(
        React.createElement(GraphiQLWithExtensions.GraphiQLWithExtensions, options),
        document.getElementById('graphiql')
    );

And then from server just serve on some url this static html

pavelloz commented 4 years ago

I decided to start from scratch and slowly but surely managed to make it with webpack build process. ( https://github.com/mdyd-dev/pos-cli/commit/75fc1f76b121d2ebee06c83a717ee2de4a0bf8db )

Maybe ill prepare a separate repo that will examplify how it can be done with current versions of everything, with minimal setup (i think i used some babel plugins that are not necessary still).

On purpose i did not extract CSS from the bundle, so @matystl if you want to use this setup, just change url of graphql endpoint, build it, and it should all work within one file.

pavelloz commented 4 years ago

BTW. I wasted a lot of time at https://github.com/mdyd-dev/pos-cli/commit/75fc1f76b121d2ebee06c83a717ee2de4a0bf8db#diff-cca83a6ca2f8c9cd99cae2d38cdfbba6R51 (or in your repo https://github.com/OneGraph/graphiql-with-extensions/blob/master/src/GraphiQLWithExtensions.js#L7 )

Because (i think) babel couldnt understand _graphiql: GraphiQL so i dig out React docs about components lifecycle, used constructor and it clicked. I thought babel-plugin-transform-class-properties was responsible for handling that, but apparently i was wrong.

Also https://github.com/OneGraph/graphiql-with-extensions/blob/master/src/GraphiQLWithExtensions.js#L21-L25

this seems to not work at all. There is no getQueryEditor() method on graphiql instance, at least not in modern one (im using current version).

matystl commented 4 years ago

I extracted (and simplified) our current set up and added it as example here https://github.com/OneGraph/graphiql-with-extensions/pull/7/files

pavelloz commented 4 years ago

Thats a good move.

Although as i mentioned above, GraphiQL version in the example is old (0.14, form August 2019), current one (0.17.5 - 9 December 2019) has different public API in some cases, so it would be probably a good idea to promote newest and greatest. Having said that - i dont know if just changing the numbers in cdnjs links wouldnt solve that issue.

I tried to do in the link i pasted above, but couldnt recreate all the features.

Poggen commented 4 years ago

Is this on the roadmap at all?

pavelloz commented 4 years ago

This is how i managed to use newest react, graphiql and explorer (with webpack, because i dont mind build step, but you can just build it once and leave dist files).

https://github.com/mdyd-dev/pos-cli/commit/75fc1f76b121d2ebee06c83a717ee2de4a0bf8db

Maybe it will save you some time. It should be easy enough to extract it to a separate npm package for reusability.