-
Notifications
You must be signed in to change notification settings - Fork 466
Feature/#1308 query enqueued assets as connections #1313
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
Merged
jasonbahl
merged 25 commits into
wp-graphql:develop
from
jasonbahl:feature/#1308-query-enqueued-assets-as-connections
May 19, 2020
Merged
Feature/#1308 query enqueued assets as connections #1313
jasonbahl
merged 25 commits into
wp-graphql:develop
from
jasonbahl:feature/#1308-query-enqueued-assets-as-connections
May 19, 2020
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This reverts commit b13aa2a.
This reverts commit 2dd87cf.
- This adds an `EnqueuedAsset` Interface, and an `EnqueuedScript` Type and `EnqueuedStylesheet` Type to the Schema. - This adds connections from `ContentNode->EnqueuedScript`, `TermNode->EnqueuedScript` and `User->EnqueuedScript` - This adds heaps of tests to make sure scripts can be queried in various contexts and work properly - The model layer has been given some adjustments to make sure global state is setup properly during GraphQL Execution so that conditionals will work properly here
…p-graphql#1308-query-enqueued-assets-as-connections # Conflicts: # src/Model/Post.php # src/Type/Object/PostObject.php # tests/wpunit/TypesTest.php # vendor/autoload.php # vendor/composer/autoload_commands_real.php # vendor/composer/autoload_framework_real.php # vendor/composer/autoload_real.php # vendor/composer/autoload_static.php
- Convert node resolver to use the loader and load_deferred method - removed `taxonomyNames` field from ContentType type - converted `connectedTaxonomies` field on ContentType to a formal connection
… other register_type methods `( $type_name, $config )` - added phpstan (doesn't run during Github workflows yet, but can be used locally by developers to catch issues. Some need to be worked out still) - updated `require_once` statements for plugin.php
…p-graphql#1308-query-enqueued-assets-as-connections
…the type properly
Codecov Report
@@ Coverage Diff @@
## develop #1313 +/- ##
===========================================
- Coverage 63.62% 62.61% -1.02%
===========================================
Files 166 181 +15
Lines 9540 10153 +613
===========================================
+ Hits 6070 6357 +287
- Misses 3470 3796 +326
Continue to review full report at Codecov.
|
Merged
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This Pull Request adds connections for enqueued assets (scripts and stylesheets) to the Graph.
Querying Enqueued Scripts and Stylesheets as Connections
When enqueueing assets to WordPress, the enqueued asset can be considered a connection to the nodes it is enqueued to.
Enqueue the assets
For example, enqueuing a script to just pages like so:
This will add the
/path/to/page-script.js' and/path/to/page-styles.css' files to any Page of the "page" post type in the front-end of WordPress, but nowhere else. Templates for tag archives, for example, would not have this CSS or JS added.Often times content (that can be queried for headlessly) relies on these scripts (and styles). For example unordered lists that are converted to Slideshows or Lightbox galleries, etc.
Query the assets as connections
With this Pull Request, these enqueued assets will be able to be queried in GraphQL as connected nodes like so:
{ pages(first: 1) { nodes { id title enqueuedScripts { nodes { id handle src } } enqueuedStylesheets { nodes { id handle src } } } } }Get the connected assets in response
This would return a payload like (any other scripts and styles enqueued to pages would also be included):
{ "data": { "pages": { "nodes": [ { "id": "cG9zdDo1MzU=", "title": "Page One", "enqueuedScripts": { "nodes": [ { "id": "ZW5xdWV1ZWRfc2NyaXB0Om15LXNjcmlwdC1mb3ItcGFnZXM=", "handle": "my-script-for-pages", "src": "/path/to/page-script.js" } ] }, "enqueuedStylesheets": { "nodes": [ { "id": "ZW5xdWV1ZWRfc3R5bGVzaGVldDpteS1zdHlsZXMtZm9yLXBhZ2Vz", "handle": "my-styles-for-pages", "src": "/path/to/page-style.css" }, ] } } ] } }This allows for external sources that are consuming WordPress content over GraphQL to make use of associated styles and scripts that may compliment the content. This could, in theory, allow for external consumers such as Gatsby, Next, Gridsome, etc to work with Gutenberg or other Page Builders!
Root Queries
This also allows for assets to be queried from the root of the graph, like so:
{ registeredScripts { nodes { id handle src } } }And get a payload like so:
{ "data": { "registeredScripts": { "nodes": [ { "id": "ZW5xdWV1ZWRfc2NyaXB0OnV0aWxz", "handle": "utils", "src": "/wp-includes/js/utils.min.js" }, { "id": "ZW5xdWV1ZWRfc2NyaXB0OmNvbW1vbg==", "handle": "common", "src": "/wp-admin/js/common.min.js" }, { "id": "ZW5xdWV1ZWRfc2NyaXB0OndwLXNhbml0aXpl", "handle": "wp-sanitize", "src": "/wp-includes/js/wp-sanitize.min.js" }, ] } } }Additionally, we can take an ID of a resource and get it from a
nodequery like so:{ node(id: "ZW5xdWV1ZWRfc2NyaXB0OndwLXNhbml0aXpl") { __typename ... on EnqueuedAsset { handle src } } }And get a payload like so:
{ "data": { "node": { "__typename": "EnqueuedScript", "handle": "wp-sanitize", "src": "/wp-includes/js/wp-sanitize.min.js" } } }Known issues:
There are some "kinks" and imperfections to this approach, as WordPress at large has not exactly been preparing for a headless/decoupled future.
Improper registration/enqueing of scripts
Many plugins and themes, for example, don't register styles and scripts to the global registry, they just enqueue them. This can be problematic as the resource nodes for the assets won't be accessible via a node query using the asset ID, nor would they be accessible via a root
{ registeredScripts { nodes { ...fields } }query (because they're not actually registered).The Storefront theme is an example of conditionally registering assets, which is also problematic. This means that a resource is only queryable via a connection and not available in a Root Query for all registered assets or via the
node( id: $id )query.This will take some education around the ecosystem. . .Registering scripts and styles should be global, and enqueueing them should be conditional / contextual.
Updating Global IDs
The intent of Global IDs is to ensure nodes have unique IDs across Types, but also to provide proper context so the server can resolve a node from an ID using the
node( id:$id)query.Prior to this PR, the Global IDs were a hash of the WordPress Type (post, page, etc) and the database ID.
Now, the Global IDs are a hash of the Loader Name and the database ID.
So posts, pages, and custom post types will all be hashed with:
post:$id, and tags, categories and custom taxonomies will all be hashed withterm:$id.This change allowed for a lot of code around resolving nodes to be deleted! (@mngi-arogers would be proud)
Formalizing all Connections
Prior to this PR, there were multiple ways of handling connections. Many connections made use of the
AbstractConnectionResolverclass, but some made use ofRelay::connectionFromArray(). TheconnectionFromArray()method didn't pass connections through filters and didn't pass edge data down for extensions to make use of if/when hooking in to add edge fields.This PR standardizes ALL connections to make use of the
AbstractConnectionResolverclass, and with that, all Connection resolvers are also associated with a Loader.Loaders for all Node Types
WPGraphQL makes use of a concept called "DataLoading". In a GraphQL request, many different types of resources can be asked for, and sometimes the same node can even be present multiple times in a response.
To make sure data is loaded as efficiently as possible, WPGraphQL first talks to the database for just a list of IDs for the resources, adds the IDs to an in-memory buffer, then circles back to resolve the objects by first checking if the objects have previously been resolved and cached, or by getting the objects from the database and storing them in the cache for future reference.
WPGraphQL abstracts quite a bit of the logic around this concept so that any new resource that wants to load data efficiently can create a new Loader extending the AbstractDataLoader class, and providing a
loadKeys()method that loads objects as efficiently as possible given an array of IDs to load.This pattern works even for data that's not in the WordPress database, for example registered post types and taxonomies, EnqueuedScripts, EnqueuedStylesheets, etc.