Hello everyone, I've finally been able to reopen my personal website, which I haven't been able to work on for a while. Since I had the time, this time I chose to use a more efficient and simple framework on the web side. I achieved a Server-Side Rendered (SSR) application for the first time using Astro.js. It was a bit challenging since I delved into the implementation without knowing the framework at all.
I could have chosen Nuxt or Quasar since I'm accustomed to developing with Vue, but I want to briefly explain why I chose Astro. Due to my old habits in web development, I might be obsessed with performance. After trying frameworks that are entirely based on Vue, the result was starting to become disappointing at some point. This is because when you compile once and start increasing modularity in your project, the small pieces you use start to come together as a whole. You end up with many component structures that come into play over and over again with each page refresh.
From my time working with Vue, I know that efforts have been made to eliminate complexity with the Options API and later the Composition API. However, since Vue uses its own structure, it becomes challenging to segment every part of the system and stay true to the project structure after a point. At this point, I thought about why I would want to manage such complexity on the web side. This was my humble opinion on how things developed. In addition to these, the component structure on frameworks like Quasar and the parts that come as utils started to seem too heavy for me on the web side.
Largest Contentful Paint (LCP)
If we're going to move on to the technical part of the discussion, the first topic I mentioned was actually the Largest Contentful Paint (LCP). The benchmark test is as follows.
All frameworks scored 50% or higher in this metric. However, the newest frameworks (Astro, SvelteKit, and Remix) are the ones that received the highest scores in this metric. All three obtained a score of over 75% in this metric for all tested websites. You can find the details here: https://astro.build/blog/2023-web-framework-performance-report/
My First Experience with Astro
It seemed clear to me that Svelte has a distinctive structure like Swelte and presents it in the simplest form. However, I must remind you that transitioning from a field like Vue or React to this side initially feels like abandoning the ship and hopping onto a boat for me. I felt like I did when I coded both back-end and front-end with pure PHP for a while. It has a space within Astro called Astro Island, in its own words:
The island architecture helps you avoid monolithic JavaScript patterns and leads to better frontend performance by automatically cleaning up all unnecessary JavaScript on the page. Developers can continue using their favorite UI components and frameworks with Astro and still enjoy these advantages.
We strive to use JavaScript on the server side as much as possible. For client-side usage, there are integrations with various frameworks like Vue, React, and Preact. If you want to use normal JavaScript on the client side, you can do so within the <script> tag, but it runs you through the standard collections in the DOM. Therefore, you prepare the system in small pieces using Vue or React, but only for client-side manipulations.
Including a Vue Component in Astro
Installation
npx astro add vue
Next, we configure the astro.config.mjs file for Vue integration.
import { defineConfig } from 'astro/config';
import vue from "@astrojs/vue";
// <https://astro.build/config>
export default defineConfig({ integrations: [vue()] });
Now, let's create a Vue component.
<template>
<div>
<ul>
<li v-for="item in food"> {{ item }} </li>
</ul>
</div>
</template>
<script setup lang="ts">
const food = ["Pizza", "French fries", "Spaghetti"];
</script>
Let's use the project we created within any .astro component.
---
// Burası Astro'nun frontmatter olarak adlandırdığı alan.
// burada typescipt ve javascript kodlayabilirsiniz
// Burada oluşturulan kodlar yalnızca server tarafında çalışacak ve client tarafında asla işleme alınmayacak
import Food from "../components/food.vue";
const title = "Hello World!";
---
The crucial point here is that interactivity doesn't work on the server side when using any Vue component. If you want to handle a client-side Vue on the SSG side, you should follow a path similar to the one below.
In Astro, there is a client directive for using interactivity. These are the options for hydration:
client:load
- Sends JavaScript to the component instantly.client:idle
- Hydration occurs instantly when the browser's main thread is idle.client:visible
- Hydration occurs when the component becomes visible in the viewport.client:media={QUERY}
- Hydration occurs when the specified media query is matched.client:only={FRAMEWORK}
- Completely ignores the Astro compiler (not recommended).
The usage of all these is exemplified as follows:
<html>
<head> <!-- Astro uses a JSX-like syntax in it's body -->
<title>{title}</title>
</head>
<body>
<header>
<Navigation client:load />
</header>
<main>
<h1>Food I like:</h1>
<Food client:load />
</main>
</body>
</html>
By configuring it this way, you are now taking the steps to build a fast web application on the server side.
🔥 Comments