- 個人ウェブサイトを単一バイナリとして作れば、1人で全体構造を理解し、自分で保守できるため、従来のSSG・ホスティングの組み合わせに伴う依存関係の負担を減らせる
- HugoとGitHub Pagesのような組み合わせは、サービスの継続性、プロジェクトの維持、プラグインエコシステム、デプロイ方式、Goなど、さまざまな外部条件を前提にしている
- 手作業でのHTML編集は単純で安定しているが、共通機能を繰り返し扱うのが難しく、作業フローが疲れるものになるため、もっと楽しく調整できる方法が必要だった
- Goベースの動的サイトは、IP表示やRSSフィード更新のように静的サイトでは面倒な作業をサーバー側コードで処理し、ブラウザではないツールにも完成したHTMLを返す
- 個人ウェブサイトは小さく始め、標準ライブラリと単純なツールで育てるほうが長続きする。大きなフレームワークから始めると、個人の時間内で追い続けるのが難しい
既存のウェブサイトツールが合わなかった理由
- Ghost、Hugo、Jekyll、sr.htとtarball、手作業でのHTML編集までさまざまな方法を試したが、個人的な基準に合わず、興味も湧かなかった
- 最も重要な基準は、1人が最初から最後まで理解し、簡単に保守できるシステムであることだった
- 読みやすいコード
- 速いフィードバックループ
- 楽しさと気の利いた工夫
- 壊れたときに自分で掘り下げられる構造
- Hugoのような静的サイトジェネレーター(SSG)は、テンプレートとMarkdownを入力としてHTMLを生成し、通常はホスティングプラットフォームと一緒に使われる
- HugoとGitHub Pagesの組み合わせには、いくつもの保守条件が付いてくる
- GitHub Pagesサービスが動き続ける必要がある
- GitHub Pagesというプロダクトが維持され続ける必要がある
- Hugoプロジェクトとコミュニティドキュメントが維持される必要がある
- プラグインエコシステムに依存する可能性がある
- Hugoバイナリが時間が経ってもHTMLをほぼ同じ方法で生成する必要がある
- GitHub Pagesのデプロイ機構が動き続ける必要がある
- Goが必要になる
- 特定のHugoバージョンを固定して使う方法もあるが、実際にはバグのためにアップグレードが必要になることがある
手作業でHTMLを編集する利点と限界
- 自分で管理するマシンにウェブサイトをホストし、VimでHTMLを手で編集する方法も選んだ
- j3s.shの最初のバージョンはこの方法で作られ、現在のレイアウト案の多くもここから生まれた
- 手でHTMLを書くと、つらい手作業のように感じられ、極端なミニマリズムにつながる
- スタイルをHTML内に直接入れる
- サイト全体の共通機能を最小限にする
- スタイリングをできるだけ避ける
- この方法は単純で安定しており、保守しやすかった
- 書いたHTMLは修正なしで再利用できた
- 外部依存関係がなかった
- サイトが長く維持されるという確信を与えてくれた
- ただし、共通機能のテンプレート化をより効率的に扱いたく、既存フレームワークなしで楽しく調整できる方法が必要だった
Goの単一バイナリウェブサイト
- ウェブサイト全体を1つの言語で書けば、成果物を単一バイナリに収めてデプロイできる
- Goは個人での保守と単純なデプロイによく合う選択肢だった
- 1人で保守しやすい
- 依存関係を少なくする方向を重視している
- 言語が比較的単純
- 後方互換性の保証がある
- 静的コンパイルされたバイナリを簡単に作れる
- ほとんどの場合10秒未満でコンパイルできる
- 標準ライブラリがよく整備されている
- 結果としてj3s.shは、ウェブサイトを配信する1つのバイナリになった
動的ウェブサイトがもたらす単純さ
- 場合によっては、静的生成ウェブサイトよりも動的生成ウェブサイトのほうが単純になり得る
- コンテンツ生成のための回避策を考えなくてよい
- 必要な内容をその場で生成できる
- 訪問者のIPアドレスを出力する機能は、Goの
http.HandlerFuncで簡単に実装できる
X-Forwarded-Forヘッダーを読む
/ipパスにハンドラーを接続する
- 必要な場所で同じ関数を呼び出せる
- 静的サイトで同じ機能を実装するにはJavaScriptのような外部依存関係が必要になることがあり、JavaScriptがない場合も考慮しなければならない
- サーバーがすでにIPアドレスを含むHTMLを返せば、クライアントがJavaScriptを理解できなくても正しいレスポンスを受け取れる
- ホームページのRSSフィードは、ウェブサイトの起動時に生成される
- 友人たちの最新記事を新たに取得できる
- 自作のRSSフィードfetcherは、長期間保守なしで動作すると考えている
- 内部動作を正確に理解している
デプロイと始め方
- デプロイは短いシェルスクリプトで処理される
- Gitリポジトリを取得する
- ローカルブランチが遅れていれば
git merge origin/mainを実行する
go buildでビルドする
- バイナリを
/usr/local/bin/j3s.shへ移動する
service j3s.sh restartでサービスを再起動する
- このスクリプトはcronjobで毎分実行され、リポジトリが更新されるとサイトを再ビルドする
- ローカルでテストしてアップロードすると、1分以内に公開サイトへ反映される
- シェルを少し知っていれば10秒以内に理解できるほど単純
- 個人ウェブサイトは、現在のウェブでは独特の雰囲気を与え、運営者が大切にしていることを深く反映できる
- 静的サイトが合う人はそのまま使えばよいが、似た価値観を持つ人には動的ウェブサイトを試すのが合うかもしれない
- 小さく始められる
- 面白いアイデアを反復的に追加できる
- 自分のサイトなのでハードコードしてもよい
- Rust、Perl、Pythonなど好きな言語で作れる
- 始めるときは小さくするべきだ
- まず
index.htmlを作り、選んだ言語でそれを配信することに集中する
- RSSやMarkdownは、後で必要になったときに追加する
- 可能なら標準ライブラリのように、最も単純で保守しやすいツールを使う
- RubyではRailsではなくSinatra、PythonではFlaskではなくGinのような、より小さな選択肢を検討できる
- ライブラリ0個で自分で実装できるかも、まず試してみるとよい
- 大きなフレームワークや、breaking changeが続くプロジェクトから始めると、個人の時間内で追い続けるのが難しく、すぐに疲れてしまう可能性がある
- ウェブにはもっと多くの奇妙さ、興奮、個性が必要であり、動的ウェブサイトを作ってみることが推奨される
1件のコメント
Hacker Newsの意見
モバイルではウェブサイトの幅が正しく計算されておらず、文章を読むには左右にスクロールしなければならない。
その直前に「私は非常に高く、独特な基準を持っている」という文を読んでいたので、正直ちょっと笑ってしまった :)
preでレンダリングして、巨大な1段落のように見えているだけ ¯_(ツ)_/¯変な書式はよく見てきたが、そもそも書式がないのは初めて。
それでも第一印象は良くない。
理解できない。
本人が誇りを持つのはいいが、私は単に読まないことにした。
「シンプルに保つ」とはそもそも何なのか、「理解できる」とは何なのかが核心だ。
こういう文章は、興味深い議論を飛ばして、自分のアプローチがシンプルで、目標がシンプルさなのだと仮定してしまう。
抽象化、たとえばライブラリやフレームワーク、サービスやAPIを選べるとき、使うほうがシンプルなのか、使わないほうがシンプルなのか?
使わずに自分で作れば、システム全体がどう動くのかをよりよく知ることになるので、ある意味ではよりシンプルだ。
しかし複雑さは依然として発生し、場合によっては抽象化レイヤーも自分で作らなければならない。
逆に使えば複雑さを隠すので、正常系ではシステムはよりシンプルだと見なせるが、その複雑さは依然として存在し、隠されているため理解できない。
どちらの方式も特定の観点からは明らかにシンプルに見えるが、その明白さを越えて初めてトレードオフが見えてくる。
普通は材料と道具を買い、既にあるオーブンで焼くことになる。
だがゼロからアップルパイを作るには、まず宇宙を作らなければならず、おそらくアップルパイをサポートする最もシンプルな宇宙を作ることになる。
スタック全体はよりシンプルかもしれないが、最後の段階である実際のパイ作りはより複雑になり、味も最高ではないかもしれない。
その代わり、第一原理から完全に理解したパイが手に入る。
Rich Hickeyのこの講演が気に入るかもしれない: https://paulrcook.com/blog/simple-made-easy
何かをより簡単に作ったりデプロイしたりするために機能を追加することはできるが、その追加によって全体はより複雑になり、理解したり問題を追跡したりするのは難しくなる。
作者は最後に、各自が自分のやり方でやればいいとはっきり言っている。
そのうえ、自分にとって理解しにくかったり負担だったりするシステムを使うことに満足していないとも述べている。
最初の段落以降も読んでみるといいと思う。
とても素晴らしい!
「皆さんもこうすべきです!」にはまったく同意しないけれど :)
保守性は私の重要な価値観の1つなので、あなたのように自転車の整備も自分でやっている。
ただ私にとっては、これがそこまで最優先ではないので、こういう選択は筋が通らない。
FrameworkノートPCは、私たちの違いをよく示している点だ。
あなたはDIYの方向で常に9点を叩き出しているが、私はいつでもLinuxとNeovimを急いで動かせる10年前のThinkPadの予備機を持っており、それすら壊れたら今後も100ドル未満のThinkPadはたくさんあるだろうと信じることでレジリエンスを確保している。
いつか必要になれば、HaskellのコンビネータでMarkdownからHTMLへの遅く、非公式で、バグだらけのパーサを書ける程度のコンピュータサイエンスと数学の知識は持ち歩いているが、そんな日がすぐ来るとは思えない。
可能ならあなたを採用したい。
逆方向に傾く多くの人々に対する完璧なカウンターウェイトになるだろう。
この記事を本当に楽しく読んだ。
作者は自分に正直で、読者に対して真摯だ。
言い訳せずに自分自身として存在し、自分の価値観に合い、楽しみを与えてくれる方法で目標を達成しようとしている。
その価値観があなたと合わなくても構わないし、むしろ美しいことだ。
これで、あなたが探索できる道についての手がかりを得たことになる。
文章は親切で謙虚で誠実であり、作者と文章が世界を少しだけ良い場所にしていると思う。
謙虚だというのも同じだ。
全体としては自画自賛に近く、ところどころ /r/confidentlyincorrect のような断片も見える。
読者は副次的な対象にすぎないので、読者体験がどれほどスパルタ式であっても核心ではなく、作者の体験こそが核心だ。
モバイルプラットフォームから来た人たちの多くが、あまりにも早く読むのを諦めたようだ。
ざっと眺めたところ、この人はほぼ間違いなく私たちを釣っているように思う。
ウェブサイトは文字どおり「plain HTML」を使っていると言っているが、実際にはplain textだ。
ここには書式用のHTMLがまったくない。
見出しも、段落も、リストもなく、aタグすらない。
少し入っているHTMLとCSSは、むしろサイトのレンダリングを悪くしている。
筆者はトロールだ。
「私は非常に高くて変わった基準を持っている」としつつ、「このスクリプトは cronjob として毎分実行され、git リポジトリが更新されていればサイトを再ビルドする」とのこと
1年に数個しかコミットしないであろうリポジトリを年525,600回取得している計算になる
「変わった」という言葉がなぜ入っているのかは分かった
git fetchは実質的に文字列比較1回に近いので [0]、言うほどコストの大きい処理ではないと思う[0] https://stackoverflow.com/a/44476803
聞かれる前に教えてあげるべき
私の git リポジトリはすべて、ウェブサイトをホスティングしている同じサーバー上にある
git はリモート fetch ではなくローカル fetchをしているので、実質的に即座に終わる
仮にリモート fetch だったとしても問題なかっただろう
年525,600回の HTTP リクエストは、NetworkManager のハートビートより無駄が少ない
Arch ではデフォルトで30秒ごとにハートビートリクエストが1回ある
ちなみに CPU 8個の標準的な nginx サーバーは、秒間50万件以上の HTTP リクエストを処理できる
OPへ:
ここにはかなり批判的な書き込みが多く見える
丁寧に言うと……気にしないでいい
批判が正しいこともあるだろうが、業界は集団的な「すべき」と「そうあるべき」に従いながら、急速に大規模な愚かさへ向かっている
その多くは現時点では都市伝説レベルの妥当性しかない
最近「エンジニアリング」と呼ばれているものは、その上に私たちが未来を積極的に作っていなければ、笑って済ませられるものだ
私の父は航空宇宙エンジニアだったが、現代のソフトウェア開発でエンジニアリングと呼ばれているものを見たら、墓の中で寝返りを打つと思う
コメント欄だから誰にでも発言の自由はあるが、個人的には業界で25年経ってようやく、あのうるさい声を無視し、まれに可能な機会には自分が筋が通っていると感じることをするようになった
個人サイトならなおさらではないか?
Apple の広告にあった「クレイジーな人たちへ」という古いフレーズも、今では真実から遠く聞こえる
インターネットがこうなり、かつてスタートアップだったところが今や地形上最大級の企業モンスターになったのだから、驚くことでもない
Theodore Roosevelt の「競技場の中の人」の引用が、最近は本当にその通りだ
続けてくれ、OP、続けてくれ……
私のウェブサイトは完璧に最適化されたサイトではなく、私だけの神聖でユニークな遊び場だ
すべて自分で書き、時間とともに進化している
私のスタイルが人に引っかかることがあるのは確かで、そういう批判には慣れている
自分の好きな形にコンテンツを曲げて押し込むために奇妙な判断をすることもあるが、まさにその点が自分のコンテンツを愛おしいものにしていると思う
外の他のものと同じではないからだ
荒削りな部分はあるだろうが、「個人的な形式」を探求しながら少しずつ良くなっていくだろう :)
私にとってウェブサイトは長期的なアートプロジェクトのようなものだ
作者を表すべきであり、私の場合、自分のサイトは堂々と私自身を表している
あなたのものが出たので、私のものも見せよう
私のウェブサイト、ゲームエンジン、ウェブサーバーは1つのバイナリだ
ソースは C コード1000行で、バイナリサイズは164KB
なぜこんなにクソでかいのかは分からない
ウェブサーバーも自前で含めた
既存のサーバーは隠れた複雑さをあまりにも多く足してくる
出来上がったドイツ語のインタラクティブフィクションゲームはここで見られる: http://vmd34232.contaboserver.net/
トラッキングなし、広告なし、商業目的なし
実行ファイルは upx で圧縮してみるといい https://upx.github.io/
https://toldby.ai/
私のは単一バイナリではなく asp.net だけど
記事で提起しているすべての点には全面的に同意するが、このウェブサイトは例としては少し微妙だ
ウェブサイトが「1つのバイナリ」だと言っているが、デプロイ戦略にはバイナリ成果物を実行する代わりにコンパイルが含まれている
github pages には依存しないと言いながら、openlibrary.org の外部リソースには依存している
自作すれば公開標準を活用できると言うが、
thoughts/内の.htmlファイルは偽の拡張子を付けたプレーンテキスト構造だ人々がこの道を選ぶときは、たいてい初回ページロードにすべてを詰め込もうとするが、ここには動的に提供される静的ファイルが複数ある
Golang コードはどのレスポンスもキャッシュせず、テンプレートもメモリに保持しない
go.modファイルには依存関係が複数あるが、どれも使われていないように見える最も重要なのは、単一バイナリの精神が現代的なインフラと比べてどんな技術的利点を持つのかについての議論がないことだ
個人的には良いアイデアだと思うが、これは悪い例だと思う
ファイルシステムと一緒に動く単一バイナリだ
すべてのコンテンツはファイルシステム上にある
「単一バイナリ」は、ファイルシステムからコンテンツを配信する軽量なGolang ウェブサーバーだ
「非常に高くて変わった基準」とのことだが、変わっているのは確かとしても、結果としてのウェブサイトデザインがひどすぎて、テキストを画面に合わせてまともに表示することすらできていないので、基準はむしろ非常に低い