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

Remove dependency on fast-json-stable-stringify #8222

Merged
merged 8 commits into from
May 18, 2021

Conversation

benjamn
Copy link
Member

@benjamn benjamn commented May 14, 2021

Fixes #8185, though I would say this removal is more for ESM-friendliness than for performance, as I explain below.

Note: I am expecting tests to fail for the first commit, demonstrating the importance of using a stable serialization strategy for field arguments.

Although fast-json-stable-stringify has done its job well, it only provides a "main" field in its package.json file, pointing to a CommonJS entry point, and does not appear to export any ECMAScript modules.

Thanks to our conversion/abandonment of fast-json-stable-stringify and other CommonJS-only npm dependencies (zen-observable in #5961 and graphql-tag in #6074), it should now (after this PR is merged) be possible to load @apollo/client/core from an ESM-aware CDN like jsdelivr.net or jspm.io:

<script type=module
        src="https://cdn.jsdelivr.net/npm/@apollo/client@beta/core/+esm">
</script>

If you put that script tag in an HTML file, or inject it into the DOM of any webpage, you will currently see this error:

Uncaught SyntaxError: The requested module '/npm/fast-json-stable-stringify@2.1.0/+esm' does not provide an export named 'default'

This list of errors used to be longer, but thankfully the only package left is fast-json-stable-stringify!

Note that we're loading @apollo/client/core@beta here, not @apollo/client@beta. The reason @apollo/client itself is not yet ESM-ready is that react and react-dom are unfortunately also CommonJS-only dependencies, and @apollo/client currently/regrettably re-exports utilities from @apollo/client/react. See #5541 for background on why this somewhat awkward package structure was originally necessary.

If importing from @apollo/client/core is a burden or feels weird, please know that we are planning to make @apollo/client synonymous with @apollo/client/core in Apollo Client 4.0 (see #8190), along with making @apollo/client/react synonymous with the v3 API of @apollo/client. While we think React developers will have an easy time accommodating these changes (just find/replace @apollo/client with @apollo/client/react), it's clearly a major breaking change, so it will have to wait until AC4.

> Note: I am expecting tests to fail for this commit, demonstrating the
importance of using a stable serialization strategy for field arguments.

Although fast-json-stable-stringify has done its job well, it only
provides a "main" field in its package.json file, pointing to a CommonJS
entry point, and does not appear to export any ECMAScript modules.

Thanks to our conversion/abandonment of fast-json-stable-stringify and
other CommonJS-only npm dependencies (zen-observable in #5961 and
graphql-tag in #6074), it should now (after this PR is merged) be
possible to load @apollo/client/core from an ESM-aware CDN like
jsdelivr.net or jspm.io:

  <script type=module
    src="https://cdn.jsdelivr.net/npm/@apollo/client@beta/core/+esm">
  </script>

If you put that script tag in an HTML file, or inject it into the DOM of
any webpage, you will currently see this error:

  Uncaught SyntaxError: The requested module
  '/npm/fast-json-stable-stringify@2.1.0/+esm' does not provide an
  export named 'default'

This list of errors used to be longer, but now the only package left is
fast-json-stable-stringify.

Note that we're loading @apollo/client/core@beta here, not
@apollo/client@beta. The reason @apollo/client itself is not yet
ESM-ready is that react and react-dom are the two remaining
CommonJS-only dependencies, and @apollo/client currently/regrettably
re-exports utilities from @apollo/client/react.

If importing from @apollo/client/core is a burden or feels weird to you,
please know that we are planning to make @apollo/client synonymous with
@apollo/client/core in Apollo Client 4.0, along with making
@apollo/client/react synonymous with the v3 API of @apollo/client,
though of course those will be major breaking changes:
#8190
@benjamn benjamn self-assigned this May 14, 2021
@benjamn benjamn added this to the Release 3.4 milestone May 14, 2021
@benjamn benjamn changed the title Remove dependency on fast-json-stable-stringify. Remove dependency on fast-json-stable-stringify May 14, 2021
This should fix the failing tests, though I'm planning to replace this
default implementation with a more clever one in the next commit.
This reimplementation of the stable `stringify` function used by
`getStoreKeyName` builds on the `ObjectCanon` introduced by my PR #7439,
which guarantees canonical objects keys are always in sorted order.
@benjamn benjamn marked this pull request as ready for review May 14, 2021 21:31
@benjamn benjamn requested review from hwillson and brainkim May 14, 2021 21:31
src/utilities/graphql/storeUtils.ts Outdated Show resolved Hide resolved
src/utilities/graphql/storeUtils.ts Show resolved Hide resolved
src/utilities/graphql/storeUtils.ts Outdated Show resolved Hide resolved
This reset will happen whenever cache.gc() is called, which makes sense
because it frees all memory associated with the replaced stringifyCanon,
at the cost of temporarily slowing down canonicalStringify (but without
any logical changes in the behavior/output of canonicalStringify).
@benjamn benjamn force-pushed the stop-depending-on-fast-json-stable-stringify branch from bbe2fb3 to ac74d8e Compare May 17, 2021 20:11
@benjamn
Copy link
Member Author

benjamn commented May 17, 2021

@brainkim I think I've addressed your feedback, if you (and/or @hwillson) want to take another look?

Copy link
Member

@hwillson hwillson left a comment

Choose a reason for hiding this comment

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

Looks great @benjamn! 👍

@benjamn benjamn merged commit 13fe707 into release-3.4 May 18, 2021
@benjamn benjamn deleted the stop-depending-on-fast-json-stable-stringify branch May 18, 2021 14:17
benjamn added a commit that referenced this pull request May 18, 2021
As promised in #8222 (comment),
a more general implementation of ObjectCanon is coming, so I think we
should restrict the functionality of the current implementation to match
what we have planned.

First, I want to reserve the isCanonical method to return true for
anything that doesn't need to be (further) canonized, including
primitive values. To that end, the isKnown method now returns true only
for *objects* previously returned by canon.admit.

Second, the future implemenation will allow full customization of
canonization by object prototype, but will only canonize arrays and
plain objects by default. To that end, I've resricted ObjectCanon
canonization to objects whose prototypes are Array.prototype,
Object.prototype, or null.
benjamn added a commit that referenced this pull request May 18, 2021
As promised in #8222 (comment),
a more general implementation of ObjectCanon is coming, so I think we
should restrict the functionality of the current implementation to match
what we have planned.

First, I want to reserve the isCanonical method to return true for
anything that doesn't need to be (further) canonized, including
primitive values. To that end, the isKnown method now returns true only
for *objects* previously returned by canon.admit.

Second, the future implemenation will allow full customization of
canonization by object prototype, but will only canonize arrays and
plain objects by default. To that end, I've resricted ObjectCanon
canonization to objects whose prototypes are Array.prototype,
Object.prototype, or null.
@benjamn benjamn linked an issue May 18, 2021 that may be closed by this pull request
benjamn added a commit that referenced this pull request May 25, 2021
benjamn added a commit that referenced this pull request Jun 15, 2021
Another opportunity to apply @brainkim's suggestion from this comment:
#8222 (comment)
@hwillson hwillson removed this from the MM-2021-06 milestone Jul 29, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature: Faster replacement for fast-json-stable-stringify
4 participants