屋号付きで個人事業主をやっているので、せっかくだしドヤ顔ポートフォリオサイトでも作りたい。まあドヤ顔は冗談にしても、デベロッパーたる者、ふらっと牛丼を食べるがごとく技術力のアピールは普段からやっていかなければならない。フラペチーノ屋さんでMacドヤをしても仕事は来ないが[要出典][独自研究?]、ポートフォリオはいつだって頼れるピッチ資料になる。
さりとてポートフォリオサイトというのはいつも、普段やらないWebフロントをやるには丁度いい題材でありつつ、あるはずだった「ポートフォリオの更新」がやってくることなくたいてい一日坊主になる。
開業よりも前に作った 3939.moe(ミクミク・ドット・モエ) は前述のような経緯でデプロイされ、やはり更新がされないまま。手塩にかけた愛ある手書きHTMLも、一度野に放ってしまうと感情が冷めてしまい、次のデプロイはなくなってしまう。
これを乗り越えるべく、新しいポートフォリオの構築は以下のような条件を掲げた。
- 更新が楽
- CMS-likeなレイヤーがどこかにいてほしい
- サーバー管理が不要
- ランニングコストがゼロ、あるいはごく少ない
- Markdownよりはいろいろ表現できてほしい
- でもしょっぱいWYSIWYGエディタはいらない
- 要は静的サイトジェネレーターとリッチなエディタ両方の利点がほしい
黒船 My Notion Blog 襲来
1年ぐらい前に、どこからともなく「Notionってサービスがパないらしい」と伝わってきた。登録してすぐに「WYSIWYGでありながら神がかったUI/UX」に一瞬でやられてしまった。Evern○teやC○nfluenceといったしょっぱいWYSIWYGとは、一線どころか三線ぐらい画すエレガントさ。もしご存知なければぜひ触ってみてほしい。
飛んで今年の1月、「Notionで書いたページをそのままブログとして静的コード生成し配信できるNext.jsのアプリ」と鮮烈に謳われた My Notion Blog がバズった。
Excited to share our long-awaited Next.js + Notion statically-generated blog example with the same tech as https://t.co/HVcLCVUO5w!
— JJ Kasper (@_ijjk) 2020年1月13日
- Edit via Notion
- Blazing fast
- JAMstack based
- Always available
- Fully customizable
- Incremental SSG
- MIT Licensedhttps://t.co/fD2vWxq2Y6
この情報は92thunderパイセン経由でキャッチした。彼のブログもやはりMy Notion Blogをベースとしている。
My Notion Blog は、先に挙げた条件をすべてクリアしている数少ない選択肢として浮上。そのまま採用することにした。
Notionの静的コード生成すごい。銀の弾丸かも。
— 𝕋𝕒𝕜𝕦𝕞𝕚 𝕊𝕦𝕖𝕕𝕒 (@puhitaku) 2020年1月23日
・GitHub Pagesのような静的なサーバーにデプロイできる
・編集が楽
・編集の自由度が高い
・自動でSP対応可能
tl;dr
ポートフォリオサイトはひとまず完成した。
実際に使ってみた感想を短く言うならば、「ZEIT NowやNotionとの結合が済んでて便利なNext.jsのBoilerplateと思ったほうが良い」という感じ。
Notion Blogの画像表示がブッ壊れるのを見て、やはり銀の弾丸などこの世にないのだと思い知らされた
— 𝕋𝕒𝕜𝕦𝕞𝕚 𝕊𝕦𝕖𝕕𝕒 (@puhitaku) 2020年4月18日
- カスタマイズ必須
- JSONにシリアライズされたNotionの記事データから自前でDOMを作っているので、Notionで書いたとおりには表示されない
- 自前DOMを作る部分が結構複雑で読みにくい
- 自前DOMなので結構基本的な部分でうまくいかないことが多い
- 画像のアス比が歪む(!)
- シャドウがずれる
- プレビューに画像を入れるとページがロードできないレベルでぶっこわれる
- カラム分割の対応が無(特に惜しい)
- etc...
- 最終的に自分で空気を読んで直すというのが数時間以上続いた
- 逆に数時間程度頑張ればそれなりに仕上がるBoilerplateと思えば優秀
- 画像などのアセットはS3から配信してるっぽくてどうも遅い
もちろん上記を差し引いても強力な利点は数多くある。
- ZEIT NowとGitHubがポチポチで秒でつながり、すぐにカスタマイズに入れて、すぐにデプロイできる
- フロントとNotionがポチポチで秒でつながり以下略
- そもそも Now は Hobby use なら完全無料というのが寛大すぎる、ZEITすごい
- Next.jsについて本気で調べなくても割と雰囲気でいじれた
- Notion上では "Database" というカラムが決まった表で記事が管理され、これにカラムを足したりしてメタデータをカスタマイズできる
- 追加したメタデータを元にした任意のカスタマイズもすぐできる
- 先人は画像サムネイルを出したりしていて、他にも結構面白い使い方ができそう
備忘
以下、開発備忘録を書き残す。稚拙な変更も多々あって恥ずかしいけどGitHubの該当箇所へのリンクをバンバン張っていく。参考になれば嬉しい。
登録・デプロイ
勘違いにより、最初のとこでちょっとつまずいてしまったのでメモ。上記の記事では手で記事管理テーブルを作成しているが、これは必要なく、自動で生成してくれる。この自動生成は「デプロイされたサイトを開いてヘッダーの "Blog" を押した時」に初めて走るため注意。
Routerの改変
セットアップが終わって適当な記事が出せたところで、次にRouterを改変した。
Next.jsのRouterは、ファイルシステムのディレクトリ構造がそのまま反映される。つまり、 /index.html
を開くと src/pages/index.tsx
が描画され、 /blog
を開くと src/pages/blog/index.tsx
が描画される。
My Notion Blogの素の状態ではHomeとBlogは別の概念になっている。今回はサイトのindexに来た時点で記事一覧を出してほしかったので、ヘッダーの "Blog" を押した時に表示されるView src/pages/blog/index.tsx
にある記事一覧コンポーネントの実装をそのままIndexのView src/pages/index.tsx
に移植した。今思えばコンポーネントの実装をそのまま移植するのではなく、 src/components/articles.tsx
とかに切り出してから import
すればよかった。まあ動くのでヨシ!
結局Contactのコンポーネントもindexに持ってきて、Headerコンポーネントは <head>
だけ残しViewらしいものは消してしまった。
フォント
日本語フォントの指定が一切ないので src/styles/global.css
に変数として --font-ja-gothic
を指定した。サイトの英字グリフはJetBrains Monoで統一したかったので、 --font-mono
の先頭に追記した。そういうわけで以下のような指定にした。
19 --font-mono: 'JetBrains Mono', Menlo, Monaco, Lucida Console, Liberation Mono, 20 DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace; 21 --font-ja-gothic: 'Hiragino Sans W3', 'Hiragino Kaku Gothic ProN', 22 'ヒラギノ角ゴ ProN W3', 'メイリオ', Meiryo, 'MS Pゴシック', 'MS PGothic';
見た目の調整
割とマークアップは質素で、よくよく見ると微妙な点がたくさんある。そこらへんはよしなに調整していく。私のブログのコードを参考にしてもらってもいいけど、前述のコンポーネント雑移植のせいでマークアップのあるべき位置がちぐはぐになっているのはご容赦を。
ところで、 .hoge .fuga
みたいにあるクラスの子孫要素のクラスを指定するセレクタが全然動かなくて最初詰まった。ReactもしくはNext.jsはそういう正解感なの?誰かTwitterでリプってほしい。
SVG系アセットの追加
Facebookや屋号であるYOTSUHACKのロゴがないので追加した。Facebookは公式からEPSが手に入る。
既にあるSVGアセットはTSX化してあるので、それの構造をノリで真似たらOK。styleの指定のようにそのままコピペでは動かないものも数多くあるので、上記を参考にしてもらったり、PyCharmとかJetBrainsのIDEにチェックしてもらいつつ移植するのがおすすめ。
画像表示の修正
画像やembedなどはwrapperとなるdivを周りにつける実装なのだが、Notion上では全く同じように見える画像でも中身がちょっと違っていてwrapperがついたりつかなかったりする。しかもwrapperなしのimgはアスペクト比が狂って最悪になる。これはちょっとまずいので、アスペクト比がメタデータに含まれるアセットは強制的にWrapperを付けることで解決した。
落とし穴: プレビューに画像を入れると死ぬ
記事一覧には「プレビュー」という概念があり、Notionのページの最初の2パラグラフ + Dividerまでがプレビューとして表示される。るんるんでこのDividerの手前に画像を入れたらスクリプトが死んで表示できなくなるので注意。多分記事一覧コンポーネントのコードを修正すれば直せると思う。
まとめ
Web素人の自分でも割とノリで行けたし、Boilerplate生成〜デプロイまでの流れと、記事執筆〜反映が超シームレスにつながっているのが何よりよかった。自作ブログや、ポートフォリオのような程よくCMS的なのが居てほしい用途には結構向いてると思う。というわけで興味があればぜひ。