Looking for work! Check my resume here.

· 10 min read

Migrating to Astro

Detailing the process I experienced migrating this site from Vitepress to Astro and how I got to `yet another framework`.

Foreward

This post may be a bit less structured as I am still technically migrating to Astro after publishing this and I am still finding bugs. I am just recording my thoughts for now and may clean this up down the road.

I migrated my personal website to Astro while it was still in beta and I have upgraded through release-candidates all the way to official 1.x.x releases and still find issues being created with updates. Is Astro ever going to stablize?

So What is Astro?

Astro is a relatively new (maybe old in Javascript years) framework for building SSR or SSG websites. Astro as a framework is unique that you can Bring Your Own Framework which I haven’t heard of elsewhere. The BYOF feature meant I do get to learn a new hip thing that may along the way solve a problem I am having but also lets me use Vue.js which I am already familiar with. As I read someone else put it, it’s nice that Astro appears to keep itself focused on the static asset generation and makes itself flexible for the JS framework to change with the popularity tides down the road. Of course, unless a newer, better meta-framework comes along!

Disclaimer: I don’t enjoy the churn in the frontend ecosystem but I want to stay relevant and fresh with new skills so I decided to give Astro a shot. Plus, as long as I would be learning something new, I might as well learn something currently hip and cutting-edge so I get that sweet RRD credit.

Astro also supports dynamic content on the page and hydrating interactive components on the client side but all that sounds like unnecessary bloat for my usecase.

Astro Hype

When I decided to switch away from Vitepress I did some searching for Vue.js based SSG. I really didn’t want to have to pick up a new Javascript framework. I thought I wanted to use Gridsome because it uses Vue 3, Vite and most importantly it would be more flexible compared to Vitepress. But, I found after a bit of research on the Github repo that the project has been neglected and users on other forums were lamenting the death of the project.

I then found many blogs mentioning Astro. I assume this is because it is adaptable to many UI frameworks so it has a larger pool of potential users to attract and it is the first (that I know of) meta-framework :rolls-eyes: which attracts more to the bandwagon. Plus, Astro has a large number of sponsors which may have contributed to its speedy growth and popularity so early in its development.

I also noticed the quality of their website and documentation and believed at the time the framework was mature and stable. The number of recognizable companies listed on their homepage as sponsers also didn’t help me see Astro as a project still in beta.

Astro Documentation

Astro’s documentation is quite detailed and most of anything I wanted to do with Astro was easily found there. That was until the migration to version 1.0.0 began and their framework started changing too rapidly to keep the documentation up-to-date; but that I will say more about later.

I will say though, the docs only caused me difficulty early on because I was fixated on using Vue.js as part of the BYOF feature and most of their docs use various frameworks or their own .astro files for examples so I had some trouble looking past that to adapt their examples to what I wanted. The example repos on their Github really clarified things in my mind then later I ended up finding their own .astro files to be pretty practical, so now I use them quite a bit. It really drives home their tagline, “Use Less Javascript”.

My Plan

I want to have a simple SSG personal website that allows me to write blog posts and pages for portfolio content via markdown while allowing some flexability with scripting so I can be sure the home page is always updated with the latest items from each category.

The output should be HTML so I can host for free via Github. And if the output is static HTML then I hope the final result is a responsive, minimal and no frills website. But knowing me, as this goes on I may look for ways to add more complications in the future for the sake of exploring.

simple I said, lol, I’m using a new wave, meta-framework with a mix of astro, markdown, vue, and who knows what else to compile static HTML. I really considered just writing markdown and HTML by hand with something as simple as Jinja for templating but that’s not RDD!

First Challenge - Blog Posts And Portfolio Posts

As I said earlier my first priority was to migrate to a system that allows me to be more flexible with my website layout and features. Foremost, I wish to have separate sections for blog posts and portfolio posts and combine them together on the home page with ease.

So I began with the default Portfolio template provided by Astro which you can find here.

Immediately I added a sibling directory post next to the already existing directory project. In there I added this file you are reading now. I found in the demo a page that lists all portfolio projects titled projects.astro and copied it to create posts.astro and inside there I changed the logic to fetch markdown files from the post directory and added a PostPreview component copied from the already existing PortfolioPreview component. Lastly, I simply added a nav item to the Nav component directed to the new posts.astro and I had acheived what I was looking for. A listing of portfolio pages on the URL /projects and a listing of blog posts on the URL /posts.

By attaching a project tag to the frontmatter section of each post and project markdown file I quickly had a way to find posts that are related to a project.

const posts = (await Astro.glob('/src/pages/post/**/*.mdx'))
	.filter(({ frontmatter }) => !frontmatter.draft && frontmatter.project === content.project)
	.sort((a, b) => new Date(b.frontmatter.publishDate).valueOf() - new Date(a.frontmatter.publishDate).valueOf());

Then at the end of the portfolio.astro layout I loop through the posts and reuse the same PostPreview Vue component from the home page.

{posts.length > 0 &&
  <div class="mt-12">
    <Wrapper>
      <h2 class="font-bold text-3xl my-8">Related Posts</h2>
      <div class="grid grid-cols-1 md:grid-cols-2 gap-12">
        {posts.map((post) => <PostPreview post={post} />)}
      </div>
    </Wrapper>
  </div>
}

Customization of this sort was my real goal and it ended up being easier than I had hoped.

Second Challenge - Vue component inside a Markdown file

I wanted to test Astro’s ability to add some dynamic content within the markdown content so I can share demostrations or examples in my posts or perhaps some other usecase down the road.

Let’s add this Counter.vue from the documentation’s examples.

To add components to Markdown files you add a setup key to the frontmatter object of the markdown file. This makes the solution easy but at first feels like a footgun to have Javascript logic in this yaml key.

As of Astro 1.0.0 release and the migration to mdx over plain markdown the setup key has been removed. Instead Javascript logic can be written directly in the document itself.

0

Look ma I got Vue.js in my Markdown in my Astro.

Hey, but it works.

Third Challenge - Vue UI Framework For Layout and Components

I wanted to use a UI Framework I’m already familiar with such as Vuetify so I can, again, use something I know to help keep things simple. I’m not the greatest with CSS nor do I want to play around with CSS too much but I do want the site to look good enough so I think a UI framework will fit that requirement.

This challenge became impossible after realizing Astro abstracts Vite and the Vue instance so these packages that hook into either one of those can not be setup without an Astro plugin that would expose lower level access to Astro’s internals.

Even though I didn’t want to muck around with CSS too much I ended up taking the opportunity to try Tailwindcss and play around with styling on my own. Tailwindcss is one of those packages that wouldn’t work normally with Astro for the same reason Vuetify won’t work but, the Astro team built a plugin to make it work (well mostly).

Fourth Challenge - Aliases

Quickly I found that I was missing aliases from my usual Vue.js and Webpack based development. It was easy to find in the docs how to make aliases even though it is technically a Vite feature and not related to Astro at all. So no longer do I type ../../components/whatever.vue but instead @components/whatever.vue. Nice little improvements like this make a big difference over time.

So the solution is to add a few alias paths to tsconfig.json then aliases worked in both .astro and .vue components.

"baseUrl": ".",
"paths": {
  "@components/*": [
    "src/components/*"
  ],
  "@layouts/*": [
    "src/layouts/*"
  ]
},

Issues

  • Changing API

The beta to 1.0.0 release has introduced some issues that temporarily broke this website. Also, the project threw out markdown and replaced it with markdownx. Same for code snippet handling.

At this point I no longer know the proper way to display code snippets with the formatting I had set up while in beta since the documentation is not yet up to date on this.

  • Hot Module Reload Flakiness

Occasionally my only option to be sure my code was taking effect was to restart the dev server. There are also some issues that can guarantee you will need to restart the dev server such as accidently importing a component with the the wrong extension. And editing the astro config file requires a restart of the dev server which is not that bad or suprising.

  • Tailwindcss or similar Vite based plugins

Any UI framework or package that integrates directly with the Vue app instance is not going to work as it is abstracted away behind Astro. A plugin could resolve that I believe. Astro also abstracts Vite a bit so Vite based plugins do not work well with Astro either. Tailwindcss being one of those packages has an official Tailwindcss plugin but it doesn’t come without its own issues.

Tailwindcss and other comparable Vite plugin based packages are a source of trouble for the Astro developers as I found in their Github issues page.

The gist of the problem that I could gather from here and here seem to be UnoCSS, Windicss, etc are Vite plugins which require being built to work. Astro on the other hand never builds .astro files and insteads injects the default css file from these frameworks into the <head> which means it loads the css via request once then does not have HMR capability. Clearly, the meta-framework is running into issues when popular packages make assumptions about their intended environment that contradicts what Astro is doing under the hood. Work arounds have been made such as this but I can’t help but think between this and Astro developers’ discussions to fix these sort of issues point to a fundemental issue which will only lead to more issues or complexity in the future and Astro may end up with more bespoke configuration options that contradict their “Write Less Javascript” tag line.

Positives

  • VSCode extension works very well

  • HMR generally works and is fast (until tailwind was added)

Although with the latest releases this is improving.

  • Great docs and demos

  • Straightforward and gives enough freedom

Final Thoughts

Astro is relatively easy to get going and I enjoy the mix of Markdown and Vue.js that I can mix as I please. The project file structure just feels familiar and easy to use compared to some of the big players in the SSG space like Hugo and Gatsby. Astro’s API is changing though so I will need to keep up with in as it exits beta but I have good hopes that it will serve me well for this personal website.

  • javascript
  • vue
Share:
Back to Blog