What a milestone! Today, the Isograph team is thrilled to announce the release of Isograph 0.1.0. Isograph is ready for use on certain projects and internal tools, and though feature incomplete, provides a great developer experience!
And on top of that, we're releasing this brand new documentation website!
So go on! Take it for a spin. Everything you need to give Isograph a try is in the quickstart guide.
This is a pre-1.0 release. Most Isograph APIs are likely to evolve substantially before being finalized.
What is Isograph, and how does it provide such a great developer experience?
Isograph is a framework for building React apps that are powered by GraphQL data. It has ambitions to be a framework for building apps powered by data.
With Isograph, developers define components and the data they need. Isograph takes care of the rest. On every save, the Isograph compiler will generate queries containing exactly the data needed by a given view (no more and no less), and wire up your app so that all of these components receive exactly the data they asked for (no more and no less).
Because the compiler is doing so much for you, Isograph is able to offer an amazing developer experience, free of boilerplate. Engineers can just reason locally about the file that they are modifying, and trust that the compiler will wire up their app correctly.
But the benefits of that go far beyond developer experience.
The trilemma
As an engineering team grows, communication and coordination become more and more difficult. There comes a time when your app becomes unstable, because no one can reason about it end-to-end anymore, and innocuous changes start leading to downtime.
In response, teams can add process and manual review, sacrificing developer velocity.
Or, they can structure their apps so that the parts are independent, and each component fetches its own data. But this comes at a cost — many network requests for duplicate data and a chaotic loading experience. Or, query declarations can become append only. Either way, your app grows sluggish over time.
With Isograph, there's no tradeoff between velocity, stability and performance
The Isograph compiler allows developers to reason about just the file they're modifying, generates optimized queries on every save, and never accidentally forgets to pass data to components. So, even as your team grows, Isograph allows you to maintain iteration speed, app stability and stellar performance.
Why now?
We're releasing an alpha version of Isograph in recognition of a milestone: the most important components of the Isograph developer experience have landed. In fact, you can check out the quickstart guide and see for yourself! You can also check out this video in which Robert Balicki builds an Isograph app.
We encourage you to try Isograph, to join the Discord and to look at the open issues on GitHub. If you want to get involved in the early stages of a project that is pushing the boundaries of what is possible in web development, we would encourage you to get involved!
If you have questions or guidance about whether Isograph is appropriate for you, we're happy to answer them!
New features
Quite a few features have shipped since the talk at GraphQL Conf! Let's talk through the biggest ones:
This blog post only goes into some of the features that have landed as part of this release. See the release notes for a complete list.
Client-defined @component
fields can be used as React components
The most-requested DevEx improvement has arrived! Client-defined @component
fields can be used directly as React components!
For example, if we select a User.Avatar
client-defined @component
field in the User.UserProfile
field, it can be rendered as <props.data.Avatar />
!
export const UserProfile = iso`
field User.UserProfile @component {
full_name,
Avatar,
}
`(function UserProfile(props) {
return (
<>
<h1>Hello {props.data.full_name}!</h1>
<props.data.Avatar />
</>
);
});
Major thanks to Alec Aivazis for explaining how this is done in Houdini, and to Christoph Nakazawa for convincing me of the importance of this feature.
Users do not have to provide types
Another absolutely groundbreaking feature that landed is that the type of the parameter to client field functions is fully typed, without the user having to do anything about it. Consider the UserProfile
example shown previously. The props
field is fully typed, and TypeScript knows about this!
How this works is that the Isograph compiler generates the iso
function, along with its types, and TypeScript can infer that we're passing an object with shape { full_name: string, Avatar: Component }
!
Major thanks to Terence Bezman for explaining how this can be done, and to Alec Aivazis for proving this out in Houdini. And a huge shoutout to Edmondo Porcu for hitting the ground running and shipping such an incredibly impactful feature!
Installable via yarn
Everything can be installed with yarn! Add Isograph to an existing project with:
yarn add --dev @isograph/compiler
yarn add --dev @isograph/babel-plugin
yarn add @isograph/react
Watch mode
The compiler can now be run in watch mode with yarn iso --watch
, and even provides pretty error messages:
Starting to compile.
Error when compiling.
Error when validating schema, resolvers and fetch declarations.
In the resolver `Actor.UserLink`, the field `Actor.foo` is selected, but that field does not exist on `Actor`
/Users/rbalicki/code/isograph/demos/github-demo/src/isograph-components/UserLink.tsx
field Actor.UserLink @component {
login,
foo,
^^^
}
Compilation took 139ms.
Babel plugin
In a huge DevEx win, Isograph now comes with a Babel plugin that replaces calls to iso(`entrypoint Type.Field`)
with require calls to the generated entrypoint artifact. (SWC support coming soon!)
Now that this and the automatically-supplied types feature have landed, there is (currently) no reason for users to import any generated artifacts or types (except iso
.)
Entrypoints
Goodbye @fetchable
client-defined fields, hello entrypoints! The Isograph mental model has been substantially simplified.
When the Isograph compiler encounters an Isograph literal of the form iso(`entrypoint Query.field`)
, it will generate a query text for that field. This entrypoint can be passed to useLazyReference
, which will make the network request during the initial render of a component.
Configurable magic mutation fields
These are no longer called magic mutation fields.
Magic mutation fields are fields that are added to certain types. When read out, these fields are functions that trigger mutations. For example, you might configure a User.set_name
field to call the Mutation.set_name
mutation.
These are now configurable in schema extensions via the @exposeField
directive. See the documentation.
A brand-new isograph.dev
You're looking at it now!
Thanks
Isograph isn't a one-person job! I want to thank Edmondo Porcu, Sami Syed and Marais Rossouw for contributing to Isograph, and Adrtivv for a surprise, last minute PR that didn't make it into this release! I want to thank Lenny Crespo Garcia for providing incredibly valuable feedback and recording videos with me. I want to thank Matt Mahoney, Jens Neuse, Predrag Gruevski, Randall Bennett, Reed Harmeyer, Gabriel Nordeborn, Benjie Gillam, Terence Bezman, Alec Aivazis, Zack Jackson, Kerry Imai, Dennis Cahillane, Nicholas Shook and John Maguire for providing valuable feedback.
I'm sure I'm forgetting others, so I apologize in advance!
Isograph would not be as far along or as polished without you.