How a Gatsby and API-driven architecture can make faster, more secure, and more scalable web projects.
THE SWARM
THE HEARD-OF-ITS
THE CV ITEMS
THE IMPACTFUL
Founder, NPM
JAMES
HTML 3.0
HTML 5
Framesets
Shockwave
Applets
Flash
Web 2.0
jQuery UI
React/Vue
2005
1995
2015
Today
"OMG I can do a website using just HTML and CSS"
(behaviour)
HTML
DATA
DATA
DATA
CSS
"The right thing is the easy thing."
Code splitting
Background pre-fetching
Image optimisation
Lazy loading
"It's yours to stuff up."
$ gatsby new my-project
cd my-project
gatsby develop
<gatsby-starter-default>
http://localhost:8000
http://localhost:8000/__graphql
$ yarn add gatsby-source-rss-feed
{
resolve: `gatsby-source-rss-feed`,
options: {
url: `https://silverstripe.org/blog/rss`,
name: `SilverStripeBlog`
}
}
$ gatsby develop
docs.silverstripe.org
silverstripe/silverstripe-gatsby
Gatsby source plugin that sources from a site with silverstripe-gatsby installed
gatsby-source-silverstripe
Silverstripe CMS module that exposes all your DataObjects to Gatsby
silverstripe-gatsby-helpers
Lightweight npm package that provides utility functions for working with the Silverstripe CMS source, such as `buildSiteTree()`, `useMenu(1)`
The A&D Team
GraphQL was the chosen API layer for asset-admin in CMS v4
Early adopters, but proven right
silverstripe-graphql module tagged stable in CMS 4.0 release
Major version releases required
GraphQHell
Discussions about making the schema cacheable date back nearly two years.
Complex problem to solve: Lots of dynamic code
Needs of our bespoke teams and partner agencies drive our product roadmap
The problem
The solution
Concession: For GraphQL to scale, a build step is inevitable
Rewrote scaffolding APIs to generate PHP code
~1.2 million layers of abstraction
And... it worked!
But were performance gains worth the DX penalty?
The problem
The solution
Small print mentions new lazy type loading API
More small print mentions type language support (and caching!)
Type language = DX win
Type lazy loading = Performance win.
Uses code generation to persist an executable schema to the filesystem
Requires a build step
Almost everything can be done in YAML
Type/Query creators and scaffolders just glorified arrays
Scaffolders are now “models” that populate those arrays
All you’re doing is composing value objects that render themselves in PHP code.
Manager is now Schema, and query handling has been isolated out.
Plugins distribute single-concern, reusable code
Confirmed: We don’t have a schema problem, we have a resolver problem.
Resolvers must be static. (99% of resolvers already are)
To reduce boilerplate, a resolver discovery pattern will find resolvers implicitly
Resolvers can take context (e.g. for generic DataObject resolvers)
($context) => ($obj, $args) => $result
Classes will define many resolver methods, organised as needed
Just about everything in the Schema accepts plugins:
Updates can be a one-type schema-wide update or a very surgical update to one field
Example plugins: Versioned, Sort, Filter, Paginate, PermissionCheck
Average response time: ~70ms
Backward compat with core modules:
Asset-admin
Versioned
Elemental
Versioned-admin / Snapshots
Refine the DX and devops around the new schema build:
Build performance
Autobuilding?
N+1 optimisation, query caching
Real world usage
Why aren’t you building more API-driven sites?
What can Silverstripe Ltd do to help derisk this?
Try it on a small project, or a side project, and give us feeback