11月25日(日) に「にじさんじ配信スケジュール」と呼ばれるウェブサービスをリリースしました。
正確には初めてリリースしたサービスでは無いのですが、会員登録機能が用意された本格的なサービスを出した事がこれまでなく、実質的には初めてのサービスと呼んでも良いだろうと考えています。
という訳で、Crieit「個人開発サービスに用いられている技術 Advent Calendar 2018」6日目は「初めてのウェブサービスを WordPress + Vue.js で個人開発した話」と題して、開発に WordPress や Vue.js を用いたこと、ウェブサービスを作るまでの話や、リリース直後の話をしたいと思います。
n番煎じなテーマですし、蛇足に感じられる内容も多々あるかと思いますが、適宜必要な箇所をお読み頂ければ幸いです。
「にじさんじ」と呼ばれるバーチャルライバー (VTuber) グループが存在しています。
僕はこちらのグループのファンなのですが、公式がスケジュール情報の発信を行っておらず、スケジュールを把握しにくい問題がありました。
スケジュール情報を発信する非公式サイトやアプリも存在していますが、閲覧がしにくく使い勝手が悪い状態でもありました。
そこで、スマートフォンでも十分に閲覧でき、にじさんじライバーの配信スケジュールに特化したウェブサービスを作れば需要があるのでは考え、開発に着手しました。
元々はシンプルにスケジュールを確認出来るだけのシンプルなサイト開発を考えていましたが、
自分自身が必要十分に感じるレベル(このサービスユーザーのペルソナの1つは自分自身です!)に加え、サービスとして多くの方々に利用頂く事を前提に機能検討した結果、リリース時は以下の機能を実装しようという結論に至りました。
にじさんじは59名(現在は58名)と多くのライバーを擁します。
ライバー全体の情報を網羅しようとした場合の情報量は馬鹿に出来ません。
ユーザーごとに追っているライバーは異なるため、にじさんじ全体の情報をすべてのユーザーに一律に見せる事はユーザーの負担に繋がります。
また、にじさんじには「1期生・2期生(無印)」「ゲーマーズ」「SEEDs」という3つのグループが存在していますが、それぞれを追っているファン層は異なります。
さらに、グループ問わず人気ライバーを追っている方や、特定のライバーに搾って追っている方など、ユーザーの興味は多種多様です。
そこで、以下のフィルタリング機能を備えることにしました。
フォロー機能を用意する場合、会員機能の実装は欠かせません。
また、当サービスを多くの方に継続的に使っていただくことを考えた場合、アプリっぽいデザインで使いやすい UI を提供する事は欠かせないだろうと考え、フロンロエンドを Ajax で提供することに決めました。
過去に情報の手動更新で苦労した経験があった為、情報の自動取得は欠かせませんでした。
また、テストデータを作成したり、自動化を行った場合であっても、情報の編集は適宜必要となる事から、GUI の管理画面の存在も必要でした。
開発フレームワークとして WordPress を用いた理由ですが、
上のようなものが挙げられます。
特に「管理画面が標準で用意されていること」は重要で、管理画面が必要な状況において、これがあるのと無いのとでは開発工数に雲泥の差が生じます。
データモデルの構造上、複数のデータ項目への検索実装が難しい点が弱点ではありますが、検索を主体としたサービスでは無いため、あまり問題にならないと判断しました。
WordPress にてカスタムフィールドを扱う際 Advanced Custom Fields が欠かせません。
繰り返しフィールド(配列)を簡単に用いることが可能な有料の Pro 版を使用しています。
GUI でデータ構造や管理画面を作成する事ができ、大変重宝しています。
コードを書かずに済む作業は、書かずに越したことがないです。
Ajax でのレンダリングを行う場合、情報元となる API が欠かせません。
以前は admin-ajax.php を利用して API を1から作る必要がありましたが、
今では WordPress コアに標準で API の機能が備わっています。WP-REST API を使わない手はありません。
こちらも WordPress コアに標準で含まれています。
ユーザー画面においてもツールバーの描画に必要で、WordPress を用いる場合欠かせません。
また、後述する Semantic-UI のスクリプトも jQuery で出来ており、jQuery に依存せざる得ない状態です。
とはいえ、単一 DOM の表示切り替えといったシンプルな仕事は jQuery 向きであると言えると思います。
また、Ajax 用の仕組みも備わっており、上のような前提が存在する状況においては、別途 axios といったライブラリを用意しなくとも済む点は引き続き評価出来ます。
Ajax にて取得したデータを用いて画面を構成する場合、開発効率やコードの視認性、いずれを考慮してもビューとコントローラーの仕組みは欠かせないだろうと思います。
Angular, React, Vue.js あたりが採用候補にあたると思いますが、jQuery との併用可能な(最新バージョンを持つ)フレームワークは後者2つのみです。
元々 Riot.js を使っていた身として、またテンプレートエンジンライクな PHP 使いとして、 Vue.js の記法はとても親近感があり書きやすいものでした。
また、Vue CLI, Nuxt.js といった関連技術も充実しており、廃れる心配が少ない技術だろうという点も技術選定の後押しポイントになりました。
UI コンポーネントは Bootstrap が有名で、僕も用いたことがありますが、
あまりにも多くのサイトで用いられている事から見慣れてしまい、飽きを感じ始めていました。
そういった状況で Semantic-UI を見つけた時は感動したのを覚えています。
選定理由としてデザインの好みの影響は多分にありますが、UI パターンが Bootstrap 並に備わっており、技術者として実用に耐えうる UI コンポーネントであると感じています。
会員登録・認証に用いました。
利用に審査が必要となり導入敷居が上がりましたが、
Google 翻訳の手助けを得つつ簡単な英文で申請を行ったところ、サクッと審査がおりました。
また、Gianism と呼ばれる WordPress プラグインがあった為、認証に係る新規コードはほとんど書かずに利用することが出来ました。
YouTube のライブ、動画データを取得する為には欠かせませんでした。
動画 API は REST 形式でも提供されており、利用の敷居はとても低くなっています。
メール通知の際にメール配信の仕組みが必要でした。
今回、サーバーはさくらインターネットさんのものを用いましたが、多くのスパム業者の利用実績の影響からか各プロパイダからの締め付けが強く、標準ポートでのメール配信は厳しいものがありました。
PHPMailer を用いると、Gmail といった各プロパイダからの受信規制の少ないサーバーを利用できるため、メール配信にあたり安心感があります。
サーバーはさくらインターネットVPS(標準2GB) + KUSANAGI という形を取りました。
さくらインターネットVPS は国内サービスのため、契約周りでの安心感がありますし、国内サービスの中での信頼性は随一です。
また、ビジネス目的でのサービスでないため運用コストは抑える必要がありますが、従量課金で無く、不意な請求が絶対に起こりえない点もポイントでした。
KUSANAGI については WordPress サイトを運営する為に必要な nginx, PHP の設定がデフォルトで最適化されており、SSL 化に欠かせない Let's Encrypt も自動で走るなど、WordPress サイトを運営するために至り尽くせりな機能が OS レベルで備わっています。
heroku や Cloud9 といった PaaS に頼る手も検討しましたが、環境セットアップの安易さはそれらのサービスに劣らないことや、さくらインターネットの場合は VPS であってもスケールアップ可能といった特徴を持つことから、最初のウェブサービスはこの構成から始めることにしました。
開発環境は VCCW を用いました。
VCCW とは Vagrant がベースの WordPress 開発に最適化されたツールです。
macOS での導入は一瞬でした。
PaaS ではなく VPS を用いた理由としては VCCW の存在も大きく、同梱された Wordmove で DB 含めたデプロイ(同期)が一瞬で完了するなど、VCCW を用いた際の総合的な体験がとてもスマートで感動しました。
実は、これまで Filezilla (FTP) を主なデプロイ手段としていましたが、どうして早く試さなかったのかと反省しています。
コードはもっぱら Visual Studio Code で書いています。
これまで Sublime Text を用いていましたが、稀に落ちたり OS ごとの挙動差分が気になっていました。
Visual Studio Code は開発環境をベースとしており拡張性も高く安心感がありますし、動作が軽快なためストレスフリーにコードが書ける点がとても評価出来ます。
開発関係のプラグインが豊富である事、検証ツールにてスマートフォンやタブレットの画面エミュレートが安易である点が良いです。
もちろん、最終的な動作確認の際は各種ブラウザ(Safari, Firefox, Edge, Opera, それぞれ最新)・OS(macOS, Windows, iOS, Android, それぞれ最新)でのテストも行っています。
純粋にファイルのバージョン管理目的で用いました。
ちなみにホスト先は Bitbucket、クライアントには SourceTree を用いています。
ハードウェアの好みで用いています。
スペックですがメモリ16GB、CPU Corei7 2.5GHz デュアルコア、SSD 512GBになります。
VCCW にて仮想環境を走らせる都合上、ある程度のメモリが必要となります。
8GB では処理が重く感じられる為、7月に new MacBook から移行しました。
ToDo リスト機能が便利でした。
WordPress のエディタにブロックの概念が導入され、レイアウトレベルで見たまま編集が行えるようになりました。その機能名の事を Gutenberg と呼びます。
WordPress 界隈においては有名な新技術ですが、Gutenberg を無効化する Classic Editor を入れ導入を見送りました。
以下のような理由からです。
フロントエンド中心の開発の勉強も兼ねて用いることを考えましたが、自動化にあたってスクレイピングが必要で、サーバーサイド中心の開発にせざる得ませんでした。
複雑なデータモデルが必要であったり、検索が重要となるサービスを開発する場合は WordPress では限界があったと思いますが、そうではありませんでした。
前者2つについては、掲示板など会員管理周りの機能が充実している事やエディタのリッチさが売りかと思われますが、その点において今回メリットには感じませんでした。
baserCMS については、CakePHP がベースに採用されており、かつ管理画面も備わっている事から、開発者目線ではとても魅力的です。
今回は採用していないですが、データモデルが複雑で、管理画面もサクッと用意したいという状況においては、選ばざる得ない選択肢だと思われます。
Movable Type は WordPress 以上に一般サイト制作に特化しており、会員管理等の標準機能が弱い印象があります。
入れれば速くて良いのですが、コストが気になります。趣味のサービスには向かないでしょう。
今回は KUSANAGI (nginx + サーバーキャッシュ) に頑張ってもらっています。
実はまともに用いたことがありません。(勉強せねば…)
ただ、これらのツールが活用できずともウェブサービスを開発し運用を開始出来る状態になる事が分かります。
文章や写真ベースの記事がほとんど無く、JavaScript に頼るページも多く導入は見送りました。
ただ、Vue.js でのレンダリング結果を Googlebot が拾ってくれない都合で、Vue.js のレンダリングが完了するまでは SSR の結果を表示する仕組みを入れた事で、JavaScript に頼るページがほとんど無くなりました。
AMP を導入した場合 SEO 効果も期待できるため、後々導入する可能性があります。
アプリっぽい見た目にした事や Ajax での情報取得は PWA 化を見越しての方法でもありました。
一旦 apple-touch-icon の設定でお茶を濁しましたが、AMP 同様後々導入する可能性があります。
VCCW のお陰で、動作環境としては Linux ベースで開発が出来ており、本番サーバーに環境も近いはずで、環境を揃える意味ではほとんど不要だろうと考えていたのですが、本番リリース直前に本番でのみ発生する不具合に見合わされました。
始めから Docker ベースでの開発であればそのような悩みも発生しなかっただろうと思います。
今後の新規開発の際に導入を検討する可能性がありそうですが、費用を中心に何かとコストが増えやすい為、趣味のサービス開発での導入は難しそうです。
上で記載した以外の点について触れたいと思います。
開発開始からわずか数日ほど経ったタイミングで、VTuber のスケジュールを扱うサービスが登場しました。
一見デザインも綺麗で、にじさんじ以外も含め、様々な VTuber のスケジュールが登録されています。
ただ、スケジュールが不十分な部分があったり、にじさんじ好きにとってはノイズとなる情報も多いなど、欠点や方向性の違いによる差がある事も分かってきました。
当初の目的を常に意識しながら、なんとかリリースする事が出来ました。
現在 @nijisanji_net というアカウントを用いていますが、元々はドメイン取得時に別のアカウント名で作成し放置していたところ、何故か凍結の事態に…
このような事は初めてでしたが、凍結直後に気づくことが出来ず、凍結解除申請も虚しく現在も凍結されたままになっています。
惜しかったですが、思い切って別アカウントを作成し事なきを得ました。
スクレイピング対象に想定外のパターンの文字列が混ざった場合、データに不具合が発生します。
中にはスクレイピング先情報の typo など、どうしようもないものもありますが、
大きなデータ崩れが発生しないように抑えるべく、多くの分岐処理が必要となりました。
スクレイピングは本サービスのコア機能になりますが、最も実装に時間のかかった部分でもありました。
リリース直前に noindex,follow 指定で本番環境でのテストを行っていた影響で、この記事を書いている現在もエラーを吐く状態となっています。
当初は別に問題があるのではといろいろ試したのですが、不慣れのため、単純な時間の問題だろうと気づくまでにとても時間がかかりました。
Search Console 上の問題もあり、時間が経つまでの検索インデックスは DOM に頼るしかない状態となっていましたが、
その問題に追い打ちをかけるように Googlebot 上で Vue.js が機能しない問題にぶち当たりました。
Googlebot で JavaScript を解釈できる事は知っていましたが、Vue.js など一部のスクリプトが正しく認識されない問題についての知識が無く、これには参りました。
結局 Vue.js で出力される内容をサーバーサイドレンダリング (SSR) させ、 Vue.js が読み込まれるまでの間の表示をサーバー側に任せる事でなんとか事なきを得ました。
9月9日に開発を開始し、11月25日に公開しました。
開発期間は約3ヶ月、累計作業工数は142時間でした。
当初はせいぜい数十時間で終わるだろうと見込んで開発を開始しましたが、実際はサービス開発を行いながら仕様を詰めており、当初の想定よりも機能が増えたことから、予定よりも工数が嵩んでしまいました。
また、作成していたプログラムの不具合の影響で、手動で作成していたライバーデータを全て別データで上書きしてしまったのですが、そのライバーデータの作成に10時間近くかかっており、再度同様の工数が発生しました。
さらに、リリース直前に発生した本番環境限定の不具合もあり対処に10時間ほど時間が取られてしまいました。
実際にかかった時間と比較し20時間〜30時間ほどは短く出来たのではと思います。次に活かしたいです。
余談ですが、改めて2つ歳下のせせりさんのすごさを実感しました。
ポッドキャストやブログでのアウトプット、仲間との Discord など、日常的に様々な趣味活動を行っていましたが、業務、他のプライベートでの活動も含め忙しく、削れる活動は制限する事に。
もちろん、万人が意識する事でも無いと思いますが、忙しい社会人が開発を継続していく為には、多少他の活動を制限する覚悟が必要だと感じています。
とは言いつつも、仕事も開発、プライベートも開発で休み無しという状況では、つらい日々が続きます。
趣味のアニメ視聴時間は一切削らず、本サービスで扱っている VTuber 動画の視聴時間もある程度確保した事は、
モチベーションの維持に大きく貢献しただろうと思います。
運営者ギルドのメンバーとなりましたが、他のみなさんの発言は「自分も頑張らないと」という刺激になりました。
公開から数日たった現在は多少慣れましたが、公開1日目は気づいたら Analytics の画面を見ている状態で本当に落ち着きませんでした。
理論上は自動化出来ているため、運用に時間が取られることも少ないだろうと考えていましたが、実際は更新ツールの不具合を修正したり、データを一部手直ししたり、アクセス数を増やすための SEO や PR を行ったりと、100%の自動化は中々難しく今後の課題であると感じています。
サービス開発においても使用感は悪くなかったです。
そもそもとして、開発フレームワークではない WordPress を開発に用いる事に対する心配をお持ちの方は多いと思われますが、上に記載した通り
データモデルの構造上、複数のデータ項目への検索実装が難しい点が弱点
問題はこの程度だと考えています。
大規模な開発になった際に、規約が少なくコードの品質が担当者間で不揃いになりやすかったり、
データモデルの都合上パフォーマンスの問題も出てきますが、
個人開発レベルにおいてはほとんど心配する事ではないだろうと思いますし、
現実的な対策は十分可能ですので今後業務の開発でも用いると思います。
リリース後に SEO 面の問題が発生した為、フロントエンド技術に頼った開発は難しそうだと実感させられました。
ただ、今回のようなサーバーサイド技術との併用であれば小回りも効くため、十分実用的ではと思います。
下記2点があり、併用には全く支障がありませんでした。
Semantic-UI と Vue.js のかみ合わせがあまりよろしくなく、
Semantic-UI 内の JS ライブラリで作成したフォームの value が Vue.js 側で上手く取得できませんでした。
Semantic-UI に value を直接返す関数が提供されておりどうにかなりましたが、
サードパーティ製ではあるものの Semantic UI Vue と呼ばれる UI コンポーネントも存在している事から、今後はそちらを使っていく可能性があります。
一部不具合も残っているため、それの改善も含めた継続的なサービス運用を目指したいです。
また、ある程度機能を絞ってリリースしており、残りの機能もしっかり開発できればと考えています。
現状、Twitter のフォロワーは 50 に満たず、まだ SEO の効果も出ていないことからアクセス数はご察しのとおりです。
趣味のサービスのため、数字や結果が最優先ではありませんが、折角ですのでにじさんじファンの半数程度(数万人)に利用して頂けるサービスを目指せればと考えています。
上で記載の通り、継続運用の為の対策を打ったり、機能拡張も計画しており、新規着手までは中々骨が折れそうですが、平行開発も踏まえ新しいサービス開発にも取り組めればと考えています。
ぶっちゃけるとほとんど書いていません。要件を前述のメモ (Apple) に数行書いた程度です。
代わりにコードへのコメントはしっかり入れています。
また、可能な限り WordPress コア標準の仕組みを用いています。
さらに作業中に発生した不要なコードやデータは逐次削除するなど、
仕様書が無くとも現状の確認で全体像が見えやすい工夫を行いました。
趣味の個人開発だから出来ることだと思います。
念の為補足ですが、余裕があれば情報は残すに越したことは無いと思います。
数年前に月間数十万PVのサイトを運営していた事もありますが、 Adsense も大した額にはなっていませんでした。
本サービスでも同等のアクセス数が稼げれば広告の導入を検討しますが、利便性も下げますので、導入は慎重に判断したいと思います。
そもそも趣味のサービスですし、権利問題も絡みますので考えてないですが、公式関係者の方々にも使って頂けるサービスにはしたいと考えています。
自分のような素人の書いた記事が参考になるのだろうか、と思う節もあり、中々重い腰が上がらなかったのですが、
すごいですね~。個人開発はじめたい人とかだとどうやってるか知りたい人多いかもしれないので、もし気が向いて且つ12月もたまたま無茶苦茶暇だったらカレンダーも是非whttps://t.co/iGA3PpFL6U
— だら@技術系投稿サービス運営中 (@dala00) November 26, 2018
Crieit のだらさんに直接お誘い頂き執筆するまでに至りました。
改めてお誘い頂きありがとうございました。
何かしらの Advent Calendar への参加は初となりますが、夢でもあったので参加出来たことはとても光栄でした。
また、これからウェブサービス開発を考えている方や、ウェブサービス開発中の方の一助になれば幸いです。
ご質問、ご指摘、アドバイス大歓迎です。コメントや @sola_io までリプライ、お気軽にお寄せ下さい。
ここまで読んで頂いたすべてのみなさま、本当にありがとうございました。
個人開発サービスに用いられている技術 Advent Calendar 2018、明日は Hiroz さんの「Koretteのオモテとウラ」になります。
そもそも「Korette」って何?というところも含め、とても気になりますね。
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント