State of Preview.js - April 2022
Preview.js was released a bit over three months ago. It's been busy!
The journey started a year ago when I built a proof of concept of a Visual Studio Code extension to preview individual React components without needing to spin up a full app. This became a tool called React Preview, available in beta across VS Code, JetBrains IDEs and the terminal. I ended up quitting my job to focus on building it, with the intention of building a paid Pro version to create an income.
More and more users started asking for an equivalent for other frameworks. A few months in, I made the decision to open source it and support other frameworks such as Vue and Solid. This involved big architectural changes to support framework-specific plugins, as well as some tough questions about monetisation and licensing strategy.
Vite as a foundation
The first proof of concept of Preview.js was based on webpack. This was quite slow and CPU-intensive when combined with the "update as you type" functionality. Fortunately, newer build tools such as Snowpack and Vite offered a much faster experience thanks to native browser support for ESM, combined with the super-fast esbuild to bundle dependencies.
Today, Preview.js relies heavily on Vite to render components. Its elegant plugin system, based on Rollup's, enables support for multiple frameworks, as well as powerful customisation. For example, Preview.js uses an in-memory virtual filesystem plugin to reflect code changes as you type, without having to save to disk.
Vite maintainers have been incredibly helpful in the process of building Preview.js. Not only are bugs fixed promptly and pull requests reviewed with a fast turnaround, they also help promote Vite-based projects with their own audience. Special mention to patak, who you should consider sponsoring if you're enjoying the Vite ecosystem.
Static analysis with TypeScript Compiler API
In order to function at all, Preview.js needs to analyse your code to find component definitions.
Here too, Preview.js relies on a renowned open source project, namely TypeScript, and more specifically the TypeScript Compiler API. This enables us to statically analyse the type of variables to figure out whether they are component definitions or Storybook stories, as well as determine what properties they expect to be passed.
If you want to learn more about this, I wrote a technical blog article on the topic.
Open source features
Preview.js seems simple, but it packs a flurry of essential features under the hood.
As mentioned earlier, one core feature of Preview.js is enabling you to preview updates to a particular component without needing to save. It's as instant as it gets!
This feature is what makes Preview.js truly special. It facilitates you staying in a state of flow by eliminating context-switching steps such as saving a file or toggling between your IDE and a browser.
Along the same vein, when you try to preview a component that expects specific properties, Preview.js tries to generate valid values for them. This is a particularly complex problem to solve, and it doesn't always work perfectly yet. Feel free to report issues if you see any!
Sometimes, autogenerated props don't quite cut it. This is why Preview.js lets you also specify a set of custom previews for a component (see documentation).
This feature was influenced by SwiftUI previews in Xcode as well as Storybook.
If you're a Storybook user, Preview.js has you covered.
It supports Storybook's Component Story Format (CSF) so you can preview and update any Storybook story without leaving your IDE.
In the spirit of preserving your state of flow, it's important that errors don't stop you in your tracks.
When your code fails, which is expected as it updates on every keystroke, Preview.js tries its best to conserve the last valid render while showing a discrete error after a short timeout, suggesting a fix when possible (e.g. detecting a missing package). This is in comparison to other developer tools that replace the entire screen with a disruptive error stack trace.
Preview.js Pro includes all features of Preview.js, along with more advanced features in exchange for supporting the project financially.
You can preview components on different viewports, toggle between light and dark background, search for any component across your codebase, and so on.
Check out the feature comparison table if you'd like to learn more about the Pro Edition.
You can also spin up a preview of any component outside of the IDE with the Preview.js CLI, which was just launched this April.
What's next for Preview.js
Aside from bug fixes and minor improvements, Preview.js itself is mostly complete.
What comes next can be grouped into a few categories:
- support for more frameworks
- advanced features
- cloud support
- deployable build
- new tools based on Preview.js
Support for more frameworks
Preview.js was launched in January with support for React, Vue 2 and Vue 3. In April, support was added for SolidJS as part of #SolidHack (votes are open until 2 May).
A natural next step is to implement Preview.js plugins for additional frameworks. Next on the list are Svelte and Preact. If you'd like your favourite framework to be supported, please file an issue!
One feature coming to Preview.js Pro in the near future that I'm quite excited about is the Component Gallery.
If you use Figma, you know what I'm talking about. Imagine an automatically generated mosaic of all your components, across the entire codebase. This is still in the prototyping phase, so if you have any requests for this feature, let me know.
Another possible feature I'd like to explore is saving previews, potentially as Storybook stories.
Preview.js relies on a local HTTP server, which makes it hard to use with cloud-based IDEs.
There are two types of cloud-based IDEs:
- IDEs that spin up a VM in the cloud such as GitHub Codespaces or GitPod
- IDEs that rely exclusively on the browser, such as vscode.dev and StackBlitz
Running Preview.js exclusively in the browser would require emulating Node APIs. StackBlitz built the WebContainers to support exactly this, but this is currently closed source. Therefore, only cloud IDEs in the first category can be supported.
An additional challenge is ensuring that the required port is automatically forwarded by the cloud IDE (including WebSocket for instant updates).
Work hasn't started yet on this front.
Speaking of cloud, wouldn't it be great if Preview.js could generate a static HTML/JS bundle with all of your component previews and deploy it wherever you like?
This feature is coming soon. It's currently blocked by a pending bug fix in Vite and Rollup, but not for much longer!
New tools based on Preview.js
The foundations of Preview.js can be leveraged to build new types of developer tools.
One topic close to my heart is screenshot testing. Wouldn't it be great if you had screenshots of all the components in your codebase, and you could easily review visual changes in pull requests?
Make sure to subscribe below to hear about it when it's ready.
Until now, the best way for users to share feedback about Preview.js was through GitHub issues and discussions, as well as Twitter.
Today, I'm happy to announce that Preview.js has its own Discord server! Here is the invite link.
Whether you use Preview.js or not, thank you for being part of the journey.
Please keep sharing your feedback and spreading the word about it! It means the world to me, and it's the reason why I keep working on it 💚