Skip to content

Commit

Permalink
Merge branch 'main' into patch-7
Browse files Browse the repository at this point in the history
  • Loading branch information
gioboa authored Jan 4, 2025
2 parents 3b02791 + e2b111a commit c4bc600
Show file tree
Hide file tree
Showing 50 changed files with 4,262 additions and 1,065 deletions.
5 changes: 5 additions & 0 deletions .changeset/fluffy-tools-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@builder.io/qwik': patch
---

docs: remove shop
5 changes: 5 additions & 0 deletions .changeset/warm-tools-tickle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@builder.io/qwik': patch
---

docs: add Qwik blog + articles
3 changes: 2 additions & 1 deletion packages/docs/public/_redirects
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,5 @@
/deployments/* /docs/deployments/:splat 308
/docs/advanced/i18n/ /docs/integrations/i18n/ 308
/docs/components/inline-components/ /docs/components/overview/ 308
/docs/think-qwik/ /docs/concepts/think-qwik/ 308
/docs/think-qwik/ /docs/concepts/think-qwik/ 308
/docs/env-variables/ /docs/guides/env-variables/ 308
10 changes: 8 additions & 2 deletions packages/docs/src/components/footer/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { QwikLogo } from '~/components/svgs/qwik-logo';
import { DiscordLogo } from '~/components/svgs/discord-logo';
import { GithubLogo } from '~/components/svgs/github-logo';
import { TwitterLogo } from '~/components/svgs/twitter-logo';
import { BlueskyLogo } from '~/components/svgs/bluesky-logo';

const baseUrl = 'https://qwik.dev';
const linkColumns = [
Expand Down Expand Up @@ -51,7 +52,7 @@ export const Footer = component$(() => {
</div>
<div class="border border-b-0 border-current mt-2"></div>
<div class="flex justify-between items-end">
<p class="text-xs">MIT License © 2024</p>
<p class="text-xs">MIT License © {new Date().getFullYear()}</p>
<FooterSocialLinks />
</div>
</div>
Expand All @@ -66,7 +67,11 @@ export const FooterLinks = component$(() => {
{linkColumns.map((column, colIndex) => (
<div key={colIndex} class="flex flex-col gap-4 flex-1">
{column.map((link, linkIndex) => (
<a key={linkIndex} class="hover:text-interactive-blue z-[10]" href={link.href}>
<a
key={linkIndex}
class="text-[color:var(--text-color)] hover:text-interactive-blue z-[10]"
href={link.href}
>
{link.title}
</a>
))}
Expand All @@ -81,6 +86,7 @@ export const FooterSocialLinks = component$(() => {
{ href: 'https://qwik.dev/chat', title: 'Discord', Logo: DiscordLogo },
{ href: 'https://github.com/QwikDev/qwik', title: 'GitHub', Logo: GithubLogo },
{ href: 'https://twitter.com/QwikDev', title: 'Twitter', Logo: TwitterLogo },
{ href: 'https://bsky.app/profile/qwik.dev', title: 'Bluesky', Logo: BlueskyLogo },
];

return (
Expand Down
11 changes: 1 addition & 10 deletions packages/docs/src/components/header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,23 +91,14 @@ export const Header = component$(() => {
</a>
</li>
<li>
<a
href="/shop/"
class={{ active: pathname.startsWith('/shop') }}
aria-label="Qwik shop"
>
<span>Shop</span>
</a>
</li>
{/* <li>
<a
href="/blog/"
class={{ active: pathname.startsWith('/blog') }}
aria-label="Qwik blog"
>
<span>Blog</span>
</a>
</li> */}
</li>
<li>
<DocSearch
appId={import.meta.env.VITE_ALGOLIA_APP_ID}
Expand Down
20 changes: 20 additions & 0 deletions packages/docs/src/components/svgs/bluesky-logo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
interface Props {
width: number;
height: number;
}

export const BlueskyLogo = ({ width, height }: Props) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width={width}
height={height}
viewBox="0 -3.268 64 68.414"
role="img"
aria-label="Bluesky Logo"
>
<path
class="fill-[var(--text-color)]"
d="M13.873 3.805C21.21 9.332 29.103 20.537 32 26.55v15.882c0-.338-.13.044-.41.867-1.512 4.456-7.418 21.847-20.923 7.944-7.111-7.32-3.819-14.64 9.125-16.85-7.405 1.264-15.73-.825-18.014-9.015C1.12 23.022 0 8.51 0 6.55 0-3.268 8.579-.182 13.873 3.805zm36.254 0C42.79 9.332 34.897 20.537 32 26.55v15.882c0-.338.13.044.41.867 1.512 4.456 7.418 21.847 20.923 7.944 7.111-7.32 3.819-14.64-9.125-16.85 7.405 1.264 15.73-.825 18.014-9.015C62.88 23.022 64 8.51 64 6.55c0-9.818-8.578-6.732-13.873-2.745z"
/>
</svg>
);
2 changes: 1 addition & 1 deletion packages/docs/src/components/svgs/discord-logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ export const DiscordLogo = ({ width, height }: DiscordLogoProps) => (
height={height}
viewBox="0 0 512 512"
role="img"
fill="currentColor"
aria-label="Discord Logo"
class="fill-[var(--text-color)]"
>
<path d="M464 66.52A50 50 0 00414.12 17L97.64 16A49.65 49.65 0 0048 65.52V392c0 27.3 22.28 48 49.64 48H368l-13-44 109 100zM324.65 329.81s-8.72-10.39-16-19.32C340.39 301.55 352.5 282 352.5 282a139 139 0 01-27.85 14.25 173.31 173.31 0 01-35.11 10.39 170.05 170.05 0 01-62.72-.24 184.45 184.45 0 01-35.59-10.4 141.46 141.46 0 01-17.68-8.21c-.73-.48-1.45-.72-2.18-1.21-.49-.24-.73-.48-1-.48-4.36-2.42-6.78-4.11-6.78-4.11s11.62 19.09 42.38 28.26c-7.27 9.18-16.23 19.81-16.23 19.81-53.51-1.69-73.85-36.47-73.85-36.47 0-77.06 34.87-139.62 34.87-139.62 34.87-25.85 67.8-25.12 67.8-25.12l2.42 2.9c-43.59 12.32-63.44 31.4-63.44 31.4s5.32-2.9 14.28-6.77c25.91-11.35 46.5-14.25 55-15.21a24 24 0 014.12-.49 205.62 205.62 0 0148.91-.48 201.62 201.62 0 0172.89 22.95s-19.13-18.15-60.3-30.45l3.39-3.86s33.17-.73 67.81 25.16c0 0 34.87 62.56 34.87 139.62 0-.28-20.35 34.5-73.86 36.19z" />
<path d="M212.05 218c-13.8 0-24.7 11.84-24.7 26.57s11.14 26.57 24.7 26.57c13.8 0 24.7-11.83 24.7-26.57.25-14.76-10.9-26.57-24.7-26.57zM300.43 218c-13.8 0-24.7 11.84-24.7 26.57s11.14 26.57 24.7 26.57c13.81 0 24.7-11.83 24.7-26.57S314 218 300.43 218z" />
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/src/components/svgs/github-logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ export const GithubLogo = ({ width, height }: GithubLogoProps) => (
viewBox="0 0 16 16"
width={width}
height={height}
fill="currentColor"
role="img"
aria-label="GitHub Logo"
class="fill-[var(--text-color)]"
>
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z" />
</svg>
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/src/components/svgs/twitter-logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ export const TwitterLogo = ({ width, height }: TwitterLogoProps) => (
height={height}
viewBox="0 0 512 512"
role="img"
fill="currentColor"
aria-label="Twitter Logo"
class="fill-[var(--text-color)]"
>
<path d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8L200.7 275.5 26.8 48H172.4L272.9 180.9 389.2 48zM364.4 421.8h39.1L151.1 88h-42L364.4 421.8z" />
</svg>
Expand Down
157 changes: 157 additions & 0 deletions packages/docs/src/routes/(blog)/blog/(articles)/astro-qwik/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
---
title: 'Astro + Qwik: Houston, we have Resumability!'
authorName: 'Jack Shelton'
tags: ['Qwik']
date: 'November 8, 2023'
canonical: 'https://www.builder.io/blog/astro-qwik'
---

import { ArticleBlock } from '~/routes/(blog)/blog/components/mdx/article-block';
import CodeSandbox from '~/components/code-sandbox/index.tsx';

<ArticleBlock>

Hey Devs! My name is [Jack](https://twitter.com/TheJackShelton), and I am a freelance fullstack developer based in Texas. I also work on this thing called [Qwik UI](https://qwikui.com/) in my free time. 🙂

## The problem

In mid-late 2022, I had the opportunity to try [Astro](https://astro.build/), a server-first, content-focused, and extremely flexible meta-framework on my day job.

It quickly became my go-to for creating landing pages, marketing websites, and even small web apps. If my clients needed something, it was almost always a click and integration guide away.

![An image of a rocket on a notebook in space.](https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2Fed9d96db1222462b89baf4f03e80617e?width=707)

Astro sites significantly outperformed the previous static site generators I had used. I appreciated the speed and found it intuitive to work with.

Unfortunately, as I added more interactivity, my Astro sites began to slow down, despite Astro being the fastest meta-framework I had used up to that point!

My clients and I took notice of this. I spent a lot of time researching how to improve site speed, but in the end it always felt like an uphill battle of optimizing versus adding the stuff my clients needed.

## The journey

In an ideal world, you could build your application, and it would be extremely fast, regardless of the level of interactivity or the size of your page. This appears to be an unsolvable problem. The more components we add, the slower it gets.

I wondered, did it have to be this way? Is it even possible to have a fast and easy development process? Is it the [developer’s fault](https://www.builder.io/blog/dont-blame-the-developer-for-what-the-frameworks-did) when our apps are slow?

Looking back, I’d say no! Developers should focus on what matters most: building the product! So, how do we solve this issue? For a while, it was a big what if. 😅

That what if quickly became a reality when I discovered Qwik’s [resumability](https://www.builder.io/blog/resumability-from-ground-up). I was 100% certain it was exactly what I was looking for.

So I did some research. I saw a lot of comparisons between the two in terms of performance. April this year I thought “why don’t we use them together?” One is a meta-framework, and the other a UI framework.

Would it still be resumable?

Is Astro’s partial hydration approach going to be a problem with a framework that doesn’t have [hydration](https://www.builder.io/blog/hydration-is-pure-overhead)?

How would it work with islands?

Well, turns out I wasn’t the only one!

![A screenshot of a Discord chat between Misko and Jack.](https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F988e08cd27f34323b77b937432ed88d5?width=707)

After some awesome help from Misko, creator of Angular and Qwik, as well as the Astro core team, I can finally answer that question I had back in April.

## Introducing @qwikdev/astro:

Astro’s first resumable UI framework.

### Starts fast, stays fast

One of Astro's key features is **Zero JS, by default**.

Unfortunately, this is usually not the case after adding a JavaScript framework and any subsequent components.

If we want to introduce interactivity with a framework, such as React, Vue, Svelte, and so on, the framework runtime is then introduced. The number of components added to the page also increases linearly O(n) with the amount of JavaScript.

### Adding Qwik

Qwik builds on top of Astro's **Zero JS, by default** principle and then some. Thanks to resumability, the components are not executed unless resumed. Even with interactivity, the framework is also not executed until it needs to be. [It is O(1) constant](https://www.builder.io/blog/our-current-frameworks-are-on-we-need-o1), … with zero effort on the developer.

![An Illustration of hydration vs resumability.](https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F41f896cda32b43279d7c32ee6725c79f?width=707)

This integration for Astro enables resumability, fine-grained lazy loading, and many of the Qwik core stuff we know and love.

This includes all of the Astro goodies, like view transitions, MDX collections, and the hundreds of integrations that Astro provides.

**So where would @qwikdev/astro make sense?**

You can use it anywhere you’re currently using a framework component in Astro! Using Qwik and resumability should significantly speed up your site.

### Do Qwik components need hydration directives?

Short answer, no!

In other UI frameworks, a hydration directive, such as `client:only` or `client:load`, would be needed for interactivity. However, these are not needed with Qwik because there is no hydration!

When using Qwik inside a meta-framework like Astro or Qwik City, components are loaded on the server, prefetched in a separate thread, and "resumed" on the client.

For example, here's how we use a Qwik counter component in Astro.

**counter.tsx**

```tsx
import { component$, useSignal } from "@builder.io/qwik";

export const Counter = component$(() => {
const counter = useSignal(0);

return <button onClick$={() => counter.value++}>{counter.value}</button>;
});
```

**index.astro**

```tsx
---
import { Counter } from "../components/counter";
---

<html lang="en">
<body>
<h1>Astro.js - Qwik</h1>
/* no hydration directive! */
<Counter />
</body>
</html>
```

### Does resumability work?

Yes! We can lazily execute code on interaction, just like using Qwik with Qwik City.

<video muted loop autoplay>
<source src="https://cdn.builder.io/o/assets%2FYJIGb4i01jvw0SRdL5Bt%2F7be046307ece4278a81789e386737813%2Fcompressed?apiKey=YJIGb4i01jvw0SRdL5Bt&token=7be046307ece4278a81789e386737813&alt=media&optimized=true" type="video/mp4"/>
</video>

Here, we are refreshing the page, and you'll notice that nothing was executed until the button was clicked. Without resumability, our `<counter></counter>` component would have been executed on page load.

The 402 byte q-chunk is our Counter's `onClick$` handler.

### What's in that 17.61kb chunk?

That's the framework! We do not execute it until it is needed. In this case, it is gzipped using SSG.

**How about islands?**

Instead of islands, we have Qwik containers! These fit quite well into Astro’s island model, having similar limitations.

Below is an example of a Qwik container in Astro. In the DOM, you'll notice there aren't any custom elements. This is because, to Astro, Qwik appears as static data.

![Untitled](https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F1f8b5720be2b4157a614b754abd8f041?width=707)

This is just the beginning! You can try out the integration in Alpha today, by running:

```bash
npx astro add @qwikdev/astro
```

> This integration is currently in Alpha release. We encourage you to try it and share your feedback.<br></br>If you run into any problems, open up an issue in our [GitHub Repository](https://github.com/QwikDev/astro/issues).
You can also view the package on [NPM](https://www.npmjs.com/package/@qwikdev/astro), [Github](https://github.com/QwikDev/astro), [Qwik integration page](https://qwik.dev/docs/integrations/astro/), and the [Astro integration page](https://astro.build/integrations/?search=qwik).<br></br>
Join the fun and [contribute](https://github.com/QwikDev/astro/blob/main/contributing.md)!

Stay awesome devs,

-Jack

</ArticleBlock>
Loading

0 comments on commit c4bc600

Please sign in to comment.