
npm create astro@latest -- --template <example-name>
| Next.js나 Remix | Astro |
|---|---|
| 성능 문제를 해결해야 하는 곳에서만 부분적으로 SSR을 사용 | 필요한 경우에만 부분적으로 CSR 사용 |
| SPA로 페이지 로드 후에야 콘텐츠 동적 생성-> TTI(Time To Interaction)에 악영향 | MPA 지원 |
| 첫 로딩 성능이 중요한 콘텐츠 중심 웹사이트에는 좋지 않음 | SSR를 적극적으로 활용하여 콘텐츠가 많은 동적 웹사이트를 고성능으로 제작 가능 |
🤔 근데 Next.js도 필요한 곳에서만 use client쓰지 않나?
일반적으로 CSR은 초기 페이지 로드 후 전체 컴포넌트 트리를 로드하고 렌더링한다.
-> 단순하고 강력함.
-> 클라이언트 측 JS사용이 많아 페이지 로드 성능 문제 존재.
그러나 부분 수화는 필요한 부분만 로드 및 렌더링한다!
-> 선택적이고 전략적인 수화.
-> 이것을 이용한 패턴이 컴포넌트 아일랜드 패턴.
클라이언트와 상호작용하는 대화형 ui 컴포넌트.
-> 이것이 astro가 웹 사이트를 빠르게 유지하는 비결!
<MyReactComponent1 /> //SSR 아일랜드
<MyReactComponent2 client:지시어 /> //CSR 아일랜드
Astro에 의해 자동으로 빌드되고 처리되는 디렉터리
콘텐츠 컬렉션 및 선택적 컬렉션 구성 파일 저장
-> 그 외에 다른 파일이 허용되지 않음!
필수 하위 디렉터리
-> 이 디렉터리가 존재하지 않으면 사이트의 페이지나 경로 또한 존재하지 않는다!
빌드 프로세스 중 처리할 필요가 없는 정적 파일들로, 그대로 빌드 폴더에 복사됨
Astro 프로젝트의 기본 구성 요소.
astro는 코드 펜스를 이용하여 컴포넌트 스크립트를 식별한다.
-> 코드 펜스로 감싸진 부분은 클라이언트 측에서 실행되지 않는, 즉 사용자 브라우저로 전송되지 않는 부분.
-> 따라서 해당 부분에 비공개 데이터베이스 호출이나 비용이 많이 드는 코드를 작성할 수 있다.
코드 펜스 아래에 있는 부분. 컴포넌트의 html 출력을 결정한다
---
// 컴포넌트 스크립트
import SomeAstroComponent from '../components/SomeAstroComponent.astro';
import SomeReactComponent from '../components/SomeReactComponent.jsx';
import someData from '../data/pokemon.json';
// `<X title="안녕하세요!" />`
const { title } = Astro.props;
const data = await fetch('SOME_SECRET_API_URL/users').then((r) => r.json());
---
//컴포넌트 템플릿
<Banner />
<h1>안녕하세요!</h1>
<p>{title}</p>
<ReactPokemonComponent client:visible />
<ul>
{myFavoritePokemon.map((data) => <li>{data.name}</li>)}
</ul>
<p class:list={['add', 'dynamic', { classNames: true }]}></p>
외부 HTML콘텐츠를 위한 공간.
map에서 슬롯 name을 동적으로 생성하는 것은 불가능!
//Wrapper.astro
---
import Header from './Header.astro';
import Footer from './Footer.astro';
const { title } = Astro.props;
---
<div id="content-wrapper">
<Header />
<slot name="after-header" />
<h1>{title}</h1>
<slot>
<p>이것은 슬롯에 전달된 하위 요소가 없는 경우 렌더링 될 대체 콘텐츠입니다.</p>
</slot>
<Footer />
<slot name="after-footer" />
</div>
//fred.astro
---
import Wrapper from '../components/Wrapper.astro';
---
<Wrapper title="Fred's Page">
<img src="https://my.photo/fred.jpg" slot="after-header" />
<p>My name is Fred</p>
<p slot="after-footer">Copyright 2023</p>
</Wrapper>
드릴링을 고려할 필요가 없어졌지만, 동시에 슬롯 관리 및 정리를 잘 해야 할 듯..🤔
Astro는 파일 기반 라우팅 시스템을 채택했다!
웹사이트의 모든 페이지에 대해 라우팅, 데이터 불러오기, 전체 페이지 레이아웃 처리를 수행
<a href="/authors/sonali/"/> // https://example.com/authors/sonali
Astro 컴포넌트와 동일한 기능을 지원하는 html문서
-> DOCTYPE html, head 태그가 자동으로 포함된다
---
---
<html lang="ko">
<head>
<title>나의 홈페이지</title>
</head>
<body>
<h1>제 웹사이트에 오신 것을 환영합니다!</h1>
</body>
</html>
마크다운을 쓸 수 있다는게 블로그에 정말 최적화된듯...😳
---
layout: '../layouts/MySiteLayout.astro'
title: '나의 Markdown 페이지'
---
# 제목
이 페이지는 **Markdown**으로 작성되었습니다.
404.astro나 404.md 로 만들 수 있음
부분적 페이지를 이용하여 새로고침이나 페이지 탐색 없이 동적으로 HTML 섹션을 불러올 수 있다.
-> 머 어케 쓰는거지 그냥 저대로 컴포넌트 만들면 되나
---
export const partial = true;
---
<li>부분적 페이지</li>
UI 구조를 제공하는 Astro 컴포넌트
---
import BaseLayout from './BaseLayout.astro';
const { frontmatter } = Astro.props;
---
<BaseLayout url={frontmatter.url}>
<h1>{frontmatter.title}</h1>
<h2>게시물 작성자: {frontmatter.author}</h2>
<slot />
</BaseLayout>
script 태그 안에서 순수js처럼 구현해야 함!
---
const handleClick = () => {
console.log("버튼이 클릭되었습니다!");
}
---
<button onClick={handleClick}>클릭해도 아무 일도 일어나지 않습니다!</button>
<button id="button">클릭하세요</button>
<script>
const handleClick = () => {console.log("버튼이 클릭되었습니다!");}
document.getElementById("button").addEventListener("click", handleClick);
</script>
---
import MyComponent from "./MyComponent.astro";
const Element = 'div'
const Component = MyComponent;
---
<Element>안녕하세요!</Element> // <div>안녕하세요!</div>
<Component /> // <MyComponent />
<div className="box" dataValue="3" /> // X
<div class="box" data-value="3" /> // O
---
---
<!-- html 주석은 브라우저 Dom구조에 포함된다 -->
{/* JS 주석은 포함되지 않는다 */}
빌드시 모든 페이지 경로에 대한 사전 렌더링 수행
요청 시 렌더링(SSR)을 포함하는 모드.
대부분 또는 모든 경로가 주문형 경로로 구성된 매우 동적인 사이트를 위한 옵션
일부 주문형 경로가 포함된 거의 정적인 사이트를 위한 옵션