Aleph.jsでJamstackサイトを作る ~ デプロイまで ~
このスクラップについて
Deno の React フレームワーク,Aleph.js を触ってデプロイまでしてみたので,途中経過や詰まった部分を書きます.
情報は少ないものの,プロジェクト初期化 → Vercel にデプロイまでの記事はぼちぼちあるようなので,そこに載ってなかった内容が書ければいいかなと思います.参考にした記事
デプロイ先
リポジトリ
忘れないように,詳細を書く前に困ったことを全部書き出しておきます.
困ったこと
まだ分からん
- VSCode でのフォーマッタの詳細設定
- モジュールのキャッシュの反映のラグ
- VSCode でのモジュール auto import,拡張子省略
その他
- Vercel では Aleph.js の API Routeに未対応
Vercel のデプロイコマンドでのバージョン指定
Vercel への Aleph.js プロジェクトデプロイに関しては公式でもドキュメントがあるんですが,aleph の最新バージョンである v0.3.0-alpha.33
には対応していません.
そのため,利用しているバージョンに合わせてビルドコマンドも変更する必要があります.
ちなみに公式ではこのコマンドをビルドコマンドに指定しようと書いています.
curl -fsSL https://deno.land/x/install/install.sh | sh -s v1.6.3 && /vercel/.deno/bin/deno run -A https://deno.land/x/aleph@v0.2.28/cli.ts build
https://deno.land/x/aleph@v0.2.28/cli.ts
のバージョン部分を更新して https://deno.land/x/aleph@v0.3.0-alpha.33/cli.ts
にするということは分かったんですが,これでビルドがこけて1時間ほど溶かしました.
抜けていたのはコマンド内の sh -s v1.6.3
部分で,これは Deno のバージョンになるので,現時点で最新の sh -s v1.6.3
に更新して,最終的にコマンドは
curl -fsSL https://deno.land/x/install/install.sh | sh -s v1.1.11.5 && /vercel/.deno/bin/deno run -A https://deno.land/x/aleph@v0.3.0-alpha.33/cli.ts build
になります!これを指定しましょう.
↓ ローカルで aleph --version
をしたときのログ
$ aleph --version
Check https://deno.land/x/aleph@v0.3.0-alpha.33/cli.ts
aleph.js 0.3.0-alpha.33
deno 1.11.5
v8 9.1.269.35
typescript 4.3.2
ちなみに僕はこの方のリポジトリを参考にして,ルートディレクトリにdeploy.shを配置,ビルドコマンドには以下を指定してデプロイしています.
$ sh deploy.sh
useDeno は SSR モードじゃないと使えない
今回,Notion APIとか (未定) を使ってJamstack なサイトを実装してみたいなと思ったので,SSG をはさむ必要がありました.Aleph.js では,Next.js でいう getStaticProps
を行うための API として,useDeno フックが用意されているので,これを使うことになります.
getStaticProps
では Page コンポーネントとは分けて関数を export
し,その返り値が default export
されている Page コンポーネントの props に渡されるような流れでしたが,useDeno はコンポーネント内で呼び出します.コールバック内のコードは Deno ランタイムで実行されているようですね.
具体的にはこういう書き方をします.
export default function Page () {
const blogs = useDeno(async () => await getBlogs());
return (
<>
{blogs.map((blog, index) => (
<Blog key={index} blog={blog} />
))}
</>
);
};
困ったのは,これを普通に aleph dev
や aleph build & start
でビルドする度に以下のエラーになり,useDeno が呼ばれないことでした.
ERROR 'useDeno' hook in SPA mode is illegal: /pages/index.tsx
「SPAモードってなんやねん,指定してへんぞ」としばらく詰まっていたんですが,SSG を行なっている他の方のリポジトリを見たところ,aleph.config.js の設定によるもののようでした.
export default {
"ssr": true,
};
ここの ssr の値が false になっていると SPA mode
という扱いになるようで,true にすると無事 useDeno が動きました.サーバーサイドで動くコールバックを渡すのに hooks ってなんか変な感じがしますが,そうでもないんですかね.
また,SSG 時には何かしら API を叩いてコンテンツを取得するかと思いますが,今回は Node のランタイム API である process
は使えないので,Deno の Deno.env
を利用します.
具体的にはこんな感じになるかと思います.
const blogs = useDeno(async () => {
const token = Deno.env.get('NOTION_API_TOKEN');
return await getBlogs({ token });
};
import_map.json の挙動
Deno は Node.js の開発者 Ryan Dahl 氏が Node.js の反省を元に開発した JS, TS ランタイムです.Node.js にあった package.json
や node_modules
の存在は彼にとっては反省点のようで,Deno ではこれらが廃止され,全てのモジュールは URL から直接 import されるようになっています.(正直まだ初心者なのでその辺の反省点はそこまでピンときませんが!)
import { useDeno } from 'https://deno.land/x/aleph@v0.3.0-alpha.33/framework/react/mod.ts';
そこで,全てのファイルにいちいち以下のような import 文を書いていたら大変だということで,import_map.json
で URL と alias を対応づけて,import 文では alias の方を利用できるようになっています.
{
"imports": {
"framework/react": "https://deno.land/x/aleph@v0.3.0-alpha.33/framework/react/mod.ts"
}
}
import { useDeno } from 'framework/react';
(ちなみに Deno はビルトインで ES モジュール をサポートしていて,逆にrequire
などは利用できません)
ここで途中まで分からずかなり困っていた仕様が,
- alias は上の
~/mod.ts
のようなファイルだけでなく,framework/react/
のようにディレクトリに対しても貼れる. -
import_map.json
に書かれていても,マシン上にキャッシュされていないモジュールはエディタ上であらゆるサジェストが効かない.
という2点です.
書くの疲れてきました.
2については当たり前なんですが,Node.js に慣れていた身からするとあれ?となりしばらく詰まります (僕だけかもしれません).
Deno では,URL からモジュールを初めて import するときに,マシン上にモジュールをキャッシュします.Node.js でいうと node_modules にパッケージがダウンロードされている状態です.これがないと,import 文を書いたときに,import_map.json に書いているにも関わらず赤波線が出て,モジュールを格納した変数をホバーしても何も表示されず,あれ,URL 間違ったかなとなります.
VSCode では URL ホバー時のポップアップからこの初回キャッシュを走らせることができますが,以下のように CLI で行えるので,これをしましょう.
$ deno install <module_url>
それだけでした.
というか,node_modulesを廃したのは分かったんですが,import したモジュールをキャッシュしてるのはこれとはまた別なんですかね?
Link コンポーネントないじゃん
普通に見つかりませんでした.どこ?
というのも,公式ドキュメントでは Link を https://deno.land/x/aleph/mod.ts
から import しているんですが,これは v0.2.28 時点での情報で,現在の v0.3.0-alpha.33 では aleph/mod.ts
は存在していません.
ドキュメントやコード内を探したんですが見つけられなかったので,onClick
で router.push(href)
する,Link らしきコンポーネントを作って対応しました…
react-router
や next/link
の Link
の内部実装はおろか生成しているDOMの詳細も知らないので分からないんですが,確か a
タグで囲みつつ,クリック時には web サーバーにリクエストを送るのを止めるみたいなコンポーネントだった気がするので,また調べます.
ちなみに useRouter フックは https://deno.land/x/aleph@v0.3.0-alpha.33/framework/react/mod.ts
で export されています.不安定だと難しいですね.
VSCode でのフォーマッタの詳細設定
これが分かりません.
Deno では リンタやフォーマッタは組み込まれていて,deno lint
や deno fmt
で実行できます.めちゃくちゃ速いです.
が,VSCode 上で save 時に走っているのは多分これじゃないですよね…
設定はこうなってます
{
< 省略 >
"deno.lint": true,
"editor.defaultFormatter": "denoland.vscode-deno",
"editor.formatOnSave": true
}
"deno.enabel": true
になっている workspace 内で .ts, .tsx, .js, .jsx ファイルが save されたら 拡張機能であるdenoland.vscode-deno
というフォーマッタが走るということかと思うんですが,この denoland.vscode-deno
拡張機能でフォーマットの詳細設定をするインターフェイスが見つからず,初期設定のままフォーマットされている状態です.