Skip to content

Commit

Permalink
Delay Apollo Client initialization in browser tabs until needed
Browse files Browse the repository at this point in the history
Apollo Client and its associated dependencies do not need to load
on each browser tab, if the Apollo Client Devtools extension is
not being used. These changes avoid loading / initializing AC
and its deps, until they are really needed.

This is ultimately a better fix for #457, which was being caused
by Apollo Client's dependency `ts-invariant` being loaded
when the devtools were initialized, even though they weren't
being used on certain sites.
  • Loading branch information
hwillson committed Mar 26, 2021
1 parent e103584 commit b3b37f7
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 67 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

- Make sure null and boolean values are rendered properly in the Cache tree. <br/>
[@alexTayanovsky](https://github.com/alexTayanovsky) in [#446](https://github.com/apollographql/apollo-client-devtools/pull/446)
- Delay the loading / initialization of Apollo Client on each browser tab until it is really needed. <br/>
[@hwillson](https://github.com/apollographql/apollo-client-devtools) in [#479](https://github.com/apollographql/apollo-client-devtools/pull/479)

## 3.0.2 (2021-03-17)

Expand Down
133 changes: 77 additions & 56 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"postinstall": "cd node_modules/graphiql-forked/packages/graphiql && npm install --production"
},
"dependencies": {
"@apollo/client": "^3.4.0-beta.15",
"@apollo/client": "^3.3.13",
"@apollo/space-kit": "^9.0.1-canary.317.8374.0",
"@emotion/cache": "^11.1.3",
"@emotion/react": "^11.1.5",
Expand All @@ -37,12 +37,14 @@
"graphiql-forked": "https://github.com/apollographql/graphiql",
"graphql": "^15.5.0",
"graphql-syntax-highlighter-react": "^0.4.0",
"graphql-tag": "^2.11.0",
"polished": "^4.1.1",
"react": "^17.0.1",
"react-copy-to-clipboard": "^5.0.3",
"react-dom": "^17.0.1",
"react-json-tree": "^0.15.0",
"stringify-object": "^3.3.0"
"stringify-object": "^3.3.0",
"zen-observable": "^0.8.15"
},
"devDependencies": {
"@emotion/jest": "11.2.1",
Expand Down
49 changes: 43 additions & 6 deletions src/extension/tab/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { DocumentNode, Source } from "graphql";
import {
DocumentNode,
Source,
OperationDefinitionNode,
FragmentDefinitionNode,
} from "graphql/language";

export type QueryInfo = {
document: DocumentNode;
Expand All @@ -11,13 +16,13 @@ export function getQueries(queryMap): QueryInfo[] {
let queries: QueryInfo[] = [];

if (queryMap) {
queries = [...queryMap.values()].map(({
document,
queries = [...queryMap.values()].map(({
document,
variables,
diff,
}) => ({
document,
source: document?.loc?.source,
source: document?.loc?.source,
variables,
cachedData: diff?.result,
})
Expand All @@ -39,7 +44,39 @@ export function getMutations(mutationsObj): QueryInfo[] {
return {
document: mutation,
variables,
source: mutation?.loc?.source,
source: mutation?.loc?.source,
}
});
}
}

export function getMainDefinition(
queryDoc: DocumentNode
): OperationDefinitionNode | FragmentDefinitionNode {
let fragmentDefinition;

for (let definition of queryDoc.definitions) {
if (definition.kind === "OperationDefinition") {
const operation = (definition as OperationDefinitionNode).operation;
if (
operation === "query" ||
operation === "mutation" ||
operation === "subscription"
) {
return definition as OperationDefinitionNode;
}
}
if (definition.kind === "FragmentDefinition" && !fragmentDefinition) {
// we do this because we want to allow multiple fragment definitions
// to precede an operation definition.
fragmentDefinition = definition as FragmentDefinitionNode;
}
}

if (fragmentDefinition) {
return fragmentDefinition;
}

throw new Error(
"Expected a parsed GraphQL query with a query, mutation, subscription, or a fragment."
);
}
17 changes: 14 additions & 3 deletions src/extension/tab/hook.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import { gql, Observable, ApolloClient } from "@apollo/client";
import type { ApolloClient } from "@apollo/client";

// Note that we are intentionally not using Apollo Client's gql and
// Observable exports, as we don't want Apollo Client and its dependencies
// to be loaded into each browser tab, when this hook triggered.
import gql from "graphql-tag";
import Observable from "zen-observable";
import { OperationDefinitionNode } from "graphql/language";
import { getMainDefinition } from "@apollo/client/utilities";

import { version as devtoolsVersion } from "../manifest.json";
import Relay from "../../Relay";
import { QueryInfo, getQueries, getMutations } from "./helpers";
import {
QueryInfo,
getQueries,
getMutations,
getMainDefinition,
} from "./helpers";
import { GraphiQLResponse, QueryResult } from '../../types';
import {
CLIENT_FOUND,
Expand Down

0 comments on commit b3b37f7

Please sign in to comment.