加具留矢流余

かぐるやるよ

小学校低学年向け学習用プリント作成サービスprillをリリースしました

リリースして3週間くらい経っていますがせっかくリリースしたので記念に記事を書きました。全て応用情報技術者試験のせいでリリースに割くリソースが無かったせいです。(いい訳)

prill.jp

まだそっけないトップページですがサービスとして最低限のものが凝縮されています。

f:id:theflyingcat28:20210419213631g:plain
サービスのイメージ概要

生成したいプリントの条件をセレクトボックスに入れるとそれに応じた問題をデータベースから探してプリントの形に整えてくれます。このサービス作った理由は↓に書いたのでこっちのブログではサービスを構成する技術的なことを書いてみようと思います。

prill.jp

TL; DR

  • puppeteerは軽くてサーバー用途でも使いやすいのでHTML+CSSから画像を生成するサービス作りたならめちゃくちゃ便利だよ!
  • GAEのフレキシブル環境はDockerコンテナを好きに動かせてデプロイも簡単なのでめちゃくちゃ便利だよ!(ただし多少高い)
  • サービス使ってね!

プリント作成機能

メインの機能です。気合いれて作りました。

プリントをフロントエンドで生成 or バックエンドで生成の2択でサービス考案当初は少し悩みましたが、フロントで動かすとなるとブラウザなどのユーザーの環境によって左右されて画一的なプリントを提供できないのでは?ということで割とサックリとバックエンドで作ることに決めました。

なんとなくのサービス構成を考えて次は要件です。要件がふわっとしてる?個人開発なんてこんなんでいいんですよ。

  1. 隙間を埋めるようにちょうどいい感じでレイアウトしたい
  2. 子供が解いてて楽しいデザインにしたい
  3. あとからデザインの修正が簡単にできるようにしたい
  4. 複数の異なる問題形式を同じように扱いたい

1は適切な配置を探索する感じで実現できると思うので一回あたりのレンダリングにかかる時間は短いほうがいいなぁ、デザインの修正が楽な方法となるとCSSとかでいい感じに描画できないかなぁ、4は設計しだいだなぁ、などと考えていて行き着いたのがヘッドレスブラウザを使った画像生成でした。

久々にヘッドレスブラウザについて調べてみると、ヘッドレスブラウザといったらPhantom JS!という時代が終わったことを知りました。じゃあSeleniumでヘッドレスChrome使ってみようかと調べると複数の接続を同時に処理するのは難しそう・・・と絶望していたところでpuppeteerという存在を知りました。

github.com

Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. Puppeteer runs headless by default, but can be configured to run full (non-headless) Chrome or Chromium.

puppeteerはrendertron(サーバーサイドレンダリングのライブラリ)にも採用されているjavascriptライブラリなので、1つのChromeインスタンスで複数のリクエストをぱぱーっと捌くことが出来ます。もうこれ使うしかないじゃんと思って採用しました。

画像を生成する方法さえ決まってしまえばあとはゴリゴリコード書いていくだけでした。プリントを生成するざっくりとした流れは

  1. 問題を使いたい順に並び替える
  2. 空きスペースが最小になるように各大門の問題数を深さ優先探索
  3. レイアウトした問題の情報を収集してQRコードに変換
  4. スクリーンショットを撮って画像に変換

puppeteerのレンダリングにかかる時間によっては2の処理時間が膨大なことになるかもしれないと考えていましたが適当な打ち切り条件を入れれば現実的な時間で動くようになりました。

本当は簡単な問題から難しい問題に変化するようにうまく調整したりしたかったですがリリース優先ということで最低限の機能に絞りました。今後の課題ということでそのうち片付けます。

サーバー

annt作ったanntはフロントエンドがメインのサービスなのでVue使ってひたすらにJSを作り込んでいく作業がメインでした。そのためサーバーサイドはFirebaseでファイル返して少しだけ認証周りを書くだけでも十分なサービスでしたが、一方今回作ったprillはサーバーサイドでゴリゴリプリントを作る必要があるのでサーバーレスではなくてもう少し自由度が高いほうがいいなーと思っていました。プリントの作成をpuppeteerでやりたいからheadless chrome好きに使えて管理は楽なやつという基準で探していくとGoogle App Engineがお手頃そうでGAEに決めました。

GAEにはスタンダード環境とフレキシブル環境があって、後者のフレキシブル環境は好きにDockerコンテナを動かせます。かつ一度環境整えちゃえばデプロイ周りも簡単にできるのでめちゃくちゃ便利です。フレキシブル環境でpuppeteer動かす方法はいつか記事にしようと思います。

www.serversus.work

ただフレキシブル環境は高いです。東京リージョンで最安の構成で動かしていますが月6000円くらいは飛んできます。社会人だから耐えられましたが学生なら死んでました。 

DBは少しお高いですがCloud SQLを使っています。採用したのに深い理由は無く同じGoogleで管理に手間かけたくないと思ったからです。アクセス少ないから最低価格の構成でいいや!と割り切って使ってます。アクセスが欲しい(涙

最後に

見てくれよ俺の自慢のサービス!という記事でした。サービス作ったあとに記事書いてる時間が一番楽しいかもしれません。辛いのは維持。充実したコンテンツを提供できるよう頑張ります。