マークダウンで投稿できるメディアサービスです
AWSにて構築しました (※ポートフォリオとしての目的を達成したため、現在、運用及び公開を停止しております。)
※ メールリレーは、ドメインを取得したところでメールアドレスがタダでもらえた関係で、提供されているSMTPサーバーをお高いNAT Gatewayを回避しつつ使うために追加しました
エンジニアになるにあたって、日々の細々としたメモから研究、はては文芸まで多彩にこなせるエディタ実装がほしいな、 と思って探してみたものの、コレ!というものが見付からず自分で作ってみるかというのが動機です。
バックエンド
フロントエンド
共通(Markdown Parser)
アプリケーション
開発環境
デモ環境
React, エディタ部分にはCodemirrorを利用して実装しています。なお、Codemirrorは装飾できるTextareaみたいな立ち位置での実装になっており ほとんどの機能を活用できていないので、今後の課題です。
エディタを作るにあたって生DOMを操作するのは辛いのでReactを導入しました。 使っていくうちに、これは便利だということでUIの一部をReact化しました。
ransackによる検索機能の実装のほか、検索結果のハイライト機能(正規表現、rails highligter)を実装しました。 検索フォームはReactで、検索結果はRails viewによる実装です。
ページネーションはgem kaminariにて実装しています。
よくみかけるアバターのクロップUIをつけてみたかったので、Canvasにより実装しました。 サーバーへはDataURLによりPostしているので、バリデーション前に変換を行い、gem CarrierWaveへ渡しています。
Reactを導入したものの、Railsの各コントローラのCURDを叩くのが辛かったので一部の機能のAPIを用意しました。 設計はRESTを参考にして、外部に公開する予定はないのでログイン機構は通常のクッキー&セッション方式を流用しています。
Fetch APIを各箇所で直接呼ぶのは仕様変更時にめんどくさいので、APIを一元処理するラッパーを作って比較的楽に拡張等ができるようにしました。 Railsのmodel単位で扱えるようにしています。
リスト表示等で同じユーザーの情報が多数必要な場合、各コンポーネントでキャッシュを実装するのは煩雑なので、 APIのラッパーにおいて透過的なキャッシュ機構を実装してサーバーの負荷低減を図っています。 TurbolinksにのっかっていることによりSPA化しているので、ページ遷移後でもキャッシュが効ききます。
サーバーサイドでフロントでのマークダウンプレビューと出力結果を同じにするために、WebAssemblyを使っています。 そのWebAssemblyへのコンパイルが簡単そうだったRustも導入しました。WebAssembly化は簡単だけど、Rust自体は超重量級だったので苦労しました。 なお、パーサーは別のプロジェクトとして切り出して、こちらではnpm packageとしてインストールする運用にしています。
マネジメントコンソールでぽちぽち頑張っていましたが、トライ&エラーが重なると辛かったので、 Terraformを導入しました。非常に楽チンです。
画像等のリソースを配信するためのサーバーをCloudFront + S3にて構築しました。 S3へのアップロードはfog_awsとCarrierWave gemで行っています。
開発時間の半分以上はRustとの取っ組み合いに消費してしまいました。ポートフォリオという点では全く本質的ではない箇所に 注力してしまったので、反省しています。出発点は自分で使いたいという理由なので、今後もオレオレ構文&機能を目指して開発は継続する予定です。
開発環境はWSL2上のUbuntu内でDockerを使用しています。Docker内で生成されたvolume上のファイルをホスト側(Ubuntu)で編集するために パーミッションをごちゃごちゃ操作しているのですが、それが原因と思われる数々のよくわからないエラーに悩まされました。