惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
J
Java Code Geeks
Martin Fowler
Martin Fowler
宝玉的分享
宝玉的分享
V
Visual Studio Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
M
MIT News - Artificial intelligence
U
Unit 42
博客园 - 三生石上(FineUI控件)
博客园 - 聂微东
The GitHub Blog
The GitHub Blog
I
InfoQ
WordPress大学
WordPress大学
H
Help Net Security
D
Docker
B
Blog
腾讯CDC
A
About on SuperTechFans
Recent Announcements
Recent Announcements
雷峰网
雷峰网
有赞技术团队
有赞技术团队
C
Check Point Blog
Y
Y Combinator Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

Netlify Developers

AI model comparison using Netlify's AI Gateway | Netlify Developers Build an AI agent to automatically process and summarize form submissions | Netlify Developers Build an AI agent to automatically generate relevant images for blog posts | Netlify Developers Prerendering SPA content pages to enable AI agent access | Netlify Developers Identify image optimization opportunities with Netlify Observability | Netlify Developers Fix top 404 page not found errors with Netlify Observability | Netlify Developers Introducing AI Gateway: built-in AI model access on Netlify | Netlify Developers Introducing Observability: your project insights on Netlify | Netlify Developers From first publish to first update with AI agents | Netlify Developers How to use Agent Runners on Netlify | Netlify Developers Add forms to your project with AI + Netlify | Netlify Developers Track Real User Metrics | Netlify Developers Lighthouse performance scores on Netlify | Netlify Developers Review your AI project before you ship | Netlify Developers Using environment variables in AI Projects on Netlify | Netlify Developers Build prototypes and MVPs fast with AI + Netlify | Netlify Developers Pause auto-publishing on Netlify | Netlify Developers Run serverless functions, storage, and more natively in Nuxt dev | Netlify Developers Netlify Office Hours: The AX Arcade challenge | Netlify Developers Netlify Office Hours: Prompting with style | Netlify Developers Netlify Office Hours: RAG Apps with OpenAI + Netlify DB | Netlify Developers How to build a RAG application with Neon, Netlify & OpenAI | Netlify Developers Netlify Office Hours: Netlify DB (powered by Neon) | Netlify Developers Netlify Office Hours: Netlify MCP Server | Netlify Developers Netlify Office Hours: Netlify Vite Plugin | Netlify Developers Building MCPs with Netlify | Netlify Developers Deploying sites from your AI tool | Netlify Developers Adding your domain using Netlify API | Netlify Developers Build a context driven chat bot with Netlify Blob and OpenAI | Netlify Developers Simplify deployments with Netlify’s branch-matching environment variables | Netlify Developers
Adding resumability to Astro with Qwik | Netlify Developers
2024-03-13 · via Netlify Developers

Astro avoids shipping any JavaScript to the client by default. However, there are occasions when client-side JavaScript is necessary. While Vanilla JS remains a viable option, frameworks are often preferred for their ability to address various challenges and streamline development processes, offering faster solutions for more complex use cases. Qwik takes an interesting approach to this, and boasts some interesting benefits. Let’s explore!

Quick

Qwik is the first framework that has similar DX (Developer Experience) as React, Vue, or Svelte in how you author components, while delivering Live HTML that is instantly interactive. Qwik achieves this property by completely removing the need for hydration. Instead, Qwik applications immediately execute the event handlers on user interaction, without having to bootstrap all the app state. This technique is called Resumability. — Qwik

#TL;DR

Within this guide, you’ll discover how to develop an Astro site leveraging Qwik’s Astro integration for client-side JavaScript functionality, as well as the process for deploying to Netlify. We’ll also explore some of the mechanics available and start building Qwik components.

#An example site

You can see a preview of the deployed site and the repository for the code on the following links.

Just deploy and play

We’re going to get into some details here, but if you’d rather simply clone and deploy this example site right away, and then explore your newly cloned code, you can do that by clicking the button below.

Deploy to Netlify

#Getting started with Astro

To get started with Astro run the following:

If you prefer you can install Astro manually.

With an Astro site created you can commit the changes, push to your remote repository and deploy to Netlify.

#Deploy with Netlify

Creating a new Astro site on Netlify is simple. Once you’ve logged in, you’ll be taken to https://app.netlify.com. Click “Add new site” to add a new site, follow the on-screen steps and all the default settings will be completed for you.

For more information about deploying, you can read our Get Started with Netlify guide.

#Install the Qwik Astro integration

To install the integration run the following, then follow the instructions in your terminal.

npm install @qwikdev/astro

The repository README contains more detailed installation information.

After a successful install you should see the following changes have been made to your astro.config.mjs.

// astro.config.mjs

import { defineConfig } from "astro/config";

import qwikdev from "@qwikdev/astro";

export default defineConfig({

integrations: [qwikdev()],

});

If you’re using TypeScript with Astro be sure to also update your tsconfig.json with the following.

{

"extends": "astro/tsconfigs/base",

"compilerOptions": {

"jsx": "react-jsx",

"jsxImportSource": "@builder.io/qwik"

}

}

#Creating your first Qwik component

In the following code snippet you’ll create a button that, when clicked, will call a function that updates a counter value stored using Qwik’s useSignal Hook.

When signal values are updated, the component will re-render and the updated value will be displayed.

// src/components/counter-example.tsx

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

const CounterExample = component$(() => {

const counter = useSignal<number>(0);

const handleUpdate = $(() => {

counter.value++;

});

return (

<>

<h2>{counter.value}</h2>

<button onClick$={handleUpdate}>update counter</button>

</>

);

});

export default CounterExample;

#Import and display

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, … with zero effort on the developer. — Adding Qwik

As such, Qwik components don’t require Astro’s Client Directives. To see your new component import and return it in an Astro page.

// src/pages/counter.astro

---

import CounterExample from '../components/counter-example';

---

<html>

<body>

<h1>Getting Started with Netlify Astro and Qwik</h1>

<CounterExample />

</body>

</html>

#Your first Qwik component explained

If you’re new to Qwik there are a few things to understand.

#component$

All Qwik components are wrapped with component$. This allows Qwik’s optimizer to break them down and lazy-load them.

You can read more about components in the Qwik docs.

#useSignal()

To update a signal, you apply changes directly to the .value. In the above example you are updating the value of the counter variable by using counter.value++.

You can read more about useSignal in the Qwik docs.

#Event handlers $

Similar to the component declaration, event handlers are also wrapped with a variation of the $ syntax. Eg. $(...).

You can read more about reusing event handlers in the Qwik docs.

#Event$

Qwik events are broadly the same as native JavaScript events, e.g onclick, but all will require the trailing $ syntax. E.g onClick$.

There are however some notable exceptions, for example onchange is onInput$.

You can read more about events in the Qwik docs.

#Beyond the basics

The above example demonstrates a simple use of Qwik to define and manage client-side state, but Qwik can do so much more. Below you’ll find some examples of common requirements.

#useStore()

useStore() is similar to useSignal() but is used when the state values are more complex than a single primitive. In the following code snippet you’ll create a component that contains an HTML select element that updates a store value, and a modified version of the counter, but this time instead of incrementing a number, you’ll push a new Rocket emoji to an array.

// src/components/emoji-example.tsx

import { component$, useStore, $ } from "@builder.io/qwik";

const EmojiExample = component$(() => {

const store = useStore<{ astronaut: string; rockets: string[] }>({

astronaut: "",

rockets: [],

});

const handleAstronaut = $((_: Event, currentTarget: HTMLSelectElement) => {

store.astronaut = currentTarget.value;

});

const handleRocket = $(() => {

store.rockets.push("🚀");

});

return (

<>

<p>

<span role="img" aria-label="Astronaut">

{store.astronaut}

</span>

</p>

<label>

astronaut:

<select onInput$={handleAstronaut}>

<option hidden>please select</option>

<option value="🧑‍🚀">🧑‍🚀 Astronaut</option>

<option value="👨‍🚀">👨‍🚀 Man Astronaut</option>

<option value="👩‍🚀">👩‍🚀 Woman Astronaut</option>

</select>

</label>

<hr />

<button onClick$={handleRocket}>add rocket</button>

<ol>

{store.rockets.map((data) => {

return (

<li>

<span role="img" aria-label="Rocket">

{data}

</span>

</li>

);

})}

</ol>

</>

);

});

export default EmojiExample;

Unlike useSignal, with useStore you update the value directly, rather than accessing the value using .value.

In this example the handleRocket function uses .push() to add a new Rocket emoji to the store value named rockets, which is typed as an array of strings.

The handleAstronaut function sets the store value named astronaut to equal that of the currentTarget.value.

You can read more about useStore in the Qwik docs.

A note on currentTarget

Qwik requires the use of an additional argument to access the currentTarget.value. Since event handling is asynchronous. The more common practice of using event.target.value can’t be used with Qwik.

#useVisibleTask()

useVisibleTask() is one of Qwik’s built-in methods and is only invoked when a component is within the viewport. If a component is not within the viewport Qwik won’t attempt to perform any actions contained within the function body. This can be helpful for client-side fetch requests where you don’t want to fetch data for UI elements the user can’t see.

// src/components/client-fetch-example.tsx

import { component$, useVisibleTask$, useStore } from "@builder.io/qwik";

const ClientFetchExample = component$(() => {

const store = useStore<{ full_name: string; title: string; html_url: string }>({

full_name: null,

title: null,

html_url: null,

});

useVisibleTask$(async () => {

try {

const response = await fetch("https://api.github.com/repos/BuilderIO/qwik/pulls/1", {

method: "GET",

});

if (!response.ok) {

throw new Error();

}

const json = await response.json();

const {

html_url,

title,

head: {

repo: { full_name },

},

} = json;

store.html_url = html_url;

store.title = title;

store.full_name = full_name;

} catch (error) {

console.error(error);

}

});

return (

<div>

{store.html_url ? (

<div>

<h2>{store.full_name}</h2>

<p>{store.full_name}</p>

<a href={store.html_url}>{store.html_url}</a>

</div>

) : (

<p>Loading...</p>

)}

</div>

);

});

export default ClientFetchExample;

In this example useVisibleTask is used to make a fetch request to the GitHub API and retrieve some data. If the request is successful the store values are updated with data from the response.

In the return statement, a loading message is displayed if the value of store.html_url is null.

You can read more about useVisibleTask in the Qwik docs.

#Server-side rendering

To enable server-side rendering in Astro you can use the Astro Netlify Adapter. There is also an option to use Netlify Edge Functions which you can see in the docs here: Running Astro middleware on Netlify Edge Functions.

After a successful installation you will need to make following changes to your astro.config.mjs.

// astro.config.mjs

import { defineConfig } from "astro/config";

import qwikdev from "@qwikdev/astro";

import netlify from "@astrojs/netlify";

export default defineConfig({

integrations: [qwikdev()],

output: "server",

adapter: netlify(),

});

#useTask()

With the Netlify adapter installed you can now use Qwik’s useTask to make server-side requests. However, Astro can also be used to make server-side data requests.

The below code is broadly the same as the useVisibleTask example, but the loading message has been removed since this data is requested and rendered on the server.

// src/components/server-fetch-example.tsx

import { component$, useVisibleTask$, useStore } from "@builder.io/qwik";

import { component$, useTask$, useStore } from "@builder.io/qwik";

const ClientFetchExample = component$(() => {

const ServerFetchExample = component$(() => {

const store = useStore<{full_name: string; title: string; html_url: string;}>({full_name: null, title: null, html_url: null});

useVisibleTask $(async () => {

useTask$(async () => {

try {

const response = await fetch('https://api.github.com/repos/BuilderIO/qwik/pulls/1', {

method: 'GET',

});

if (!response.ok) {

throw new Error();

}

const json = await response.json();

const {

html_url,

title,

head: {

repo: { full_name },

},

} = json;

store.html_url = html_url;

store.title = title;

store.full_name = full_name;

} catch (error) {

console.error(error);

}

});

return (

<div>

{store.html_url ? (

<div>

<h2>{store.full_name}</h2>

<p>{store.full_name}</p>

<a href={store.html_url}>{store.html_url}</a>

</div>

) : (

<p>Loading...</p>

)}

</div>

);

});

export default ClientFetchExample;

export default ServerFetchExample;

#You did it!

These are just a few examples of what you can achieve using Qwik. If you’re looking to continue your journey, why not explore the examples of state and tasks in the Qwik docs.