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

Add support for inspecting multiple clients #1418

Merged
merged 217 commits into from
Jul 22, 2024
Merged

Conversation

jerelmiller
Copy link
Member

@jerelmiller jerelmiller commented Jun 14, 2024

Fixes #822

Adds support for connecting and inspecting multiple Apollo Client instances simultaneously. This allows apps that use multiple client instances (for example with a microfrontends) to inspect the state of each of these client instances. This takes advantage of the upcoming feature in 3.11 that will enable users to name their client instance making it easy to identify which client they're inspecting.

This works with the "Explorer" tab as well. Changing clients will rerun the introspection query for that client and send GraphQL requests through that client.

Screenshot 2024-07-11 at 6 02 19 PM Screenshot 2024-07-11 at 6 02 24 PM

This PR includes a major refactor to several areas of the code base. Up to this point, much of the logic for handling messages from the hook script was handled in the devtools.ts script. That script was then responsible for syncing data to the React app running the UI. The UI used its own ApolloClient instance to sync data to the UIs, but it did so exclusively through manual cache updates in combination with the @client directive.

This PR switches to use a SchemaLink in combination with RPC calls to treat it more like client/server setup. This means we can move things like data polling to the React app. This has the added benefit that we only need to sync the data requested by a particular view. For example, we know longer need to sync all mutation data and cache data when looking at the "Queries" tab, which should be more efficient and add less strain on the running app. This is a natural result of switching to the resolver model for syncing that data.

The devtools script is now not much more than a message bus between the client port and the panel window, which drastically simplifies it. Moving forward, we'll add much more of the logic-heavy code to the React app itself, making it feel more like a traditional SPA; a pattern we are all familiar with.

@jerelmiller jerelmiller requested a review from a team as a code owner June 14, 2024 00:34
@jerelmiller jerelmiller marked this pull request as draft June 14, 2024 00:35
Copy link

relativeci bot commented Jun 14, 2024

#710 Bundle Size — 1.5MiB (+16.41%).

c653494(current) vs c223f14 main#702(baseline)

Warning

Bundle contains 13 duplicate packages – View duplicate packages

Warning

Bundle introduced 21 new packages: @xstate/react, @graphql-tools/schema, use-isomorphic-layout-effect and 18 more – View changed packages

Bundle metrics  Change 6 changes Regression 3 regressions
                 Current
#710
     Baseline
#702
Regression  Initial JS 1.46MiB(+16.88%) 1.25MiB
No change  Initial CSS 0B 0B
Change  Cache Invalidation 97.17% 2.54%
No change  Chunks 5 5
No change  Assets 12 12
Change  Modules 1216(+16.92%) 1040
Regression  Duplicate Modules 51(+4.08%) 49
Change  Duplicate Code 3.34%(-14.8%) 3.92%
Regression  Packages 182(+12.35%) 162
No change  Duplicate Packages 10 10
Bundle size by type  Change 1 change Regression 1 regression
                 Current
#710
     Baseline
#702
Regression  JS 1.46MiB (+16.88%) 1.25MiB
No change  IMG 35.85KiB 35.85KiB
No change  HTML 810B 810B
No change  Other 778B 778B

Bundle analysis reportBranch jerel/multiple-clientsProject dashboard

Copy link
Member

@phryneas phryneas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only very minor nits so far.

src/application/components/Cache/Cache.tsx Outdated Show resolved Hide resolved
src/application/App.tsx Outdated Show resolved Hide resolved

// Keep a reverse mapping of client -> id to ensure we don't register the same
// client multiple times.
const knownClients = new Map<ApolloClient<SafeAny>, string>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const knownClients = new Map<ApolloClient<SafeAny>, string>();
const knownClients = new WeakMap<ApolloClient<SafeAny>, string>();

Let's ensure that the devtools don't cause any memory leaks

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately I need to be able to traverse this map to be able to look up which client belongs to which id, otherwise it defeats the purpose of this feature.

I probably could use some combination of WeakRef and WeakSet/WeakMap for this to be able to perform some kind of iteration along with FinalizationRegistry to detect when the client has been garbage collected, but definitely a bit more complicated than it seems. How do you feel about a followup PR that does this in isolation?

@jerelmiller jerelmiller changed the base branch from main to jerel/use-query-id July 8, 2024 00:32
Base automatically changed from jerel/use-query-id to main July 10, 2024 19:47
@jerelmiller jerelmiller force-pushed the jerel/multiple-clients branch 3 times, most recently from 148ca9e to 2bb7376 Compare July 10, 2024 22:50
@jerelmiller jerelmiller changed the title [WIP] Add support for multiple clients Add support for inspecting multiple clients Jul 12, 2024
@jerelmiller jerelmiller marked this pull request as ready for review July 12, 2024 00:05
Copy link
Member

@phryneas phryneas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to have problems with older AC versions - the dropdown doesn't show up. Once that's fixed, LGTM

Comment on lines +73 to +74
useActorEvent("panelHidden", () => stopPolling());
useActorEvent("panelShown", () => startPolling(500));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could I suggest a skipPollAttempt watchQuery defaultOption? That would synchronize this even if we had it in multiple places.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will look to address this in a followup PR to avoid holding up this release. Thanks for the review!

@jerelmiller
Copy link
Member Author

Discussed over Slack, but posting here for transparency:

The issue with the older client versions wasn't a bug with the devtools, but rather because the client config updated in this PR is using the newer devtools option that will be introduced in 3.11 instead of the now-deprecated connectToDevtools option. The connectToDevtools option, when not set explicitly, will only be set to true if it doesn't detect a window.__APOLLO_CLIENT__ instance: https://github.com/apollographql/apollo-client/blob/3f6d023db2d7d6bf977060dd5db6291fd64e85e6/src/core/ApolloClient.ts#L204-L206

After downgrading and reverting back to the explicit connectToDevtools: true option, multiple clients started showing up again in the devtools.

@jerelmiller jerelmiller dismissed phryneas’s stale review July 22, 2024 20:35

Discovered non-blocking change and will address additional feedback in followup PR

@jerelmiller jerelmiller merged commit ce416bd into main Jul 22, 2024
9 checks passed
@jerelmiller jerelmiller deleted the jerel/multiple-clients branch July 22, 2024 20:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Apollo dev tools 4.0 not showing any data with multiple Apollo Clients
2 participants