DEV Community

Cover image for Exploring Astro and Svelte vs. SvelteKit: A comparative guide
Matt Angelosanto for LogRocket

Posted on • Originally published at blog.logrocket.com

Exploring Astro and Svelte vs. SvelteKit: A comparative guide

Written by Elijah Asaolu✏️

Despite being a relatively new web framework, Astro has gained significant traction in the development space. With this surge in popularity, many developers are contemplating migration from legacy frameworks like SvelteKit and Nuxt to their Astro counterparts.

In this article, we will delve into the differences between Astro + Svelte and SvelteKit, comparing their performance, developer experience, and relevant feature offerings. Jump ahead:

At the end of this article, we’ll summarize the key differences in a comparison table to provide a helpful guide as you consider which framework to use in your next Svelte project.

What is Astro?

Astro lets you create fast and modern websites using your preferred UI components and libraries. This UI-agnostic framework is compatible with modern JavaScript frameworks like React, Svelte, Vue, Solid, and more. You can even integrate multiple JavaScript frameworks within a single codebase.

With Astro, you can fetch content from various sources and deploy it across different platforms. Its remarkably fast, zero-JavaScript frontend architecture is perfect for building multi-page applications, all while optimizing SEO and performance.

By default, Astro operates as a zero-JavaScript framework, converting application logic into HTML to be rendered on the server side. However, its “component island” feature enables you to create and import interactive components that execute JavaScript on the client side.

Astro's versatility extends to supporting Markdown and MDX, making it a suitable choice for creating content-rich websites and blogs.

What is SvelteKit?

SvelteKit is a web development framework you can use to create flexible and rapid web applications utilizing Svelte. It combines prerendered pages for optimal performance with dynamic server-side rendering for enhanced flexibility.

Additionally, SvelteKit facilitates transforming apps into progressive web apps (PWAs) and supports export as static sites.

SvelteKit mirrors the relationships of Next.js with React and Nuxt with Vue, offering fundamental features like routing, data fetching, accessibility, SEO optimization, and more.

Getting started with Astro + Svelte

To incorporate Svelte into an Astro application, the first step involves creating a new Astro app:

npm create astro@latest
Enter fullscreen mode Exit fullscreen mode

This command will prompt you to provide details such as your app's name and preferred starting template. Opt for the "Empty" project template and configure other settings based on your requirements. Once completed, launch your application using:

npm run dev
Enter fullscreen mode Exit fullscreen mode

To add Svelte to your Astro app, execute the following command:

npx astro add svelte
# OR
yarn astro add svelte
Enter fullscreen mode Exit fullscreen mode

This command will install the necessary packages and request permission to modify essential files. Accept the changes, and Svelte should be seamlessly integrated into your Astro application.

With the Svelte adapter added to your Astro application, you can begin creating Svelte components in the .svelte files within the default src/components directory and importing them into your application.

Installing Tailwind CSS in Astro

Astro simplifies the process of installing third-party packages with its one-line installer, much like how we added Svelte earlier. To witness this in action, let's go ahead and install Tailwind CSS by running the following command:

npx astro add svelte
# OR
yarn astro add svelte
Enter fullscreen mode Exit fullscreen mode

Upon executing this command, you'll receive prompts to authorize modifications to specific files and to install the required packages. After completing this step, simply restart your application, and Tailwind should seamlessly begin functioning.

If you prefer a more hands-on approach, you can check out Astro’s detailed instructions for manually installing Tailwind.

Creating a component with Svelte + Astro

Let’s try out our Astro + Svelte combo. Create a new UserCard.svelte file inside the default src/components folder and paste the following code into it:

<script>
    import { onMount } from 'svelte';

    let user = null;

    onMount(async () => {
        try {
            const response = await fetch('https://randomuser.me/api/');
            const data = await response.json();
            user = data.results[0];
        } catch (error) {
            console.error('Error fetching user:', error);
        }
    });
</script>

<div class="flex items-center justify-center h-screen">
    {#if user}
        <div class="bg-white rounded-lg shadow-md p-6 w-80">
            <img src={user.picture.large} alt="User" class="w-25 h-25 rounded-full mx-auto mb-4" />
            <h2 class="text-xl font-semibold mb-2">
                {user.name.first}
                {user.name.last}
            </h2>
            <p class="text-gray-600">{user.email}</p>
            <p class="text-gray-600 mt-1">
                {user.location.street.number}
                {user.location.street.name}
            </p>
            <p class="text-gray-600">
                {user.location.city}, {user.location.country}
            </p>
        </div>
    {:else}
        <p>Loading...</p>
    {/if}
</div>
Enter fullscreen mode Exit fullscreen mode

The code above retrieves data from the Random User API. Once the component mounts, it renders a Tailwind-styled profile card. Next, proceed to the default pages/index.astro file and replace its current content with the following code:

---
import Layout from "../layouts/Layout.astro";
import UserCard from "../components/UserCard.svelte";
---

<Layout title="Welcome to Astro.">
  <UserCard client:load />
</Layout>
Enter fullscreen mode Exit fullscreen mode

Here, we've updated our app's index page to import and render the previously created UserCard Svelte component.

Furthermore, we introduced the client:load prop to the UserCard component, showcasing the Astro component island principle in action. Let’s break down the “Astro island” in our example in more detail.

Our Svelte component fetches data after being mounted, which requires JavaScript to execute on the client side. This contrasts with Astro's default behavior, which revolves around rendering HTML without relying on JavaScript.

To bridge this gap and signal to Astro that this component is interactive, we've introduced the client:load prop within the UserCard component. This will load and hydrate the component JavaScript immediately on page load, ensuring the expected behavior of our component.

With everything in place, upon running our application in a web browser, we should see an output similar to the example below: Demo Of Astro And Svelte Combo Used To Create A Card Component

Getting started with SvelteKit

To create a new SvelteKit application, run the following commands:

npm create svelte@latest new-app
cd my-app
npm install
Enter fullscreen mode Exit fullscreen mode

Once your application is successfully created, launch it using:

npm run dev
Enter fullscreen mode Exit fullscreen mode

Installing Tailwind CSS in SvelteKit

The process of installing Tailwind CSS in SvelteKit is pretty similar to the steps you'd follow in other legacy frameworks. These steps involve a sequence of commands. Let’s go through this sequence now.

To begin, run the following command in your project directory to install Tailwind CSS along with its peer dependencies. This step also generates the essential tailwind.config.js and postcss.config.js files:

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Enter fullscreen mode Exit fullscreen mode

Next, open your svelte.config.js file and update it with the code provided below to import vitePreprocess from @sveltejs/kit/vite. This enables us to process <style> blocks as PostCSS:

import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/kit/vite';

const config = {
  kit: {
    adapter: adapter()
  },
  preprocess: vitePreprocess()
};

export default config;
Enter fullscreen mode Exit fullscreen mode

Extend the tailwind.config.js file by updating the content section to match the following example, which includes paths to all your template files:

content: ['./src/**/*.{html,js,svelte,ts}'],
Enter fullscreen mode Exit fullscreen mode

Create a new ./src/app.css file and embed the @tailwind directives for each of Tailwind's distinctive layers:

@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

Lastly, create a new layout file at ./src/routes/+layout.svelte and import the recently created app.css file within it:

<script>
    import '../app.css';
</script>
<slot />
Enter fullscreen mode Exit fullscreen mode

These steps collectively highlight the process of installing Tailwind CSS within SvelteKit. It's interesting to contrast these steps with the corresponding procedure in Astro, underlining the differences in their respective workflows.

Creating a Svelte component with SvelteKit

When it comes to integrating Svelte components, the fact that SvelteKit is a Svelte-based framework helps simplify our task.

For example, duplicating and reusing the UserCard component within our SvelteKit application is practically effortless. We can directly import the component into any page, such as .page.svelte, without requiring additional configurations.

This straightforward method of recreating the UserCard example in our application underscores SvelteKit's innate compatibility with Svelte.

Comparing Astro + Svelte vs. SvelteKit

So far, we've explored the initial steps of setting up both Astro + Svelte and SvelteKit. Now, let's delve into a comparative analysis, evaluating the distinct advantages and limitations of these frameworks based on their unique attributes.

Build and performance

Comparing the performance of these frameworks with a basic profile page would not provide a comprehensive perspective, as their behavior might vary significantly in more complex applications.

To get around this limitation, I created a blog application displaying blog posts from the JSONPlaceholder API. The application employs server-side rendering (SSR) for both the Astro + Svelte combination and SvelteKit.

Subsequently, the following Lighthouse scores were recorded for the Astro + Svelte combination: Screenshot Of Lighthouse Scores For Demo App Built With Astro And Svelte Combo In comparison, using SvelteKit generated the following scores: Screenshot Of Lighthouse Scores For Demo App Built With Sveltekit Analyzing the outcomes above, it's evident that both frameworks deliver satisfactory performance. Looking more closely, we can see the Astro + Svelte combination yielded the following performance metrics:

  • First Contentful Paint (FCP): 1.4s
  • Largest Contentful Paint (LCP): 1.4s
  • Total Blocking Time: 0ms
  • Cumulative Layout Shift: 0

Meanwhile, SvelteKit delivered the following performance metrics:

  • First Contentful Paint (FCP): 0.9s
  • Largest Contentful Paint (LCP): 0.9s
  • Total Blocking Time: 40ms
  • Cumulative Layout Shift: 0

These figures indicate that SvelteKit slightly outperforms Astro + Svelte in terms of First Contentful Paint and Largest Contentful Paint times. However, Astro + Svelte has the advantage for zero Total Blocking Time, providing smoother interactivity.

Furthermore, the Astro + Svelte combination exhibits a higher level of consistency across both mobile and desktop platforms, which SvelteKit does not.

You should also explore the source code for both the Astro + Svelte blog and the SvelteKit version to gain valuable insights into their distinct approaches and structures.

Routing mechanism

Astro is a multi-page application framework, while SvelteKit operates as a single-page application framework, leading to differences in their application scopes. Nevertheless, let's delve into their routing and page rendering mechanisms for a detailed comparison.

Both Astro and SvelteKit utilize file-based routing. However, when working with Astro + Svelte, the process involves creating distinct Svelte components that are subsequently imported into Astro pages.

Moreover, if your Svelte component employs client-side JavaScript, Astro mandates the specification of hydration behavior through its client directives. This level of granularity offers finer control over the hydration process within Astro.

Furthermore, both frameworks provide SSR capabilities. However, when it comes to statically generated routes (SSG), Astro's approach stands out for its simplicity through the utilization of the getStaticPaths() method.

For example, the dynamic route below will generate static HTML pages for each of the blog posts retrieved from the JSONPlaceholder API:

---
// src/pages/blog/[id].astro

export async function getStaticPaths() {
  const data = await fetch("https://jsonplaceholder.typicode.com/posts").then(
    (response) => response.json()
  );

  return data.map((post) => {
    return {
      params: { id: post.id },
      props: { post },
    };
  });
}

const { id } = Astro.params;
const { post } = Astro.props;
---

<h1>{post.title}</h1>
<p>{post.body}</p>
Enter fullscreen mode Exit fullscreen mode

On the other hand, SvelteKit's implementation requires the incorporation of an SSG adapter and supplementary configuration to enable similar functionality.

Additionally, while SvelteKit route pages exclusively process .svelte files, Astro routes can include .md, .mdx, and .html files without extra configuration.

Data fetching

Both frameworks present distinct approaches to data fetching within route pages. Astro enables direct access to route information and data fetching within the page file itself. In contrast, SvelteKit introduces a more separated approach:

.
└── sample-page
    ├── +page.js OR +page.server.js
    └── +page.svelte
Enter fullscreen mode Exit fullscreen mode

As depicted above, in SvelteKit, you access route information, perform data fetching, and export the required data within the +page.js or +page.server.js file. You can then access the exported data in the corresponding +page.svelte file.

While Astro can achieve a similar level of separation, SvelteKit explicitly emphasizes this separation of concerns.

Furthermore, when combining Astro and Svelte, fetching data from Svelte components and importing the component into your Astro pages may result in partial hydrations.

Developer experience

Astro's developer experience offers a significant advantage to developers with its streamlined third-party library integration. You can integrate libraries easily via the one-line installer using the astro add command.

We previously experienced this straightforward process when adding Svelte and Tailwind to our application. It not only covers a variety of packages, but it also allows for the creation of custom integrations. SvelteKit, on the other hand, lacks a comparable feature.

Astro also improves the development process by including TypeScript support and seamless markdown rendering. When working with SvelteKit, however, such features would typically necessitate additional configurations.

One drawback in Astro's developer experience is that improper client directive specification in Astro + Svelte can lead to partial hydration issues and unexpected app behavior.

Comparison table: Astro + Svelte vs. SvelteKit

Check out the comparison table below highlighting the key similarities and differences between Astro + Svelte and SvelteKit:

Feature/Aspect Astro + Svelte SvelteKit
Routing mechanism File-based routing with Svelte components imported into Astro pages File-based routing with `.svelte` files
Meant for… Multi-page applications Primarily single-page applications
SSR & SSG support
SSG approach Utilizes getStaticPaths() for simple SSG Requires an SSG adapter and additional configuration
File types Supports `.svelte`, `.md`, `.mdx`, and `.html` files. Exclusively processes `.svelte` files.
Data fetching Direct access to route information and data fetching within the page file Separated approach with +page.js or +page.server.js for data fetching
Hydration Allows fine-grained control over hydration through client directives No explicit hydration control
Partial hydration Allows for partial hydration when combining with Svelte components No explicit feature for partial hydration
Developer experience One-line installer `astro add` for third-party libraries No built-in one-line installer for third-party libraries
TypeScript and Markdown support Includes TypeScript support and seamless Markdown rendering Requires additional configurations for TypeScript and Markdown support.

You can refer to this table to help inform your choice as you consider whether using SvelteKit or Astro with Svelte is best for your project’s scope and requirements.

Conclusion

In this article, we explored both Astro + Svelte and SvelteKit, delving into their respective initiation processes and distinguishing characteristics in a variety of areas.

As you might expect, the choice between Astro + Svelte and SvelteKit comes down to the nature of your intended application and your personal preferences.

If your project involves content-centric features such as blogs or similar scenarios, Astro + Svelte is a strong contender. SvelteKit, on the other hand, is an appealing option if your goal is to create performant, interactive applications that heavily rely on client-side JavaScript for complex interactions.

Thanks for reading!

Top comments (0)