Isograph is an opinionated, compiler-driven framework for building data-driven apps that are stable and performant out of the box. In Isograph, developers write components, along with the data they require, and a compiler stitches everything up for you. See also the quickstart!
The Isograph team is extremely proud to announce the release of Isograph v0.5.0! This release contains amazing new runtime features, massive DevEx wins, compiler performance improvements and important internal refactors. And the team is growing! The team is growing — since the last release, five new engineers have contributed to the project!
- Optimistic updates. You can now provide an optimistic response at that time, which will be written into the store for the duration of the network request.
- Writing external data into the Isograph store. We now provide a typed interface to write arbitrary data into the Isograph store. Useful when incrementally adopting Isograph, when you don't yet have a GraphQL endpoint set up, or when you have another source of data (e.g. server-sent of events or local storage.)
- DevEx wins in the VSCode extension. Selecting a field that doesn't yet exist? There's an autofix that will create the field for you! And so much more!
- Compiler performance wins. We no longer rewrite the entire
__isographfolder on every change, leading to massive speedups in watch mode!
Let's talk about each of these, and more!
Optimistic updates
We now support providing an optimistic response for most network requests! Oftentimes, when you make a network request (for example, when making a mutation to increment a post's like count), you already know what the result will be if the request succeeds. In cases like this, you can now provide an optimisticNetworkResponse. This response will be written into the store, and later dropped when the network request completes.
The best part about this — this is completely statically typed! Entrypoints contain so-called raw response types, which are types that correspond to what the network response would be. When you provide an optimisticNetworkResponse, you must provide something of that shape. So that means that if you change what you're fetching by adding or removing fields, then the raw response type changes, and what you provide must change!
In order to implement this, we had to rewrite the store from being a single object to being a stack of objects! Writing an optimistic response is as simple as adding an object to this stack, and reverting it is simply removing it from the stack. Neat! This work also sets us up for future support for "forking" the store (i.e. a store that supports multi-version concurrency control).
Thank you @PatrykWalach for this amazing work!
Writing external data
We now provide a typed API for writing external data into the Isograph store! You may want to do this in at least three circumstances:
- you're incrementally adopting Isograph,
- you don't have a GraphQL backend, but want to enjoy the DevEx and performance wins of Isograph, or
- you have an external source of data (e.g. some server-sent events, local storage, etc.) that you want to work with an existing Isograph app.
Like with optimistic updates, these rely on the raw response type! You create an entrypoint and provide the equivalent of the network response, and that is written into the store, as if it came from the network.
Another win here is that writing data from an external source uses the same primitives as writing network data, so you get a bunch of awesome things for free! Just the needed components are re-rendered, the data can be garbage collected when its unused, etc.
Once again, amazing work by @PatrykWalach!
VSCode extension improvements
And this version of Isograph included some amazing DevEx wins! In my (admittedly biased) opinion, I think Isograph can lay a claim to being the framework that provides the best DevEx! Check out this video, where we holistically describe the developer experience of using Isograph:
And now, we've released not only a VSCode extension, but also an Open VSIX extension, so you can get the benefits when using other editors, like VSCodium and Eclipse Theia. Thank you @sp6370 for setting this up!
But let's also call out some specific features that shipped in v0.5.0:
- errors are now surfaced in VSCode!
- autocomplete of fields now works!
- if you select a field that doesn't exist, you will get an autofix that creates a file containing a stub of the field for you! For example, if you selected
Query.Header, and it didn't exist, and used the autofix labeledCreate new @component field named `Query.Header`, then it would create a file containing:
import { iso } from '@iso';
export const Query__Header2 = iso(`
field Query.Header @component {
}
`)(({ data }) => {
return null;
});
What a massive speedup!
And guess what? There are even more VSCode extension improvements coming soon!
Compiler performance wins
Another win that we shipped was an absolutely massive performance win. We previously rewrote the entire __isograph directory on every save. Now, we keep track of the previous file state and make only the minimal changes to the file system required.
Testing locally, in the pet demo, updating the graphql schema by adding a new, unused field on pet demo went from 144ms to 53ms (in a debug build on a macbook pro m1), and updating the Query.HomeRoute iso literal by adding a new field went from 125ms to 72ms. These gains are likely going to be much larger in larger projects!
Thank you @lucasmachadorj for this amazing work!
Internal refactors
We also did an absolutely monumental amount of internal refactoring, with three big goals:
- enable us to add additional features to the extension,
- improve the performance of the compiler, and
- set us up to support other network protocols (e.g. SQL, tRPC).
Since these aren't user-facing, I'll focus on just one of these improvements by @ch1ffa. We added support for returning references from memoized functions. This is a gamechanger. Our incremental compiler is written as a series of memoized pure functions which reuse their old values if no input has changed, and therefore their return value couldn't have changed. However, one limitation was that we were restricted to returning owned object, so if a particular value went through several memoized functions, it was repeatedly cloned. Now, we support returning references, and the compiler clones objects far less!
Other improvements
- @Cobord added tests related to the garbage collection of
MemoRefs. - @corydeppen added docs about TanStack start and StrictMode.
- @TheRealGChen added docs related to troubleshooting.
- @tbezman fixed broken
useClientSideDefertypes.
There is a lot more! See the commit message for more details.
Conclusion
Getting this release out has been a monumental effort, and this blog post didn't cover even cover everything! There's never been an easier time to try out Isograph!
So go on, give the quickstart a try! Join the discord! Star the repository!