Paul is a Senior Software Engineer, Independent Developer Advocate and Technical Writer. More from Paul can be found on his site, paulie.dev.
Read more from Paul Scanlon
In this post, I’ll explain how to build a lightweight StackBlitz embed component for your Astro site using Qwik. I’ll be using the StackBlitz JavaScript SDK, which can be used to embed its projects in web pages.
If you’re not familiar with StackBlitz, it’s an entire development environment that runs in the browser. Every type of project you can imagine is just one click away, and you can spin them up in seconds.
As mentioned above, StackBlitz’s JavaScript SDK can be used to embed StackBlitz projects in web pages — or, in my case, blog posts authored in MDX.
Here’s a screenshot from my site where I’m using a StackBlitz embed component in one of my posts.
For me, a technical writer, it’s almost become a necessity. I write a lot of technical articles and guides, each usually requiring a link to a GitHub repository; and in a lot of cases, a live preview of the finished example.
But I’m running out of places to put this stuff. Understandably, Netlify has a limit to how many sites you can deploy on its free starter plan. That’s cool, but before I hit that limit, I want to investigate some alternatives.
Embedding a StackBlitz project in my posts seems like a nice solution. Even on the free plan it offers unlimited projects and collections. Which is great news for me!
But there’s a problem. Embedding a StackBlitz project in my blog posts will likely affect performance.
As you probably know, Astro ships zero JavaScript to the client by default, keeping page size small and load speed fast, so slamming in an iframe that has to load a bunch of stuff over the network is not the best idea.
But just so you know, here’s one way to load a StackBlitz project using an iframe (Yikes, what is this, the 90s?).
And to be fair, this issue isn’t specific to StackBlitz — embedding anything in a webpage that requires an HTTP request to load content might have an impact on page load speed.
However, because I also use Qwik on my site, I can both lazy load the code required — and more than that — I can make it “viewport” aware.
useVisibielTask$()
is a little like React’s useEffect
(with an empty dependency array), which runs “on mount”. But where useVisibleTask is different is that it has a built-in Intersection Observer which Qwik uses to determine if the component is within the viewport.
This is very helpful in the case of embeds, which could appear anywhere in the body of a post or article; and naturally, you won’t want to load it until the user can actually see it.
Moreover, in any blog post or article I write, I might require multiple embeds to communicate multiple concepts.
If, on page load, all of these embeds make HTTP requests to load content, it would really affect the overall user/reader experience and possibly contribute to higher bounce rates — so use embeds with caution!
I’ve written a little more about useVisibleTask on my site here: How to use Qwik’s useVisibleTask$. And I’ll be using a similar approach to creating the StackBlitz embed.
Step one is to install the @qwikdev/astro integration. The README in the repo explains how to do this and is super straightforward, so I won’t cover it again here.
Step two involves creating a Qwik component and ensuring it can be “auto-imported” and used within MDX files.
Install astro-auto-import. Again, the README in the repo explains how to do this so I won’t explain it again. I will however quickly explain how I configured the integration ready for the StackBlitz embed component.
With astro-auto-import installed, you can now configure which imports point to which components.
In the above code snippet, I’m providing a path to the StackBlitz component, and defining the name the import is known by, E.g. StackBlitz
, and the type of export I’m using in the component, default
.
The usage for this component when used within an MDX file would look similar to the below.
To create the component you’ll need to install the StackBlitz JavaScript SDK. Instructions can be found in the docs.
Allow me to explain the embedprojectId method, though. In its simplest form, it would look something like the below code. The method accepts three arguments, which are:
Here’s the finished component:
Besides the usual TypeScript bits, the main things to notice are:
Here’s a simpler JavaScript snippet so you can see more clearly:
The usage would then look similar to the one below. Depending on what functionality you think you’ll need will determine which props to pass on to the options object.
Two very useful features that are working well for me are the view
and file
options.
The view option allows you to determine which view StackBlitz will display. The options are as follows, and you can read more about these options in the docs: UiViewOption.
The file option is also pretty cool! When used with the view
set to either default
or editor
you can open StackBlitz at a specific file.
And here are some screenshots from my site that uses this same approach.
Before a user scrolls the embed component into view, the page size is ~241kb.
After the page is scrolled, and the component enters the viewport and is loaded by Qwik, the page size is ~42 MB!
There is also one other option you might like to explore. The options object accepts clickToLoad
. Which will still load the essential StackBlitz stuff, but will prevent the whole project from installing/loading.
In my example, with this option, set to true
the page size is ~1.7 MB.
And that’s why you need a polite solution to loading embed components. A ~42 MB initial page load size is unacceptable, and whilst 1.7 MB is better it’s still not great, even at Elon Musk’s house where I imagine he has a really fast internet connection.
So there you have it. Keep it polite, keep it Qwik and give StackBlitz a try. I think it’s a pretty cool solution for technical writers.