🦕

Denoのフロントエンド開発の動向【2021年秋】

2021/11/04に公開

半年ほど前にDenoのフロントエンド開発についてまとめた以下のような記事を書きました。

https://zenn.dev/uki00a/articles/frontend-development-in-deno-2021-spring

ここ半年程でまた色々と変化があったため、改めてまとめてみます。

要約

npmパッケージとの相互運用性について

Node.js互換モード

Deno v1.5でNode.js互換モードが実装されました。

現時点でもexpresskoaなどのパッケージがある程度動作するようです。

https://zenn.dev/uki00a/articles/node-compat-mode-introduced-in-deno-v1-15

現在、このNode.js互換モードを使用して、ViteやNext.jsなどを動かすための対応が試みられています。

https://github.com/denoland/deno/issues/12577

また、DenoコアチームのメンバであるBartek Iwańczuk氏によるとeslintがまもなく動かせそうとのことです。

https://twitter.com/biwanczuk/status/1454776772751470594

esm.shのアップデート

esm.shはnpmパッケージを配信することを目的としたCDNです。

https://github.com/alephjs/esm.sh

このesm.shでパッケージのエイリアス機能がサポートされました。

https://esm.sh/swr@1.0.1?alias=react:preact/compat

これにより、preact/compatなどの使い勝手が良くなっています


Aleph.js v0.3 betaがリリース

Aleph.jsはNext.jsに影響を受けたReactベースのフレームワークです。

https://github.com/alephjs/aleph.js

このAleph.jsのv0.3 betaがリリースされました。

大きな変更点としては下記の通りです。

ビルド基盤がesbuild+swcへ移行

元々、Aleph.jsではビルド基盤としてtsc(正確に言うとtypescriptパッケージ)を使用していました。

v0.3 betaでは、ビルド基盤がesbuildとswcへ移行されました。

これによりビルドの高速化などが期待されます。

新しいプラグインシステム

プラグインシステムによって、Aleph.jsのランタイムを拡張し、コードの変換プロセスに介入したりカスタムファイルタイプのサポートなどを追加できます。

公式では下記の3種類のプラグインが提供されています:

また、Aleph.jsの作者であるije氏によりWindi CSSプラグインが提供されています。

https://github.com/ije/aleph-plugin-windicss

// aleph.config.ts
import windicss from 'https://deno.land/x/aleph_plugin_windicss@v0.0.2/plugin.ts'
import type { Config } from 'aleph/types'

export default {
  plugins: [windicss]
} as Config

これでTailwind CSS互換のクラスが利用できるようになります。


<link>タグベースのスコープドCSSのサポート

どういうことかと言うと、次のように<link>*.module.cssファイルを読み込むことで、スコープの限定されたCSSスタイルが生成されます。

このスタイルは$プレフィックスを付与することで参照できます。

import React from 'react'

export default function App() {
  return (
    <>
      <link rel="stylesheet" href="../style/app.module.css" />
      <h1 className="$title">Hello world!</h1>
    </>
  )
}

Pageコンポーネントでのssrオプションのサポート

Pageコンポーネントでssrオプションがサポートされました。

これはNext.jsにおけるgetStaticProps/getStaticPaths相当の機能です。

import React from 'react'
import type { SSROptions } from 'aleph/types'

export const ssr: SSROptions = {
  props: async router => ({ date: Date.now() }),
  paths: async () => [],
}

export default function Page(props) {
  return (
    <p>{props.date}</p>
  )
}

Oakとの統合

OakはDenoのWebアプリケーションフレームワークです。

Node.jsのKoaに影響を受けています。

このv0.3 betaリリースでは、aleph/server/mod.tsoakify()という関数が追加されており、これによりAlephオブジェクトをOakミドルウェア化することができます。


APIミドルウェアのサポート

api/_middlewares.tsまたはaleph.config.tsでミドルウェアを定義できるようになりました。

ロギングやレスポンスヘッダの設定など、様々なことができそうです。


Fresh

https://github.com/lucacasonato/fresh

DenoコアチームのメンバであるLuca Casonato氏が開発しているPreactベースのWebフレームワークです。

基本的には、Deno Deployで動かすことを想定されているようです。(一応、Deno CLIでも動きます)

設定や事前ビルドなどをせずに利用ができ、ビルドやレンダリングはサーバ上で必要に応じて実施されます。(FreshのREADME.mdではJITレンダリングと呼ばれています)

また、<Suspense>などの機能もサポートされています。

/** @jsx h */
import { h, Suspense, useData } from "../deps.ts";

export default function Home() {
  return (
    <Suspense
      fallback={(
        <div>
          Loading...
        </div>
      )}
    >
      <SuspendedComponent />
    </Suspense>
  );
}

function SuspendedComponent() {
  const message = useData("/api/message", fetchMessage);
  return <div>{message}</div>;
}

async function fetchMessage(key: string): Promise<string> {
  const res = await fetch(key);
  return await res.text();
}

ちなみに、deno lintの公式ページであるlint.deno.landはこのFreshとtwindで作成されています。[1]

今後についてですが、GitHub issueにて下記の機能などが提案されています。

個人的にはページのキャッシュなどがサポートされれば、かなり使い勝手がよくなるのではないかと想像しています。

Ultra

https://github.com/exhibitionist-digital/ultra

UltraというReactベースのフレームワークが公開されました。

特徴

  • ReactDOM.renderToReadableStreamベースのSSR
  • Viteなどと同様のオンデマンドでのコード変換
  • esbuild+swcベースのビルドシステム
  • SWR向けのキャッシュプロパイダを提供
  • Import mapsベースの依存管理

スキャフォールディングなどはまだ提供されていないので、利用する際は公式のボイラープレートなどを参考にするとよいと思います。

まだ公開されたばかりのフレームワークなので、本格的に使用できるようになるのはまだ先になるのではないかと思います。

packup

https://github.com/kt3k/packup

packupはParcelに影響を受けたesbuildベースのビルドツールです。

作者はDenoコアチームのメンバであるkt3kさんです。

Parcelと同様に設定が不要で、packupコマンドの引数としてHTMLファイルを指定するだけで使用することができます。

また、基本的なSassサポートなども提供されています。

Snel

https://github.com/crewdevio/Snel

SnelはSvelteアプリケーションのビルドツール/フレームワークです。

内部的にはBundlerdeno-rollup(フォーク版)などをベースに実装されています。

依存関係の管理やタスクランナとしてTrex を採用しており、Import Mapsを使用して依存モジュールを管理することができます。

また、実験的ですがSSGなどもサポートされています。 (SSRは将来的にサポートされる予定のようです)

vnoのアップデート

https://github.com/open-source-labs/vno

vnoはDenoでVue.jsアプリを開発するためのビルドツールです。

直近半年程で実施された大きな変更点としては以下の通りです:

  • SSR及びdevサーバでのライブリロードがサポート (v1.3.0)
  • SSGがサポート (vno ssg buildコマンド) (v1.4.1)
    • ただし、ドキュメントにはまだ記述されていないので注意

CSS関連の動向

今のところ、Denoの公式ドキュメントなどではtwindが使用/紹介される傾向にあるような印象を受けています。

例)

また、twdというDenoでTailwind CSSライクなスタイルを記述するためのツールでも、内部ではこのtwindが使用されています。

またAleph.jsではCSS ModulesWindi CSSのサポートなどが提供されています。

Velocirapor v1がリリース

VelociraptorはDenoのタスクランナーです。

https://github.com/jurassiscripts/velociraptor

このVelociraporのv1リリースされました。

このリリースではGitフックのサポートが追加されています。

scripts.yml
scripts:
  format:
    cmd: deno fmt
    gitHook: pre-commit

設定ファイルでこのように記述しておくと、vrコマンドを実行した際にGitフックが自動生成されます。


おわりに

半年前と比較すると、ある程度選択肢なども増えてきたと感じています。

とはいえ、本格的なフロントエンド開発をするには、Aleph.js / Fresh / packupあたりがメジャーリリースされるまではまだ少し厳しいのではないかとも感じてます。

ただし、Node.js互換モードによってViteが動くようになれば、正直それを使えばよさそうと個人的には思ったりもしてます。(本番リリース時はプロダクションビルドするはずなので、開発時にNode.js互換モードを使うことによるオーバーヘッドもそこまで問題にはならないはず)

もし興味のあるものなどがありましたら、ぜひ使ってみてください!

脚注
  1. 元々、lint.deno.landはDext.tsとTailwind CSSで書かれていましたが、最近リライトされました ↩︎

Discussion