Astroざっくり触ってみた フロントエンド定例 2022/11/11

tanifumiya|2022年11月11日
フロントエンド

こんにちは、フロントエンドチームの 谷(@high_g_engineer)です。
今週のフロントエンド定例の内容を記載します。

フロントエンド定例について、以前の記事(ランサーズのフロントエンドチームが取り組んでいること)でお伝えしたのですが、毎週金曜日に開催しており、実際の業務で取り組んでいることや気になった技術情報等をシェアしあう会になっています。

以下、今週の内容です。

Astroざっくり触ってみた

モチベーション

Astroの雰囲気を理解する。

概要

2022/8/9 Astro v1.0 がリリースされました。
https://astro.build/blog/astro-1/

以下、公式からの掲載

Astroとは?

Astroは、コンテンツにフォーカスした高速なWebサイトを構築するためのオールインワンWebフレームワークです。

主な特長

  • サーバーファーストのAPI設計: ユーザーのデバイスから高コストのハイドレーションをなくします。(MPAフレームワーク)
  • デフォルトでゼロJS: サイトを遅くするJavaScriptランタイムオーバーヘッドはありません。
  • エッジ対応: DenoやCloudflareのようなグローバルなエッジを含め、どこでもデプロイできます。
  • カスタマイズ可能: Tailwind、MDX、その他100以上のインテグレーションから選択可能です。
  • 特定のUIに依存しない: React、Preact、Svelte、Vue、Solid、Litなどをサポートします。
  • コンポーネントアイランド: 高速なウェブサイトを構築するための新しいウェブアーキテクチャー。

Astroアイランド
https://docs.astro.build/ja/concepts/islands/

それぞれのコンポーネントをReact, Vueなど別々のアーキテクチャでのコンポーネントにすることが可能

環境構築

インストール

npm create astro@latest
or
yarn create astro

エディタのセットアップ

https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode

ディレクトリ構成

src/* – プロジェクトソースコード(コンポーネント、ページ、スタイルなど)
|- components – layouts, pagesに属さない雑多なコンポーネント
|- layouts – 全体のレイアウトを担うコンポーネント
|- pages – ページを担うコンポーネント。ファイル名とルーティングと一致する様になっている。
public/* – コード以外の処理不要のアセット(フォント、アイコンなど)
astro.config.mjs – Astroの設定ファイル
package.json
tsconfig.json

コード記述

基本的に、.astroという拡張子のファイルを利用しますが、.md, .mdx, .html. js, .tsなどのコンポーネントもサポートしています。

書式

— で、jsとhtml, cssを記述する箇所を分ける形です。
かなりデフォルトのhtml, cssに近い形で記述が可能で、jsの記述もスマートにできます。

---
// コンポーネントスクリプト (JavaScript)
---

<!-- コンポーネントテンプレート (HTML + JS Expressions) -->

属性

classNameがclass、data属性もdata-◯◯の形で書く。標準的。

<div className="box" dataValue="3" />
<div class="box" data-value="3" />

コメント

{/* */} だけでなく、htmlコメントも可能

<!-- .astroファイルではHTMLコメント構文が有効です -->
{/* この形式もok */}

props, js変数利用

propsは、Astro.propsで受け取ることが可能
jsで定義したローカル変数をhtml側で展開する場合は、Reactと同じ様に {} で展開可能です。

---
const { greeting, name } = Astro.props;
---
<h2>{greeting}、{name}!</h2>

import

components/ や layouts/ で定義したコンポーネントをjs側でimportで利用して
そのままhtml側で <Component> の形で利用出来るのはかなりスマートです。

---
import Layout from '../layouts/Layout.astro'
---

<Layout title="Welcome to Astro.">
...
</Layout>

slot

Reactで言うところのchildren

---
const { title } = Astro.props
---
<div id="content-wrapper">
  <h1>{title}</h1>
  <slot /> <!-- 子要素はここに入ります -->
</div>

slotがない場合の表示設定

---
const { title } = Astro.props
---
<div id="content-wrapper">
  <h1>{title}</h1>
  <slot>
    <p>スロットがない場合の表示</p>
  </slot>
</div>

配列データの描画

配列を要素として描画するときはReactと同じ様な記述。フラグメントも利用可能

---
const items = ["犬", "猫", "カモノハシ"];
---
<ul>
  {items.map((item) => (
    <>
      <li>赤い{item}</li>
      <li>青い{item}</li>
      <li>緑の{item}</li>
    </>
  ))}
</ul>

CSSの当て方

styleタグを利用します。
CSSのスコープはコンポーネント内にとどまります。

<h1>Hello, world!</h1>

<style>
h1 { color: red }
</style>

具体例

(例)Card.astro

---
export interface Props {
  title: string
  body: string
  href: string
}

const { href, title, body } = Astro.props
---

<li class="link-card">
  <a href={href}>
    <h2>
      {title}
      <span>→</span>
    </h2>
    <p>{body}</p>
  </a>
</li>
<style>
.link-card {
list-style: none;
display: flex;
padding: 0.15rem;
background-color: white;
}
</style>

(例)pages/inde.astro

---
import Layout from '../layouts/Layout.astro'
import Card from '../components/Card.astro'
---

<Layout title="Welcome to Astro.">
  <main>
    <h1>Welcome to <span class="text-gradient">Astro</span></h1>
    <p class="instructions">
      To get started, open the directory <code>src/pages</code> in your project.<br />
      <strong>Code Challenge:</strong> Tweak the "Welcome to Astro" message above.
    </p>
    <ul role="list" class="link-card-grid">
      <Card
        href="https://docs.astro.build/"
        title="Documentation"
        body="Learn how Astro works and explore the official API docs."
      />
    </ul>
  </main>
</Layout>

<style>
main {
  margin: auto;
  padding: 1.5rem;
  max-width: 60ch;
}
h1 {
  font-size: 3rem;
  font-weight: 800;
  margin: 0;
}
</style>

不満

以下が動作しません。

---
function handleClick () {
console.log("ボタンがクリックされました!");
}
---

<button onClick={handleClick}>クリックしても何も起きません!</button>

↓こう書かないとダメです。思いっきり命令的記述なので、ここはかなり体験が悪いです。。

---
---
<button id="button">Click Me</div>
<script>
function handleClick () {
console.log("ボタンがクリックされました!");
}
document.getElementById("button").addEventListener("click", handleClick);
</script>

まだ試せていないですが、Partial Hydrationでどうにかなるのでは?という気もしています。

https://zenn.dev/yend724/articles/20220701-430vndv085eh6xn2#partial-hydration%E3%81%A8%E3%81%84%E3%81%86%E3%82%B3%E3%83%B3%E3%82%BB%E3%83%97%E3%83%88

その他

エンドポイントを設定してAPIを作成したり、
デプロイしたりなどが試せていないので、今後試せたらと思います。

参考

https://docs.astro.build/ja/getting-started/

 

ランサーズでは、フロントエンドエンジニアを随時募集しておりますので、まずはお話でもという方はご連絡くださいませ!

フロントエンドエンジニア(本社)の採用情報 | ランサーズ株式

前回の定例内容はこちらから確認可能ですのでご興味いただければ下記のリンクから閲覧いただければと思います。

https://engineer.blog.lancers.jp/?s=フロントエンド定例