🦕

Deno製フレームワークAleph.js(beta)をmicroCMSで試す

2021/12/06に公開

この記事はmicroCMS Advent Calender 2021 3日目の記事です。

以前Next.jsインスパイアのDeno製フレームワークであるAleph.jsを紹介させていただきました。
https://zenn.dev/ryusou/articles/alephjs-microcms

この記事はその続きです。
Aleph.jsはこの数ヶ月でalpha版からbetaへとバージョンアップしています。
Next.jsインスパイアというわけあって、Next.jsの機能に追従しつつも独自に進化遂げていて個人的にとても注目しているフレームワークの1つです。

バージョンアップしてみる

前回の記事の時点のバージョンが v0.3.0-alpha.33 のalphaでした。
まずは雑にバージョンアップしてみようと思います。
この間Denoのバージョンも上がっているので、最新版をインストールしてみます。
バージョンを指定することで任意のバージョンをインストールすることもできます。

deno upgrade

今回検証したDenoのバージョンは以下の通りです。

deno 1.16.4 (release, aarch64-apple-darwin)
v8 9.7.106.15
typescript 4.4.2

Aleph.jsもバージョンアップしてみます。
最新バージョンをインストールします。

deno run -A https://deno.land/x/aleph/install.ts

バージョンは以下の通りです。

Aleph.js v0.3.0-beta.19

前回でも書いた通り、Aleph.jsでは、 import_map.json でバージョン管理することができるので以下のようにバージョンを上げます。
基本的にはURL+バージョン名を記入すればOKです。

{
  "imports": {
    "~/": "./",
    "aleph/": "https://deno.land/x/aleph@v0.3.0-beta.19/",
    "aleph/type": "https://deno.land/x/aleph@v0.3.0-beta.19/types.d.ts",
    "framework": "https://deno.land/x/aleph@v0.3.0-beta.19/framework/core/mod.ts",
    "framework/react": "https://deno.land/x/aleph@v0.3.0-beta.19/framework/react/mod.ts",
    "react": "https://esm.sh/react@17.0.2",
    "react-dom": "https://esm.sh/react-dom@17.0.2",
    "microcms": "https://esm.sh/v58/microcms-js-sdk@2.0.0"
  },
  "scopes": {}
}

開発環境で実行します。

aleph dev

本番環境にデプロイしてみます。
Verselへのデプロイが一番試しやすく、簡単だと思います。
設定方法は以下をご覧ください
https://alephjs.org/docs/deployment。

以下のような設定をします

Build Command: deno run -A https://deno.land/x/aleph/cli.ts build
Output Directory: dist (you can override it in aleph.config.ts)
Install Command: curl -fsSL https://deno.land/x/install/install.sh | DENO_INSTALL=/usr/local sh

問題なくデプロイできました。alphaからbetaへの移行はスムーズにできそうです。

新機能を試す

以下の記事を参考にさせていただきました。Aleph.js以外にもDenoのフロントエンドについてまとまっていてとても参考になりました。
https://zenn.dev/uki00a/articles/frontend-development-in-deno-2021-autumn#aleph.js-v0.3-betaがリリース

その中から気になった機能を試してみます。

esbuild+swcへの移行

ビルドが tsc から移行されました。
39s (記事数30件)から 33s (記事数35件)へと少し短縮されました。ビルドの要素自体が少ないので誤差ですがビルド時間の短縮が期待できそうです。

Scoped CSS

前回の記事で、CSSのコンパイルがスコープなのかという課題がありましたが、CSS modulesサポートや link タグをコンポーネントごとに読み込むことにより、ScopedなCSSをかけるようになりました。
具体的にはCSS modulesファイルをコンポーネントごとに用意します。

.card {
  margin: 20px;
}
.card:hover {
  opacity: 0.7;
}

.cardLink {
  text-decoration: none;
  color: black;
}

コンポーネントで使用するときはlinkをコンポーネント内で読み込み、$プレフィックスで参照します。

import React from "react";

export const Card: React.VFC<Props> = (
  { url, title },
) => {
  return (
    <article className="$card">
      <link rel="stylesheet" href="./card.module.css" />
      <a
        href={url}
        className="$cardLink"
        target="_blank"
        rel="noopener noreferrer"
      >
        <h3>{title}</h3>
      </a>
    </article>
  );
};

Plugin

その他にも(試せてはいませんが)Next.jsにも実装され話題となったmiddlewareなどの機能も追加されているそうです。
中でも個人的に良いなと思ったのは、Pluginの機能です。
これは設定ファイル aleph.config.ts にPluginを書くことによって、その処理をページ読み込み時に実行する機能になります。
同じような仕組みをVue.jsのフレームワークであるNuxt.jsが実装しています。
ページが読み込まれる前に処理が実行されるので、認証などの必ずページ読み込み以前に走らせたい処理を実行させるのに便利です。
公式では、Google Tag Manegerを読み込む処理などが紹介されています。
https://alephjs.org/docs/api-reference/plugin-api

import type { Plugin } from 'aleph/type'

export default <Plugin> {
  name: 'google-analytics-plugin',
  setup: aleph => {
    const id = Deno.env.get('GTAID')
    if (id && aleph.mode === 'production') {
      aleph.onRender(({ html }) => {
        html.scripts.push(
          {
            src: `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(id)}`,
            async: true
          },
          `
            window.dataLayer = window.dataLayer || [];
            function gtag() {
              dataLayer.push(arguments);
            }
            gtag('js', new Date());
            gtag('config', ${JSON.stringify(id)});
          `
        )
      })
    }
  }
}

Framework API

Aleph内のReactにもAPIが追加されています。
https://alephjs.org/docs/api-reference/framework-api

dynamic import

dynamic importは個別にコンポーネントを取得することでパフォーマンスを向上させることができます。
Fallback を利用することで、コンポーネント読み込み時の処理を追加することができます。
Reactの Suspence のような機能です。

import { useDeno } from "framework/react";
import React from "react";
import { dynamic, Fallback } from 'framework/react';
import "../style/home.css";

import { microcmsClient } from "../lib/microcmsClient.ts";

import type { Post } from "../types/post.ts";

const Card = dynamic(() => import("../components/Card/card.tsx"))

export default function Home() {
  const articles = useDeno<Post>(async () => {
    return await microcmsClient.get({
      endpoint: "articles",
      queries: { limit: 99 },
    });
  });

  return (
    <div className="page">
      <head>
        <title>Ryusou Profile</title>
      </head>
      <section>
        {articles.contents.map((content) => {
          const categorys = content.category.map((category) => category.id);
          const categoryId = categorys[0];
          return (
            <React.Fragment key={content.id}>
              <Fallback to={<p>Loading....</p>}>
                <Card
                  url={content.url}
                  title={content.title}
                  publish_article={content.publish_article}
                  category={categoryId}
                  />
              </Fallback>
            </React.Fragment>
          );
        })}
      </section>
    </div>
  );
}

microCMS

microcms-js-sdkにあった変化についてもご紹介します。
現在バージョンは v2.0.0 です
https://document.microcms.io/tutorial/javascript/javascript-sdk

型定義の見直し

以前までですと、offset totalCount などの型定義を自前で用意する必要がありました。

type Contents = {
  contents: Contents[];
  //以下のようなクエリを自前で用意する必要があった
  totalCount: number;
  limit: number;
  offset: number;
};

これらの型定義はmicrocms-js-sdkに含まれるようになったので、書く必要はありません。

API-KEYの移行

https://blog.microcms.io/renew-x-microcms-api-key/
新APIキーへのリニューアルがされました。
権限などをキーごとに設定できます。
使用方法などはこれまでとは基本的に変わりません。
以下のように設定をします。Denoは以下のようにして .env の値を取得することができます。

import { createClient } from "microcms";

export const microcmsClient = createClient({
  serviceDomain: "your-subDomain",
  apiKey: `${Deno.env.get("X_MICROCMS_API_KEY")}`,
});

useDeno Hookで呼び出します。このHooksはサーバーサイドで実行されるのでAPIキーの漏洩の問題はありません。

  const articles = useDeno<Post>(async () => {
    return await microcmsClient.get({
      endpoint: "articles",
      queries: { limit: 99 },
    });
  }, { revalidate: true });

またAleph.jsではbetaからSSRオプションが使用できるようになったので、そちらでも呼び出せることができます(Next.jsでいうところのgetServerSidePropsなどに近いです)。
https://alephjs.org/docs/basic-features/ssr-and-ssg

POST,PATCHなどのWRITE系のAPIはサーバーサイド側で実行する必要があります。
Next.jsのAPI Routesにあたる機能もAleph.jsには存在するので、APIをそこで定義して使用することになると思います。
https://alephjs.org/docs/basic-features/apis

ここら辺はかなりNext.jsと近い感覚で実装できるのではないかと思っています。

最後に

Next.jsにも URL imports というかなりDenoを意識した機能が先日v12で発表されました。
https://nextjs.org/docs/api-reference/next.config.js/url-imports

そんな中Aleph.jsはどのような発展をしていくのか?
注目しています。

皆さんもぜひ、年末は新しい技術に挑戦してみてはいかがでしょうか?

Discussion