An open-source tool that brings Storybook’s functionality into Visual Studio Code. Please follow our work on GitHub.
A New Chapter for Storybook
Storybook currently displays visual components in the user’s browser. It’s an extensive and vital tool for front-end visual TDD. Aesop is was conceived as a lightweight (>130kb) dev tool that brings Storybook’s component-driven development into tighter sync with developer workflow. At present, launching a Storybook will send users to an external browser window to view their previewed components. Aesop set out to overcome the need to tab between applications to bridge that subtle attention gap, and fully benefit from Storybook’s HMR capabilities.
Aesop uses VSCode webviews to display Storybook’s interface inside of VSCode. A webview is a logic-wrapped iframe that enables VSCode to relay localhost content, execute scripts, and pass messages between the host instance and the user’s workspace. In our previous article, we discussed the basics of webviews and how to display content in them. This article will delve deeper into the underlying Node.js processes that Aesop uses to display content in a webview.
How to utilize Node.js child processes with VSCode API
Once we serve the localhost content into our webview, we have essentially re-created the Storybook experience inside of VSCode. However, as software engineers, we would be remiss to have this wonderful functionality exist without a user-friendly way of utilizing it. The first thing we needed to address was the delineation of the extension’s launch logic to account for all possible scenarios of the user using Storybook:
- If user already ran Storybook (via pre-defined localhost port)
- If user already ran Storybook (via random [i.e., not pre-defined] localhost port)
- If user did not yet run Storybook (user has pre-defined localhost port)
- If user did not yet run Storybook (user has not defined localhost port)
In the first two configurations, Aesop will not need to execute any commands to start storybook, as the server is already up and running. However, with the last two, Aesop will need a way to explicitly start the Storybook server for us.
Enter Node child processes.
Aesop uses a Node.js process architecture to manage asynchronous functions and associated promise resolutions. Upon activation, it instantiates an event emitter to break its startup logic for every use case defined above. It then spawns a child process to silently execute shell commands in the user’s workspace.
Aesop utilizes networking tools to listen in on running Storybook processes in order to determine which port it will use. If no Storybook process is running, Aesop will first check your package.json for any custom configurations you’ve added to your “storybook” script, determine any predefined ports, and applies a “ — ci” flag to the child process’s launch arguments, preventing any unnecessary bounces to an external browser window.
As a bonus, Aesop will double back and check your shell outputs to make sure your Storybook made it to the port you’ve selected — just in case you’ve left a pesky server running on your favorite port. It accomplishes this with platform-specific logic to parse out meaningful values and divert ports if necessary.
As you can see, Node child processes are incredibly useful. When applied in the context of VSCode extension building, they provide an extremely powerful way of controlling your logic flow.
What’s in Store Next?
Aesop is open-source project on GitHub, and our extension can be downloaded from the VSCode Extension marketplace. As we move closer to releasing Aesop out of beta, the team is aiming to implement greater UI integration to permit our humble helper to interface with Storybook’s Manager and enable advanced features, like changing focus to the appropriate Story file when selecting a new preview from the Explorer UI.
The Aesop team is grateful for the support of the Storybook community and we invite everyone to download and test Aesop. Please follow the team’s progress on Twitter @AesopStorybook, and feel free to reach out to us on GitHub.