Tech

Svelte/Sapperでブログを作り直した

Svelte/Sapper構成でブログを作りなおしてみたので遭遇した問題や何を使ったかの記録。

(追記)
将来的にSapperはSvelteKitが代替となり、1.0にはならないようなことが発表されていますので最新状況を確認してみてください。

モチベーション

  • 前のデザインに飽きてきていた
  • Svelte/Sapperを触ってみたかった
  • SSRでホスティングしてみたかった
  • IEが切れるよ、となったときに自分のHTML/CSS知識が化石となっている気がしたのでそこに注意しつつ何かを作ってみたかった
  • タグリストや関連記事、最新記事などある程度ブログ構成にしつつあとでカテゴリ分けなどができるように作りたかった

Markdown

最初はMDsveXを使ってMDXでやることを検討していましたが、出始めかつ開発中(今は更新止まっていそう)という背景もあり、Markdown内のjavascriptコードが実行されてしまったり、上手くパースされなかったりで既存の記事が結構動かなくなってしまい、そもそもMDX化作業も後でいいかなと思い、最終的にremarkで自力でやりました。

(追記: 後にかなりアクティブになっていることを確認しました)

Remarkはぱっと使おうとするとよくわからずいつもはまる…ので以前のブログのGridsomeのブログのプラグインを参考に変換処理を書きました。Remark公式に書いてあるプラグインで絶対使う系以外は全然動かなかったけど環境のせい…?

なんにせよ理解しつつ色々カスタマイズしたかったり作りたい機能があるのでどこかで時間を取りたい所。

CSS(Tailwind CSS)

CSSは基本的にはTailwind CSSですがやはりPostcssがあまり好きではないことや命名が暗記ゲームだったりして便利なもののちょっと個人的にはフラストレーションが溜まったりします。
遥か昔にEmmetの命名に沿った似たようなSassライブラリ作ろうとしたことがあるけどEmmetにのっかるのは変なアイデアなのだろうか…。

と思うところはあるものの一から自分で書くのかというとなんか違うなという気持ちにもなってしまい、結局Tailwind CSSを使いました。
Sapperに対してセットアップするのは一番に見つかるであろう資料に沿って実装するとコンポーネント内で @apply などができなかったりするのでこのあたりも自力解決が必要でした。メモするのを忘れましたが最終的に参考にしたのはこちらの記事のような気がします。

(追記: 後にこのサイトではないですが、個人的には@apply等を使わずにTailwind CSS + scoped cssが気に入っています)

Prettier/lint-staged

PrettierもSvelte用のPluginをいれたりしました。
また、Sapperも [] をファイル名で使用するのでlint-staged + prettierでエラーが発生するようで、これはNext.jsの設定を参考に持ってきました。

Sitemap

これもプラグインで基本的に完成、とはならないのでこの記事をベースにカスタマイズして作成しました。

問い合わせ

Mailjet / SendGrid / MailGun / Amazon SES あたりを検討して結局SESが価格的によかったのですが、
使用前に申請が必要なことと、特にそんなに問い合わせが来るわけでもないので申請はしてみたものの承認をまっている間にMailjetで実装して終わってしまいました…。

一つ調べていて気になったのは SendGridは日本語版?があり料金体型も本家と全然違いました。興味深い。

OG Image

今回のサイトは所謂NoImageではなく、画像がない場合テンプレートに沿って独自の画像が作成される、ということをやりたかったので、はじめは手抜きですがライブラリを探してみたものの、こちらも改行の判定がうまくいかなかったりと意外と良いのがありませんでした。

最終的には自分でHTMLを作ってそれをPuppeteerでスクショを撮って生成するコードを書きました。荒めですが意外と3-4時間?かそれ以下でできました。

ホスティング

ホスティングはなんか色々と迷走しまくっていたのですが、サーバーを管理せず関数を実行できる環境でSSRをホストする、という部分とブログはMarkdownのまま管理していきたい、という指針で検討しました。

最初はスタートとしてFirebaseのCloud FunctionsでSSR動かせるよ、というNuxt.js系の情報がスタートだったのでそれを目指しFirebaseで動かしてみました。
そもそも動かすのに苦労したのでもしFirebase使う方はfunctionsディレクトリに全部乗せる方式(たしかこれ)がおすすめです。ルートにSapper、Functionsにbuildされたファイルをどうこうはめちゃくちゃ管理がめんどくさいです。

とはいえ結局Firebaseでは動かせたものの初期起動が遅いなとかファイルの読み書きが絡む処理が結構あるのですがそこは壊滅的に遅く、別のものを検討しました。

そもそもローカル以外だとこんなもんなのかな?という疑問とともに試しにdokkuVultrのサーバーに入れてホスティングしてみるとレスポンス速度などかなり早くなりました。

ただ基本的に普段サーバーを管理してたりもしないため、これによってお金も発生するし面倒だなと思い、Vercel(Now)に移植してみた所、ファイルI/O周りのスピードはFirebaseより大分早くVPSより大分遅い、という感じでした。ただVercelにはFunctionsに対してキャッシュを有効にできる仕組みがあり、一回目は若干遅いものの2回目以降は何も問題が無かったです。(というかそもそもVercel(Now)もFunctions系の仕組みあったんですね、知らなかった…。)

ということで単純な性能的には VPS > Vercel(Now) > Firebase でしたが、VPSはキャッシュ設定とかもしないといけないので最終的に動作、コスト、設定、管理などのバランスを見てVercel(Now)で動かしていくことにしました。

PullRequestのプレビュー生成もNetlifyと同様ですが、開発中にとても便利ですね。一人開発とはいえ、何故かプレビュー環境で簡単にバグに気付くことが多いです。

Vercel(Now) * Sapper は これが便利です。

Svelte/Sapperの感想

はじめる

公式チュートリアルがかなり丁寧に作られていると思うので一旦はチュートリアル一周してSapperのドキュメントを読んで、でスタート自体はできるかと思います。なにか作られたものがみたい、という場合はRealworldをコアーチームが作っていると思われるのでこれを参照すると良いと思います。ぐぐってもそこそこ情報は出ます。

面白い所

特にあまり機能を使い倒すサイトではないので表面的にしか全然使えてないのですが面白い機能は context="module" を使った コンポーネント間の共有とかアニメーションヘルパーのようなものがSvelteについている所ですかね。このサイトのアニメーションは大体これで書いてみています。(ホバー系意外)

他にはAPIを作りたい時に get などの関数をexportとすることでAPIがさくっと作れちゃうのが新しい体験でした(恐らくNext.js系も似たようなことができるのかなとは思いますが未経験)。
https://sapper.svelte.dev/docs#Server_routeshttps://sapper.svelte.dev/docs#Server_routes

調べ物をしているとRich Harris氏(Svelte作者)が書いているProposal的なissue() がよく出てきてなんでこういう設計で進んでいるのかとかを知る機会が結構ありました。

困った所

ちょっとこまったのはA状態の時にB classを付ける、みたいなところで class:iwant={boolean} という構文になるのですが、これは一度に複数のクラスをハンドリングできず複数のclassを変更したい場合は複数このコードを書く必要があります。 (class:iwanta={boolean1}, class:iwantb={boolean1} )

あとはページトランジションが同じコンポーネント内でIDだけが変わる(記事ページから記事ページなど)場合に同じコンポーネントと判断されてしまいハッキーなことをしないとできなくてこれははまりました。
SvelteではコンポーネントのIDとしてのkeyはEachブロック内に書くため、コンポーネントに対してなんらかの値を渡して通知する、というような事が難しいです。
{#each list as item (item.key)}

個人的には困ってはいないですが公式のTypeScript対応はまだありません。調べていた範囲だとコンポーネント外のファイルなどは普通に使えるようにできるようではありましたが使っていないのでよくわかりません。個人的に型定義が間違ってるのか自分が間違ってるのかよくわからなくて時間を取られるということが多く発生していて言語的には好きなもののどうしても採用したいという感覚値がないです…。このあたりはJSの上にのっかったTS、みたいな世界がなんか疲弊するんですよねという最近の愚痴です。

本当に最近ですがSvelteのLanguage Serverのリポが作られて対応自体はずっと具体的な動きはなかったもののこのissueをきっかけに動き始めています。

(追記: VSCodeを主体としたTypescriptサポートはおそらく今はリリース済です)

環境

React/Vueなどを比べるとやはり情報も少なく(とはいえまったくないという感じではない)、プラグイン周りも多くはないため、ライブラリ組み合わせてさっさとローンチ、みたいな事を考えていると痛い目に合うかもなという所感です。
また、Sapperに対してNext.js/Nuxt.js系から同じ感覚値で来るとたまにSvelteでは実装されていなかったり対応されていない機能などもあるのでそのあたりも注意ですね。

ただこのあたりは逆に設計観点が結構違ったりするので差異が強く出ている部分は面白い所でもあります。(ふわっとしている)

追加したい機能

  • i18n
    • 日英対応したい
    • ブログは日本語しかないのに英語対応しておこう、みたいな意味不明状態(正解は英語記事を書くことだ!)
  • RSS
  • Tech / Diary / Game でカテゴリ分けする、技術だけにこだわらない構成にする
    • ゲームはかなりやるくせしておすすめを聞かれてもぱっとでないので勝手にまとめたい
    • ポエム的なところも書いていきたい
  • Remarkのカスタマイズ
    • oembed系を対応できるようにしたりしたい。
    • 概ね色々とやりたくてプラグインをさしてみたものの大体うまくいかなかったのでRemarkプラグインを自作したい

まとめ

  • やりたいと思っていた機能がそもそも前のブログよりも多くて途中放り投げそうになりつつも、なんとか捨てるとこは捨ててリリースできたのでよかった
    • このあたりは個人開発メソッド的な所でずっとnoindex状態でインターネット上には公開していてアップデートしていた
  • 安定してさくっと作りたい or Typescript絶対使いたい、だとReact/Vue系のほうが良さそう
  • Vercel(Now)とても良い
  • ブログサイトで機能がたいしてないため、最終的に仕事で使っていくのか、までは判断がいたらない or 頭がまとまっていない
  • Svelte自体は割と好きかな印象で終わっています。
  • この記事にほとんどコードがでてこないので説明できるところはこの記事から抽出して別記事を書きたい
  • だれつつ2-3ヶ月開発したおかげでやっとブログが書けた!!!コスパが良い(迷走)

おまけ

こういうときぐらいしかまとめないのでなつかしむ

v1 - Vue.js/Nuxt.js

v1.png

v3 - Vue.js/Gridsome (v2はGatsbyで作ってたけど公開前にGridsomeが出て乗り換え)

v3.png

v4 - Svelte/Sapper

v4.png

share