tag:crieit.net,2005:https://crieit.net/tags/Vagrant/feed 「Vagrant」の記事 - Crieit Crieitでタグ「Vagrant」に投稿された最近の記事 2021-05-21T01:14:28+09:00 https://crieit.net/tags/Vagrant/feed tag:crieit.net,2005:PublicArticle/17180 2021-05-19T09:57:20+09:00 2021-05-21T01:14:28+09:00 https://crieit.net/posts/Vagrant-Temporary-failure-resolving-DNS Vagrant で Temporary failure resolving となる問題の解決 - イントラネット DNS 編 <p>Vagrant で Ubuntu の VM を立ち上げたとき、 apt 等を行おうとすると、以下のようなエラーに遭遇した。</p> <pre><code class="plain">client: Err:1 http://security.ubuntu.com/ubuntu focal-updates/main amd64 libjpeg-turbo8 amd64 2.0.3-0ubuntu1.20.04.1 client: Temporary failure resolving 'proxy.local.example' </code></pre> <p>上記のエラーの内容はプロキシに接続できないというものだが、 問題のポイントはプロキシかどうかはあまり関係が無く、 名前解決に失敗しているという部分だ。<br /> こういうのはだいたい <code>systemd-resolved</code> のスタブリゾルバ周りの問題だと相場が決まっている。</p> <p>…ということで、順番に確認しながら問題を解決していこう。</p> <p>なお、 使った box は <code>generic/ubuntu2004</code> で、 VirtualBox で VM をホストしている。</p> <h2 id="スタブリゾルバの確認"><a href="#%E3%82%B9%E3%82%BF%E3%83%96%E3%83%AA%E3%82%BE%E3%83%AB%E3%83%90%E3%81%AE%E7%A2%BA%E8%AA%8D">スタブリゾルバの確認</a></h2> <p>まず、 <code>resolv.conf</code> を確認してみる。</p> <pre><code class="plain">$ cat /etc/resolv.conf # This file is managed by man:systemd-resolved(8). Do not edit. # # This is a dynamic resolv.conf file for connecting local clients to the # internal DNS stub resolver of systemd-resolved. This file lists all # configured search domains. # # Run &quot;resolvectl status&quot; to see details about the uplink DNS servers # currently in use. nameserver 127.0.0.53 </code></pre> <p>テキストファイルのコメントに書いてあるとおり、コイツを書き換えるのは悪手。</p> <p>ネームサーバーが 127.0.0.53 を指しているが、 これが <code>systemd-resolved</code> のスタブリゾルバだ。</p> <p>ここで言う<strong>リゾルバ</strong>とは、ドメイン名を元にIPアドレスを解決する仕組みのことを指していて、 DNS なども同様の機能を持っている。<br /> その中でも、<strong>スタブリゾルバ</strong>は、(「スタブ」と言うだけあって、)それ自身はドメイン名とIPの対応リストを持たずに、 DNS 等の他のリゾルバを呼び出して解決する仕組みをもっている、ローカルのサービスだ。<br /> ローカルアプリケーションが直接 DNS を参照せず、一旦スタブリゾルバを参照することで、 <code>systemd</code> で管理された適切な DNS を自動的に参照されるようになったり、 DNS では解決できない <code>hostname.local</code> といったホスト名ベースの名前解決 (mDNS) を行えるようになっている。</p> <p>さて、 そのスタブリゾルバがどう動いているか <code>resolvectl status</code> で確認してみよう。</p> <pre><code class="plain">$ resolvectl status [...] Global Current DNS Server: 4.2.2.1 DNS Servers: 4.2.2.1 4.2.2.2 [...] Link 2 (eth0) Current Scopes: DNS DNSSEC supported: yes Current DNS Server: 4.2.2.1 DNS Servers: 4.2.2.1 4.2.2.2 208.67.220.220 10.0.2.3 </code></pre> <p>4.2.2.1 や 208.67.220.220 などが DNS に設定されているのがわかる。<br /> これらは、いわゆるパブリックDNSだ。</p> <p>実は、先ほど名前解決できなかったプロキシは、 LAN 内のサーバーだった。 このため、 パブリックDNSに問い合わせられてしまっては、名前解決ができないのも当然だ。</p> <h2 id="パブリックDNS はどこで設定されているのか"><a href="#%E3%83%91%E3%83%96%E3%83%AA%E3%83%83%E3%82%AFDNS+%E3%81%AF%E3%81%A9%E3%81%93%E3%81%A7%E8%A8%AD%E5%AE%9A%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%81%AE%E3%81%8B">パブリックDNS はどこで設定されているのか</a></h2> <p>名前解決に失敗する理由はわかった。 しかし、この DNS はどこで設定されているのか?</p> <p>ざっと確認してみたところ、 <code>resolved.conf</code> の設定と、 仮想マシン内の NAT を繋いだ NIC の netplan 設定に、それっぽい設定が書かれていた。</p> <pre><code class="plain">$ cat /etc/systemd/resolved.conf [Resolve] DNS=4.2.2.1 4.2.2.2 208.67.220.220 </code></pre> <pre><code class="plain">$ cat /etc/netplan/01-netcfg.yaml network: version: 2 renderer: networkd ethernets: eth0: dhcp4: true dhcp6: false optional: true nameservers: addresses: [4.2.2.1, 4.2.2.2, 208.67.220.220] </code></pre> <p>これらは通常の Ubuntu のインストールプロセスでは設定されないので、 <code>generic/ubuntu2004</code> の box の作成者の味付けなのだろう。</p> <p>これらの DNS のアドレスの設定を、プライベートネットワーク内の DNS のアドレスに書き換えてしまえば、きっと意図した動作に近づくはずだ。</p> <h2 id="スタブリゾルバを使わずに LAN内 の DNS を指定する"><a href="#%E3%82%B9%E3%82%BF%E3%83%96%E3%83%AA%E3%82%BE%E3%83%AB%E3%83%90%E3%82%92%E4%BD%BF%E3%82%8F%E3%81%9A%E3%81%AB+LAN%E5%86%85+%E3%81%AE+DNS+%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B">スタブリゾルバを使わずに LAN内 の DNS を指定する</a></h2> <p>スタブリゾルバは、細かい優先度合いの制御などを外から行えない。 これはネットワークの状況に応じて最適調整してくれる設計だからなのだが、 Vagrant で立ちあげる VM のように、 NAT の DNS や ローカルの DNS が混在していると、うまく調整できずに、こういった問題の解決がやりにくい。</p> <p>スタブリゾルバを動かしているままでも問題なく動いているのならそれでもかまわないのだが、 上記の DNS の書き換えを行ってもどうも意図通りに名前解決されない場合は、 <code>systemd-resolved</code> のスタブリゾルバを使わずに、 <code>/etc/resolv.conf</code> の nameserver を切り替えるようにしたい。</p> <p>具体的には、 <code>/etc/resolv.conf</code> が <code>../run/resolvconf/resolv.conf</code> へのシンボリックリンクになっているところ、 <code>../run/systemd/resolve/resolv.conf</code> へのシンボリックリンクに書き換える。<br /> こうすることで、 <code>resolved.conf</code> や netplan で設定した DNS が直接 <code>/etc/resolv.conf</code> の nameserver に書かれるようになる。<br /> 詳しくは、 <a target="_blank" rel="nofollow noopener" href="https://translate.google.com/translate?hl=ja&sl=en&u=https://man.archlinux.org/man/systemd-resolved.8.en&prev=search&pto=aue">systemd-resolved.service のマニュアル</a> あたりを見て欲しい。</p> <p>…と、このような書き換えを、 Vagrantfile の定義に書き落とすと、以下のようになる。<br /> なお、以下は <code>192.168.11.1</code> がローカルネットワークの DNS のアドレスである場合の例なので、適宜書き換えていただければと。</p> <pre><code class="ruby">config.vm.provision :shell, inline: <<-'SHELL' ln -sf ../run/systemd/resolve/resolv.conf /etc/resolv.conf sed -i -E '/nameservers:/{n; s/(addresses:).*/\1 [192.168.11.1]/}' /etc/netplan/01-netcfg.yaml netplan apply sed -i -E 's/(^\s*DNS\s*=\s*).*$/\1192.168.11.1/' /etc/systemd/resolved.conf systemctl restart systemd-resolved.service SHELL </code></pre> <p>そうすると、 <code>resolv.conf</code> の中身が以下のように netplan の設定などから求められた DNS に置き換えられ、スタブリゾルバを経由せずに名前解決されるようになる。</p> <pre><code class="plain">$ cat /etc/resolv.conf # This file is managed by man:systemd-resolved(8). Do not edit. # # This is a dynamic resolv.conf file for connecting local clients directly to # all known uplink DNS servers. This file lists all configured search domains. # nameserver 192.168.11.1 nameserver 10.0.2.3 </code></pre> <p>このようになれば、ローカルの DNS でキチンと名前解決されるようになるだろう。</p> advanceboy tag:crieit.net,2005:PublicArticle/15510 2019-10-27T15:10:52+09:00 2019-10-30T22:31:59+09:00 https://crieit.net/posts/1fed4cfffba68fc79557e060d24d5a18 個人開発でサイトリリースした理由とやったこと <p><a href="https://crieit.now.sh/upload_images/5b0212fe52d73d692cba535132678c2c5db990c43e5a5.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/5b0212fe52d73d692cba535132678c2c5db990c43e5a5.jpg?mw=700" alt="個人開発でサイトリリースした理由とやったこと" /></a><br /> こんにちは。ケイジです。<br /> ボルジムというボルダリングジム検索ウェブサービスを制作し運営しています。</p> <p>今回、このサービスをリリースするまでにやったことを綴ることによって、誰かの役に立つのではと思い記事を書きました。</p> <h1 id="なぜ創ったか"><a href="#%E3%81%AA%E3%81%9C%E5%89%B5%E3%81%A3%E3%81%9F%E3%81%8B">なぜ創ったか</a></h1> <p>この数年、ボルダリング沼にとっぷりと浸かってしまい、週イチの社内ボルダリング部活動と週末の自主活動の週2回ボル活をするのが習慣になっています。たまにボルダリングができない週末があると気持ちも体も落ち着かずムズムズし週明けの仕事に差し支えるまでに。</p> <p>また個人開発もしばらくご無沙汰していて何か創りたい欲がフツフツと湧いてきたタイミングでもあったので、エイヤ!とボルダリングジム検索ウェブサービスを創りました。<br /> 首都圏近郊のボルダリングジムの口コミなどの情報が閲覧、投稿できるウェブサービスになります。</p> <p><a target="_blank" rel="nofollow noopener" href="https://boulgym.com/?ref=crieit">ボルジム・首都圏近郊ボルダリングジム検索サイト</a></p> <p>好きなこと ✕ 好きなことの掛け合わせだから、それはそれは楽しいだろうと。</p> <h1 id="やったことリスト"><a href="#%E3%82%84%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8%E3%83%AA%E3%82%B9%E3%83%88">やったことリスト</a></h1> <p>ボルジムを立ち上げるために、したことは以下のようになります。</p> <h2 id="プログラミング言語、フレームワークを選ぶ"><a href="#%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E%E3%80%81%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%92%E9%81%B8%E3%81%B6">プログラミング言語、フレームワークを選ぶ</a></h2> <p><a href="https://crieit.now.sh/upload_images/fe96233f19a7998d16e424d92bfc351c5db53460a28f2.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/fe96233f19a7998d16e424d92bfc351c5db53460a28f2.jpg?mw=700" alt="logos01.jpg" /></a></p> <p>以前はCakePHPでの開発経験はあったものの、ここ数年はWordPressのカスタマイズをメインに仕事をしているため、どの言語とフレームワークで開発するのかをまず選定しました。</p> <p>候補に挙がったのは以下のフレームワークになります。<br /> ※カッコ内はプログラミング言語</p> <ul> <li>Laravel(PHP)</li> <li>WordPress(PHP)</li> <li>Ruby on Rails(Ruby)</li> <li>Django(Python)</li> </ul> <p>選定にあたってはGoogleトレンドでまずざっくりと最近の検索結果の多いものをリストアップしました。</p> <p>また、求人が多いフレームワークは今勢いのあるものだろうと推測し、国内と海外のリクルートサイトで求人数の多いもので絞り込みもしました。</p> <p>結果、学習期間にあまり時間を使いたくないということで個人的なPHP慣れもある、LaravelとWordPressの二択になったのですが、開発の自由度の高いLaravelに決定しました。</p> <h1 id="環境づくり"><a href="#%E7%92%B0%E5%A2%83%E3%81%A5%E3%81%8F%E3%82%8A">環境づくり</a></h1> <p><a href="https://crieit.now.sh/upload_images/5396069f54a02c0404723081c571a00a5db5348995da3.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/5396069f54a02c0404723081c571a00a5db5348995da3.jpg?mw=700" alt="logos02.jpg" /></a><br /> 環境づくりはできるだけ仕事で使い慣れているものを選択。</p> <h2 id="ローカル開発環境"><a href="#%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83">ローカル開発環境</a></h2> <p>Vagrant一択でした。</p> <h2 id="ソースコード管理"><a href="#%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89%E7%AE%A1%E7%90%86">ソースコード管理</a></h2> <p>BitbucketでGitコードを管理。<br /> 現在はGitHubでプライベートリポジトリを作成できるとのことなので今選ぶならそっちになるかもしれません。</p> <h2 id="ウェブサーバ"><a href="#%E3%82%A6%E3%82%A7%E3%83%96%E3%82%B5%E3%83%BC%E3%83%90">ウェブサーバ</a></h2> <p>さくらのレンタルサーバを使ってます。</p> <h2 id="サイトデザイン"><a href="#%E3%82%B5%E3%82%A4%E3%83%88%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3">サイトデザイン</a></h2> <p>いつも使い慣れているものを使いました。<br /> パーツ、ロゴやイラスト制作は、Adobe IllustratorとPhotoshop。<br /> サイト全体とUIデザインにはSketchを使用。</p> <h1 id="学習方法"><a href="#%E5%AD%A6%E7%BF%92%E6%96%B9%E6%B3%95">学習方法</a></h1> <h2 id="Laravel学習法"><a href="#Laravel%E5%AD%A6%E7%BF%92%E6%B3%95">Laravel学習法</a></h2> <p>Laravelについてはまったく触ったことがなかったので、ドットインストールのプレミアム会員になり、動画学習しました。</p> <p>まず、Laravelをローカル環境で使うにあたって必要な<a target="_blank" rel="nofollow noopener" href="https://dotinstall.com/lessons/basic_sqlite_v2">SQLite入門</a>をざっと一周します。</p> <p>次に、<a target="_blank" rel="nofollow noopener" href="https://dotinstall.com/lessons/basic_laravel_v2">Laravel 5.5入門レッスン</a>をざっと1周して概要をつかみ、次に実際にローカル環境で手を動かしてチュートリアルウェブアプリをつくりながらもう1周しました。</p> <p>ドットインストールは構成が初学者にとって非常に分かりやすく、動画一つが3分前後ととっつきやすくておすすめです。<br /> Vagrantについても最初はこのサイトで学習しました。</p> <p>プレミアム会員になると女性ボイスが選択できるのと、再生スピードが変更できるのが個人的に良い機能だと思います。</p> <p>という感じでざっくりとLaravelについて理解が深まったところで、<a target="_blank" rel="nofollow noopener" href="https://laravel10.wordpress.com/category/%e3%81%af%e3%81%98%e3%82%81%e3%81%a6%e3%81%ae-laravel/">ララ帳「はじめてのLaravel」</a>を参考にしつつ、実際にウェブサイト開発をしていきました。</p> <p>分からないところは随時ググりながら進めました。<br /> 頻繁に使ったのは<a target="_blank" rel="nofollow noopener" href="https://readouble.com/laravel/">readouble</a>(日本語版Laravelドキュメンテーション)になります。翻訳してくれている有志の方々ありがとう。</p> <p>英語に抵抗がなければ<a target="_blank" rel="nofollow noopener" href="https://laravel.com/docs/6.x">laravel documentation</a>の方が情報も早く、デザインも見やすいためおすすめです。</p> <h1 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h1> <p>という感じのことを、休日や出勤前や後に細々と続けていき大体6ヶ月ほどかけてリリースまでこぎつけました。</p> <p>この記事が少しでも読まれた誰かの一助になれば幸いです。</p> <p>では、よいものづくりライフを!</p> ケイジ tag:crieit.net,2005:PublicArticle/14841 2019-02-28T04:11:43+09:00 2019-03-05T16:02:58+09:00 https://crieit.net/posts/LAN-Pleroma-Vagrant-Box-OS LAN内ですぐに使えるPleromaのVagrant Box(構築済みゲストOSのひな形)を作った <p>表題の通り。本記事の半分はインストール方法でできています。</p> <h2 id="Pleroma is 何"><a href="#Pleroma+is+%E4%BD%95">Pleroma is 何</a></h2> <blockquote> <p>PleromaとはElixirで書かれた分散型SNSのひとつ.</p> <p>GNU SocialやMastodonとも連携することが可能.Pleromaによればラズパイでも動く軽さが特徴.</p> </blockquote> <p>※<a target="_blank" rel="nofollow noopener" href="https://murabitoleg.com/pleroma/">分散型SNSのPleromaをDocker+Macでローカルに構築する from てくてくぷれいす by しまさん</a>様より引用</p> <h2 id="Pleroma用Vagrant Boxからサーバの立ち上げまでの手順"><a href="#Pleroma%E7%94%A8Vagrant+Box%E3%81%8B%E3%82%89%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AE%E7%AB%8B%E3%81%A1%E4%B8%8A%E3%81%92%E3%81%BE%E3%81%A7%E3%81%AE%E6%89%8B%E9%A0%86">Pleroma用Vagrant Boxからサーバの立ち上げまでの手順</a></h2> <p>以下の手順はWindows、macOS、Linuxで共通です。ただし、Windows 10 Homeでのみ確認を行っています。</p> <ol> <li>Oracle VirtualBoxをインストールします。<a target="_blank" rel="nofollow noopener" href="https://www.virtualbox.org/wiki/Downloads">ダウンロードページ</a></li> <li>Vagrantをインストールします。<a target="_blank" rel="nofollow noopener" href="https://www.vagrantup.com/downloads.html">ダウンロードページ</a></li> <li>コマンドプロンプトなどのターミナルにて自分の好きなフォルダへ移動します。</li> <li>下記コマンドを実行します。Vagrant Box(構築済みゲストOSのひな形ファイル)のダウンロードと登録、<code>Vagrantfile</code>という設定ファイルの生成が行われます。<br /> <code>vagrant init hidao/Pleroma099</code></li> <li>テキストエディタで先ほどのコマンドによって生成された <code>Vagrantfile</code> の最後の <code>end</code> の前の行に以下の行をコピペします。<br /> <code>config.vm.network "public_network", ip: "192.168.0.221"</code></li> <li>以下のコマンドを実行します。構築済みゲストOSのインストールが行われます。しばらくかかるのでコーヒーを淹れて待ちましょう。<br /> <code>vagrant up</code></li> <li>ターミナルにプロンプトが表示されていればゲストOSが実行中になっています。ブラウザから <code>http://192.168.0.221</code> にアクセスしましょう。</li> </ol> <p>以上の手順でLAN内からアクセスできるゲストOS上のPleromaの準備が完了です。</p> <p>ユーザの追加はブラウザからできますが、「つながっているすべてのネットワーク」に別のサーバを登録したいときには、ゲストOS内でコマンドを実行する必要があります。</p> <p>その方法は他の記事に譲ります。</p> <h2 id="【重要】ゲストOSの停止方法"><a href="#%E3%80%90%E9%87%8D%E8%A6%81%E3%80%91%E3%82%B2%E3%82%B9%E3%83%88OS%E3%81%AE%E5%81%9C%E6%AD%A2%E6%96%B9%E6%B3%95">【重要】ゲストOSの停止方法</a></h2> <p>Vagrantでは、ゲストOSを停止させずにホストOSを終了しようとしたとき、ゲストOSが邪魔をしてホストOSのシャットダウンを中断させてしまいます。</p> <p>そのため、ホストOSをシャットダウンさせる前に、起動したすべてのゲストOSをシャットダウンさせる必要があります。</p> <h3 id="ゲストOSのシャットダウン方法"><a href="#%E3%82%B2%E3%82%B9%E3%83%88OS%E3%81%AE%E3%82%B7%E3%83%A3%E3%83%83%E3%83%88%E3%83%80%E3%82%A6%E3%83%B3%E6%96%B9%E6%B3%95">ゲストOSのシャットダウン方法</a></h3> <p>ターミナルより、起動したゲストOSの <code>Vagrantfile</code> があるフォルダに移動して、次のコマンドを入力します。</p> <pre><code class="sh">vagrant halt </code></pre> <p>ゲストOSをシャットダウンさせた旨のメッセージが出たら、ゲストOSが正常終了されています。</p> <p>ホストOSをシャットダウンさせる前に、すべてのゲストOSをシャットダウン(<code>vagrant halt</code>)するようにしましょう。</p> <h2 id="おわりに"><a href="#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB">おわりに</a></h2> <p>Pleromaの環境構築用にdocker-compose等もありますが、あれはあれで癖があるのと、「構築済み環境が一発で立ち上がる」のを目標にVagrant Boxを作成してみました。</p> <p>Vagrant Cloudデビューも兼ねていたので至らぬ点があるかもしれませんが、お気づきの点があるときはコメントまたはQiitadonのアカウント(@hidao)までご連絡ください。</p> <p>それでは素敵なPleromaライフを!</p> hidao tag:crieit.net,2005:PublicArticle/14628 2018-12-06T00:00:50+09:00 2018-12-09T13:50:54+09:00 https://crieit.net/posts/WordPress-Vue-js 初めてのウェブサービスを WordPress + Vue.js で個人開発した話 <h1 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h1> <p>11月25日(日) に「<a target="_blank" rel="nofollow noopener" href="https://nijisanji.net/">にじさんじ配信スケジュール</a>」と呼ばれるウェブサービスをリリースしました。</p> <p><a href="https://crieit.now.sh/upload_images/97a83c7d3562ab645bbaeeacb5f4d9035c0474bf97d50.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/97a83c7d3562ab645bbaeeacb5f4d9035c0474bf97d50.png?mw=700" alt="にじさんじ配信スケジュール" /></a></p> <p>正確には初めてリリースしたサービスでは無いのですが、会員登録機能が用意された本格的なサービスを出した事がこれまでなく、実質的には初めてのサービスと呼んでも良いだろうと考えています。</p> <p>という訳で、<a href="https://crieit.net/">Crieit</a>「<a href="https://crieit.net/advent-calendars/2018/technology">個人開発サービスに用いられている技術 Advent Calendar 2018</a>」6日目は「初めてのウェブサービスを WordPress + Vue.js で個人開発した話」と題して、開発に WordPress や Vue.js を用いたこと、ウェブサービスを作るまでの話や、リリース直後の話をしたいと思います。</p> <p>n番煎じなテーマですし、蛇足に感じられる内容も多々あるかと思いますが、適宜必要な箇所をお読み頂ければ幸いです。</p> <h1 id="この記事の想定読者"><a href="#%E3%81%93%E3%81%AE%E8%A8%98%E4%BA%8B%E3%81%AE%E6%83%B3%E5%AE%9A%E8%AA%AD%E8%80%85">この記事の想定読者</a></h1> <ul> <li>これからウェブサービスを個人で作りたい方や開発中の方</li> <li>ウェブサービスで実際に用いられている技術やツールを知りたい方</li> <li>開発ノウハウを知りたい方</li> <li>技術面以外の話にも興味がある方</li> </ul> <h1 id="開発経緯"><a href="#%E9%96%8B%E7%99%BA%E7%B5%8C%E7%B7%AF">開発経緯</a></h1> <p>「<a target="_blank" rel="nofollow noopener" href="http://nijisanji.ichikara.co.jp/">にじさんじ</a>」と呼ばれるバーチャルライバー (VTuber) グループが存在しています。</p> <p><a href="https://crieit.now.sh/upload_images/16b8ee5f67d0b16127720c30ee9b6fe65c04737c73b32.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/16b8ee5f67d0b16127720c30ee9b6fe65c04737c73b32.jpg?mw=700" alt="にじさんじ" /></a></p> <p>僕はこちらのグループのファンなのですが、公式がスケジュール情報の発信を行っておらず、スケジュールを把握しにくい問題がありました。<br /> スケジュール情報を発信する非公式サイトやアプリも存在していますが、閲覧がしにくく使い勝手が悪い状態でもありました。<br /> そこで、スマートフォンでも十分に閲覧でき、にじさんじライバーの配信スケジュールに特化したウェブサービスを作れば需要があるのでは考え、開発に着手しました。</p> <h1 id="主な機能"><a href="#%E4%B8%BB%E3%81%AA%E6%A9%9F%E8%83%BD">主な機能</a></h1> <p>元々はシンプルにスケジュールを確認出来るだけのシンプルなサイト開発を考えていましたが、<br /> 自分自身が必要十分に感じるレベル(このサービスユーザーのペルソナの1つは自分自身です!)に加え、サービスとして多くの方々に利用頂く事を前提に機能検討した結果、リリース時は以下の機能を実装しようという結論に至りました。</p> <h2 id="ユーザー向け機能"><a href="#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E5%90%91%E3%81%91%E6%A9%9F%E8%83%BD">ユーザー向け機能</a></h2> <ul> <li>バーチャルライバー (VTuber) グループ「にじさんじ」メンバーの生配信スケジュールの閲覧</li> <li>実際の生配信(ライブ)、アーカイブ情報の閲覧</li> <li>ライバー情報の閲覧</li> <li>ライバーのフォローを元にしたスケジュール等の情報閲覧(要会員登録)</li> <li>配信時間前のメール通知(要会員登録)</li> <li>Twitter へスケジュール情報まとめツイート</li> <li>端末を問わず利用可能(レスポンシブ)</li> <li>ネイティブアプリっぽいリッチなデザイン</li> </ul> <h2 id="運営者向け機能"><a href="#%E9%81%8B%E5%96%B6%E8%80%85%E5%90%91%E3%81%91%E6%A9%9F%E8%83%BD">運営者向け機能</a></h2> <ul> <li>スケジュール、ライブ、アーカイブ情報の自動取得(API、スクレイピング)</li> <li>情報登録時のメール通知</li> <li>管理画面</li> </ul> <h2 id="機能についての詳細"><a href="#%E6%A9%9F%E8%83%BD%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%81%AE%E8%A9%B3%E7%B4%B0">機能についての詳細</a></h2> <h3 id="ユーザー向け"><a href="#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E5%90%91%E3%81%91">ユーザー向け</a></h3> <p>にじさんじは59名(現在は58名)と多くのライバーを擁します。<br /> ライバー全体の情報を網羅しようとした場合の情報量は馬鹿に出来ません。<br /> ユーザーごとに追っているライバーは異なるため、にじさんじ全体の情報をすべてのユーザーに一律に見せる事はユーザーの負担に繋がります。<br /> また、にじさんじには「1期生・2期生(無印)」「ゲーマーズ」「SEEDs」という3つのグループが存在していますが、それぞれを追っているファン層は異なります。<br /> さらに、グループ問わず人気ライバーを追っている方や、特定のライバーに搾って追っている方など、ユーザーの興味は多種多様です。</p> <p>そこで、以下のフィルタリング機能を備えることにしました。</p> <ul> <li>にじさんじ内のグループごと</li> <li>ユーザーによるライバーのフォロー</li> </ul> <p>フォロー機能を用意する場合、会員機能の実装は欠かせません。</p> <p>また、当サービスを多くの方に継続的に使っていただくことを考えた場合、アプリっぽいデザインで使いやすい UI を提供する事は欠かせないだろうと考え、フロンロエンドを Ajax で提供することに決めました。</p> <h3 id="運営者向け"><a href="#%E9%81%8B%E5%96%B6%E8%80%85%E5%90%91%E3%81%91">運営者向け</a></h3> <p>過去に情報の手動更新で苦労した経験があった為、情報の自動取得は欠かせませんでした。<br /> また、テストデータを作成したり、自動化を行った場合であっても、情報の編集は適宜必要となる事から、GUI の管理画面の存在も必要でした。</p> <h1 id="使用技術・開発ツール"><a href="#%E4%BD%BF%E7%94%A8%E6%8A%80%E8%A1%93%E3%83%BB%E9%96%8B%E7%99%BA%E3%83%84%E3%83%BC%E3%83%AB">使用技術・開発ツール</a></h1> <h2 id="今回用いた技術・開発ツール"><a href="#%E4%BB%8A%E5%9B%9E%E7%94%A8%E3%81%84%E3%81%9F%E6%8A%80%E8%A1%93%E3%83%BB%E9%96%8B%E7%99%BA%E3%83%84%E3%83%BC%E3%83%AB">今回用いた技術・開発ツール</a></h2> <h3 id="WordPress"><a href="#WordPress">WordPress</a></h3> <p>開発フレームワークとして WordPress を用いた理由ですが、</p> <ul> <li>見知った技術であること</li> <li>データの CRUD 、ページ作成、ユーザー認証など、会員機能付きウェブサービス作成に必要十分な機能が揃っていること</li> <li>管理画面が標準で用意されていること</li> <li>「プラグイン」を用いて楽が出来ること</li> <li>枯れた技術であること</li> </ul> <p>上のようなものが挙げられます。</p> <p>特に「管理画面が標準で用意されていること」は重要で、管理画面が必要な状況において、これがあるのと無いのとでは開発工数に雲泥の差が生じます。</p> <p>データモデルの構造上、複数のデータ項目への検索実装が難しい点が弱点ではありますが、検索を主体としたサービスでは無いため、あまり問題にならないと判断しました。</p> <h3 id="Advanced Custom Fields Pro"><a href="#Advanced+Custom+Fields+Pro">Advanced Custom Fields Pro</a></h3> <p>WordPress にてカスタムフィールドを扱う際 <a target="_blank" rel="nofollow noopener" href="https://www.advancedcustomfields.com/pro/">Advanced Custom Fields</a> が欠かせません。<br /> 繰り返しフィールド(配列)を簡単に用いることが可能な有料の <a target="_blank" rel="nofollow noopener" href="https://www.advancedcustomfields.com/pro/">Pro</a> 版を使用しています。</p> <p>GUI でデータ構造や管理画面を作成する事ができ、大変重宝しています。<br /> コードを書かずに済む作業は、書かずに越したことがないです。</p> <h3 id="WP-REST API"><a href="#WP-REST+API">WP-REST API</a></h3> <p>Ajax でのレンダリングを行う場合、情報元となる API が欠かせません。<br /> 以前は <a target="_blank" rel="nofollow noopener" href="https://wpdocs.osdn.jp/%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%A7_AJAX_%E3%82%92%E4%BD%BF%E3%81%86">admin-ajax.php</a> を利用して API を1から作る必要がありましたが、<br /> 今では WordPress コアに標準で API の機能が備わっています。<a target="_blank" rel="nofollow noopener" href="https://ja.wp-api.org/">WP-REST API</a> を使わない手はありません。</p> <h3 id="jQuery"><a href="#jQuery">jQuery</a></h3> <p>こちらも WordPress コアに標準で含まれています。<br /> ユーザー画面においてもツールバーの描画に必要で、WordPress を用いる場合欠かせません。<br /> また、後述する Semantic-UI のスクリプトも jQuery で出来ており、jQuery に依存せざる得ない状態です。</p> <p>とはいえ、単一 DOM の表示切り替えといったシンプルな仕事は jQuery 向きであると言えると思います。<br /> また、Ajax 用の仕組みも備わっており、上のような前提が存在する状況においては、別途 axios といったライブラリを用意しなくとも済む点は引き続き評価出来ます。</p> <h3 id="Vue.js"><a href="#Vue.js">Vue.js</a></h3> <p>Ajax にて取得したデータを用いて画面を構成する場合、開発効率やコードの視認性、いずれを考慮してもビューとコントローラーの仕組みは欠かせないだろうと思います。</p> <p>Angular, React, Vue.js あたりが採用候補にあたると思いますが、jQuery との併用可能な(最新バージョンを持つ)フレームワークは後者2つのみです。<br /> 元々 <a target="_blank" rel="nofollow noopener" href="https://riot.js.org/ja/">Riot.js</a> を使っていた身として、またテンプレートエンジンライクな PHP 使いとして、 Vue.js の記法はとても親近感があり書きやすいものでした。<br /> また、Vue CLI, Nuxt.js といった関連技術も充実しており、廃れる心配が少ない技術だろうという点も技術選定の後押しポイントになりました。</p> <h3 id="Semantic-UI"><a href="#Semantic-UI">Semantic-UI</a></h3> <p>UI コンポーネントは Bootstrap が有名で、僕も用いたことがありますが、<br /> あまりにも多くのサイトで用いられている事から見慣れてしまい、飽きを感じ始めていました。<br /> そういった状況で <a target="_blank" rel="nofollow noopener" href="https://semantic-ui.com/">Semantic-UI</a> を見つけた時は感動したのを覚えています。</p> <p>選定理由としてデザインの好みの影響は多分にありますが、UI パターンが Bootstrap 並に備わっており、技術者として実用に耐えうる UI コンポーネントであると感じています。</p> <h3 id="Twitter API"><a href="#Twitter+API">Twitter API</a></h3> <p>会員登録・認証に用いました。</p> <p>利用に審査が必要となり導入敷居が上がりましたが、<br /> Google 翻訳の手助けを得つつ簡単な英文で申請を行ったところ、サクッと審査がおりました。</p> <p>また、<a target="_blank" rel="nofollow noopener" href="https://ja.wordpress.org/plugins/gianism/">Gianism</a> と呼ばれる WordPress プラグインがあった為、認証に係る新規コードはほとんど書かずに利用することが出来ました。</p> <h3 id="YouTube API"><a href="#YouTube+API">YouTube API</a></h3> <p>YouTube のライブ、動画データを取得する為には欠かせませんでした。</p> <p>動画 API は REST 形式でも提供されており、利用の敷居はとても低くなっています。</p> <h3 id="PHPMailer"><a href="#PHPMailer">PHPMailer</a></h3> <p>メール通知の際にメール配信の仕組みが必要でした。</p> <p>今回、サーバーはさくらインターネットさんのものを用いましたが、多くのスパム業者の利用実績の影響からか各プロパイダからの締め付けが強く、標準ポートでのメール配信は厳しいものがありました。</p> <p><a target="_blank" rel="nofollow noopener" href="https://github.com/PHPMailer/PHPMailer">PHPMailer</a> を用いると、Gmail といった各プロパイダからの受信規制の少ないサーバーを利用できるため、メール配信にあたり安心感があります。</p> <h3 id="さくらインターネットVPS + KUSANAGI"><a href="#%E3%81%95%E3%81%8F%E3%82%89%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%8D%E3%83%83%E3%83%88VPS+%2B+KUSANAGI">さくらインターネットVPS + KUSANAGI</a></h3> <p>サーバーはさくらインターネットVPS(標準2GB) + <a target="_blank" rel="nofollow noopener" href="https://kusanagi.tokyo/">KUSANAGI</a> という形を取りました。</p> <p>さくらインターネットVPS は国内サービスのため、契約周りでの安心感がありますし、<a target="_blank" rel="nofollow noopener" href="http://ascii.jp/elem/000/001/738/1738515/">国内サービスの中での信頼性は随一</a>です。<br /> また、ビジネス目的でのサービスでないため運用コストは抑える必要がありますが、従量課金で無く、不意な請求が絶対に起こりえない点もポイントでした。</p> <p>KUSANAGI については WordPress サイトを運営する為に必要な nginx, PHP の設定がデフォルトで最適化されており、SSL 化に欠かせない Let's Encrypt も自動で走るなど、WordPress サイトを運営するために至り尽くせりな機能が OS レベルで備わっています。</p> <p>heroku や Cloud9 といった PaaS に頼る手も検討しましたが、環境セットアップの安易さはそれらのサービスに劣らないことや、さくらインターネットの場合は VPS であってもスケールアップ可能といった特徴を持つことから、最初のウェブサービスはこの構成から始めることにしました。</p> <h3 id="VCCW"><a href="#VCCW">VCCW</a></h3> <p>開発環境は <a target="_blank" rel="nofollow noopener" href="http://vccw.cc/">VCCW</a> を用いました。<br /> VCCW とは Vagrant がベースの WordPress 開発に最適化されたツールです。<br /> macOS での導入は一瞬でした。</p> <p>PaaS ではなく VPS を用いた理由としては VCCW の存在も大きく、同梱された <a target="_blank" rel="nofollow noopener" href="https://github.com/welaika/wordmove">Wordmove</a> で DB 含めたデプロイ(同期)が一瞬で完了するなど、VCCW を用いた際の総合的な体験がとてもスマートで感動しました。</p> <p>実は、これまで Filezilla (FTP) を主なデプロイ手段としていましたが、どうして早く試さなかったのかと反省しています。</p> <h3 id="Visual Studio Code"><a href="#Visual+Studio+Code">Visual Studio Code</a></h3> <p>コードはもっぱら <a target="_blank" rel="nofollow noopener" href="https://code.visualstudio.com/">Visual Studio Code</a> で書いています。<br /> これまで Sublime Text を用いていましたが、稀に落ちたり OS ごとの挙動差分が気になっていました。<br /> Visual Studio Code は開発環境をベースとしており拡張性も高く安心感がありますし、動作が軽快なためストレスフリーにコードが書ける点がとても評価出来ます。</p> <h3 id="Google Chrome"><a href="#Google+Chrome">Google Chrome</a></h3> <p>開発関係のプラグインが豊富である事、検証ツールにてスマートフォンやタブレットの画面エミュレートが安易である点が良いです。</p> <p>もちろん、最終的な動作確認の際は各種ブラウザ(Safari, Firefox, Edge, Opera, それぞれ最新)・OS(macOS, Windows, iOS, Android, それぞれ最新)でのテストも行っています。</p> <h3 id="Git"><a href="#Git">Git</a></h3> <p>純粋にファイルのバージョン管理目的で用いました。</p> <p>ちなみにホスト先は <a target="_blank" rel="nofollow noopener" href="https://bitbucket.org/">Bitbucket</a>、クライアントには <a target="_blank" rel="nofollow noopener" href="https://ja.atlassian.com/software/sourcetree">SourceTree</a> を用いています。</p> <h3 id="Macbook Pro (13inch)"><a href="#Macbook+Pro+%2813inch%29">Macbook Pro (13inch)</a></h3> <p>ハードウェアの好みで用いています。</p> <p>スペックですがメモリ16GB、CPU Corei7 2.5GHz デュアルコア、SSD 512GBになります。</p> <p>VCCW にて仮想環境を走らせる都合上、ある程度のメモリが必要となります。<br /> 8GB では処理が重く感じられる為、7月に new MacBook から移行しました。</p> <h3 id="メモ (Apple)"><a href="#%E3%83%A1%E3%83%A2+%28Apple%29">メモ (Apple)</a></h3> <p>ToDo リスト機能が便利でした。</p> <p><a href="https://crieit.now.sh/upload_images/34a233108cad55c08bf8ba640a9a976f5c0610e0b3e88.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/34a233108cad55c08bf8ba640a9a976f5c0610e0b3e88.png?mw=700" alt="ToDo 抜粋" /></a></p> <h2 id="今回用いなかった技術・開発ツール"><a href="#%E4%BB%8A%E5%9B%9E%E7%94%A8%E3%81%84%E3%81%AA%E3%81%8B%E3%81%A3%E3%81%9F%E6%8A%80%E8%A1%93%E3%83%BB%E9%96%8B%E7%99%BA%E3%83%84%E3%83%BC%E3%83%AB">今回用いなかった技術・開発ツール</a></h2> <h3 id="Gutenberg"><a href="#Gutenberg">Gutenberg</a></h3> <p>WordPress のエディタにブロックの概念が導入され、レイアウトレベルで見たまま編集が行えるようになりました。その機能名の事を <a target="_blank" rel="nofollow noopener" href="https://ja.wordpress.org/gutenberg/">Gutenberg</a> と呼びます。<br /> WordPress 界隈においては有名な新技術ですが、Gutenberg を無効化する <a target="_blank" rel="nofollow noopener" href="https://ja.wordpress.org/plugins/classic-editor/">Classic Editor</a> を入れ導入を見送りました。<br /> 以下のような理由からです。</p> <ul> <li>今のところ新しい技術であり今後仕様が頻繁に変わるリスクがある</li> <li>画面の表示要素を再利用したり、レイアウトを頻繁に変更したり、デザインを他人に任せたり、ユーザーに編集させたりといった、Gutenberg のメリットを享受可能な状況に置かれていない</li> </ul> <h3 id="Firebase"><a href="#Firebase">Firebase</a></h3> <p>フロントエンド中心の開発の勉強も兼ねて用いることを考えましたが、自動化にあたってスクレイピングが必要で、サーバーサイド中心の開発にせざる得ませんでした。</p> <h3 id="Laravel, CakePHP 等の開発フレームワーク"><a href="#Laravel%2C+CakePHP+%E7%AD%89%E3%81%AE%E9%96%8B%E7%99%BA%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF">Laravel, CakePHP 等の開発フレームワーク</a></h3> <p>複雑なデータモデルが必要であったり、検索が重要となるサービスを開発する場合は WordPress では限界があったと思いますが、そうではありませんでした。</p> <h3 id="Drupal, concrete5, baserCMS, Movable Type 等の CMS"><a href="#Drupal%2C+concrete5%2C+baserCMS%2C+Movable+Type+%E7%AD%89%E3%81%AE+CMS">Drupal, concrete5, baserCMS, Movable Type 等の CMS</a></h3> <p>前者2つについては、掲示板など会員管理周りの機能が充実している事やエディタのリッチさが売りかと思われますが、その点において今回メリットには感じませんでした。</p> <p><a target="_blank" rel="nofollow noopener" href="https://basercms.net/about/index.html">baserCMS</a> については、CakePHP がベースに採用されており、かつ管理画面も備わっている事から、開発者目線ではとても魅力的です。<br /> 今回は採用していないですが、データモデルが複雑で、管理画面もサクッと用意したいという状況においては、選ばざる得ない選択肢だと思われます。</p> <p>Movable Type は WordPress 以上に一般サイト制作に特化しており、会員管理等の標準機能が弱い印象があります。</p> <h3 id="CDN"><a href="#CDN">CDN</a></h3> <p>入れれば速くて良いのですが、コストが気になります。趣味のサービスには向かないでしょう。<br /> 今回は KUSANAGI (nginx + サーバーキャッシュ) に頑張ってもらっています。</p> <h3 id="gulp, babel, webpack 等のフロントツール"><a href="#gulp%2C+babel%2C+webpack+%E7%AD%89%E3%81%AE%E3%83%95%E3%83%AD%E3%83%B3%E3%83%88%E3%83%84%E3%83%BC%E3%83%AB">gulp, babel, webpack 等のフロントツール</a></h3> <p>実はまともに用いたことがありません。(勉強せねば…)<br /> ただ、これらのツールが活用できずともウェブサービスを開発し運用を開始出来る状態になる事が分かります。</p> <ul> <li><a href="https://crieit.net/posts/Webpack">初心者はWebpackの事は一度忘れた方が良い - Crieit</a></li> </ul> <h3 id="AMP"><a href="#AMP">AMP</a></h3> <p>文章や写真ベースの記事がほとんど無く、JavaScript に頼るページも多く導入は見送りました。</p> <p>ただ、Vue.js でのレンダリング結果を Googlebot が拾ってくれない都合で、Vue.js のレンダリングが完了するまでは SSR の結果を表示する仕組みを入れた事で、JavaScript に頼るページがほとんど無くなりました。</p> <p>AMP を導入した場合 SEO 効果も期待できるため、後々導入する可能性があります。</p> <h3 id="PWA"><a href="#PWA">PWA</a></h3> <p>アプリっぽい見た目にした事や Ajax での情報取得は PWA 化を見越しての方法でもありました。<br /> 一旦 apple-touch-icon の設定でお茶を濁しましたが、AMP 同様後々導入する可能性があります。</p> <h3 id="Docker"><a href="#Docker">Docker</a></h3> <p>VCCW のお陰で、動作環境としては Linux ベースで開発が出来ており、本番サーバーに環境も近いはずで、環境を揃える意味ではほとんど不要だろうと考えていたのですが、本番リリース直前に本番でのみ発生する不具合に見合わされました。<br /> 始めから Docker ベースでの開発であればそのような悩みも発生しなかっただろうと思います。<br /> 今後の新規開発の際に導入を検討する可能性がありそうですが、費用を中心に何かとコストが増えやすい為、趣味のサービス開発での導入は難しそうです。</p> <h1 id="開発やリリースで苦労したこと"><a href="#%E9%96%8B%E7%99%BA%E3%82%84%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9%E3%81%A7%E8%8B%A6%E5%8A%B4%E3%81%97%E3%81%9F%E3%81%93%E3%81%A8">開発やリリースで苦労したこと</a></h1> <p>上で記載した以外の点について触れたいと思います。</p> <h2 id="類似サービスの登場"><a href="#%E9%A1%9E%E4%BC%BC%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%81%AE%E7%99%BB%E5%A0%B4">類似サービスの登場</a></h2> <p>開発開始からわずか数日ほど経ったタイミングで、VTuber のスケジュールを扱うサービスが登場しました。</p> <p>一見デザインも綺麗で、にじさんじ以外も含め、様々な VTuber のスケジュールが登録されています。</p> <p>ただ、スケジュールが不十分な部分があったり、にじさんじ好きにとってはノイズとなる情報も多いなど、欠点や方向性の違いによる差がある事も分かってきました。</p> <p>当初の目的を常に意識しながら、なんとかリリースする事が出来ました。</p> <h2 id="Twitter アカウント凍結"><a href="#Twitter+%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E5%87%8D%E7%B5%90">Twitter アカウント凍結</a></h2> <p>現在 <a target="_blank" rel="nofollow noopener" href="https://twitter.com/nijisanji_net">@nijisanji_net</a> というアカウントを用いていますが、元々はドメイン取得時に別のアカウント名で作成し放置していたところ、何故か凍結の事態に…</p> <p>このような事は初めてでしたが、凍結直後に気づくことが出来ず、凍結解除申請も虚しく現在も凍結されたままになっています。</p> <p>惜しかったですが、思い切って別アカウントを作成し事なきを得ました。</p> <h2 id="スクレイピング"><a href="#%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0">スクレイピング</a></h2> <p>スクレイピング対象に想定外のパターンの文字列が混ざった場合、データに不具合が発生します。<br /> 中にはスクレイピング先情報の typo など、どうしようもないものもありますが、<br /> 大きなデータ崩れが発生しないように抑えるべく、多くの分岐処理が必要となりました。<br /> スクレイピングは本サービスのコア機能になりますが、最も実装に時間のかかった部分でもありました。</p> <h2 id="Google Search Console"><a href="#Google+Search+Console">Google Search Console</a></h2> <p>リリース直前に noindex,follow 指定で本番環境でのテストを行っていた影響で、この記事を書いている現在もエラーを吐く状態となっています。<br /> 当初は別に問題があるのではといろいろ試したのですが、不慣れのため、単純な時間の問題だろうと気づくまでにとても時間がかかりました。</p> <h2 id="Googlebot 上で Vue.js が機能しない"><a href="#Googlebot+%E4%B8%8A%E3%81%A7+Vue.js+%E3%81%8C%E6%A9%9F%E8%83%BD%E3%81%97%E3%81%AA%E3%81%84">Googlebot 上で Vue.js が機能しない</a></h2> <p>Search Console 上の問題もあり、時間が経つまでの検索インデックスは DOM に頼るしかない状態となっていましたが、<br /> その問題に追い打ちをかけるように Googlebot 上で Vue.js が機能しない問題にぶち当たりました。</p> <p><a href="https://crieit.now.sh/upload_images/9d6f358801008d7098a080eada7db9425c0629610762a.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/9d6f358801008d7098a080eada7db9425c0629610762a.png?mw=700" alt="googlebot vue.js" /></a></p> <p>Googlebot で JavaScript を解釈できる事は知っていましたが、Vue.js など一部のスクリプトが正しく認識されない問題についての知識が無く、これには参りました。</p> <p>結局 Vue.js で出力される内容をサーバーサイドレンダリング (SSR) させ、 Vue.js が読み込まれるまでの間の表示をサーバー側に任せる事でなんとか事なきを得ました。</p> <p><a href="https://crieit.now.sh/upload_images/277173c532a3325c1b39552c64edb6705c062acf87c0d.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/277173c532a3325c1b39552c64edb6705c062acf87c0d.png?mw=700" alt="Googlebot SSR" /></a></p> <h1 id="開発期間・工数"><a href="#%E9%96%8B%E7%99%BA%E6%9C%9F%E9%96%93%E3%83%BB%E5%B7%A5%E6%95%B0">開発期間・工数</a></h1> <p>9月9日に開発を開始し、11月25日に公開しました。<br /> 開発期間は約3ヶ月、累計作業工数は142時間でした。</p> <h2 id="工数について"><a href="#%E5%B7%A5%E6%95%B0%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6">工数について</a></h2> <p>当初はせいぜい数十時間で終わるだろうと見込んで開発を開始しましたが、実際はサービス開発を行いながら仕様を詰めており、当初の想定よりも機能が増えたことから、予定よりも工数が嵩んでしまいました。</p> <p>また、作成していたプログラムの不具合の影響で、手動で作成していたライバーデータを全て別データで上書きしてしまったのですが、そのライバーデータの作成に10時間近くかかっており、再度同様の工数が発生しました。</p> <p>さらに、リリース直前に発生した本番環境限定の不具合もあり対処に10時間ほど時間が取られてしまいました。</p> <p>実際にかかった時間と比較し20時間〜30時間ほどは短く出来たのではと思います。次に活かしたいです。</p> <p>余談ですが、改めて2つ歳下のせせりさんのすごさを実感しました。</p> <ul> <li><a target="_blank" rel="nofollow noopener" href="http://www.itmedia.co.jp/news/articles/1712/11/news089.html">「1人で6時間で作った」 Twitterで匿名質問「Peing」人気、月間2億PV超えへ - ITmedia NEWS</a></li> </ul> <h1 id="開発以外で取り組んだこと"><a href="#%E9%96%8B%E7%99%BA%E4%BB%A5%E5%A4%96%E3%81%A7%E5%8F%96%E3%82%8A%E7%B5%84%E3%82%93%E3%81%A0%E3%81%93%E3%81%A8">開発以外で取り組んだこと</a></h1> <h2 id="他の趣味活動の制限"><a href="#%E4%BB%96%E3%81%AE%E8%B6%A3%E5%91%B3%E6%B4%BB%E5%8B%95%E3%81%AE%E5%88%B6%E9%99%90">他の趣味活動の制限</a></h2> <p><a target="_blank" rel="nofollow noopener" href="https://anitech.fm/">ポッドキャスト</a>や<a target="_blank" rel="nofollow noopener" href="http://solaio.hateblo.jp/">ブログ</a>でのアウトプット、仲間との Discord など、日常的に様々な趣味活動を行っていましたが、業務、他のプライベートでの活動も含め忙しく、削れる活動は制限する事に。</p> <p>もちろん、万人が意識する事でも無いと思いますが、忙しい社会人が開発を継続していく為には、多少他の活動を制限する覚悟が必要だと感じています。</p> <h2 id="息抜きは欠かさない"><a href="#%E6%81%AF%E6%8A%9C%E3%81%8D%E3%81%AF%E6%AC%A0%E3%81%8B%E3%81%95%E3%81%AA%E3%81%84">息抜きは欠かさない</a></h2> <p>とは言いつつも、仕事も開発、プライベートも開発で休み無しという状況では、つらい日々が続きます。</p> <p>趣味のアニメ視聴時間は一切削らず、本サービスで扱っている VTuber 動画の視聴時間もある程度確保した事は、<br /> モチベーションの維持に大きく貢献しただろうと思います。</p> <h2 id="開発者コミュニティへの加入"><a href="#%E9%96%8B%E7%99%BA%E8%80%85%E3%82%B3%E3%83%9F%E3%83%A5%E3%83%8B%E3%83%86%E3%82%A3%E3%81%B8%E3%81%AE%E5%8A%A0%E5%85%A5">開発者コミュニティへの加入</a></h2> <p><a target="_blank" rel="nofollow noopener" href="https://scrapbox.io/admin-guild-pr/%E9%81%8B%E5%96%B6%E8%80%85%E3%82%AE%E3%83%AB%E3%83%89">運営者ギルド</a>のメンバーとなりましたが、他のみなさんの発言は「自分も頑張らないと」という刺激になりました。</p> <h1 id="リリースしてからの気付きや変化"><a href="#%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9%E3%81%97%E3%81%A6%E3%81%8B%E3%82%89%E3%81%AE%E6%B0%97%E4%BB%98%E3%81%8D%E3%82%84%E5%A4%89%E5%8C%96">リリースしてからの気付きや変化</a></h1> <h2 id="アクセス数が気になって落ち着かない"><a href="#%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E6%95%B0%E3%81%8C%E6%B0%97%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%A6%E8%90%BD%E3%81%A1%E7%9D%80%E3%81%8B%E3%81%AA%E3%81%84">アクセス数が気になって落ち着かない</a></h2> <p>公開から数日たった現在は多少慣れましたが、公開1日目は気づいたら Analytics の画面を見ている状態で本当に落ち着きませんでした。</p> <h2 id="運用に時間が取られる"><a href="#%E9%81%8B%E7%94%A8%E3%81%AB%E6%99%82%E9%96%93%E3%81%8C%E5%8F%96%E3%82%89%E3%82%8C%E3%82%8B">運用に時間が取られる</a></h2> <p>理論上は自動化出来ているため、運用に時間が取られることも少ないだろうと考えていましたが、実際は更新ツールの不具合を修正したり、データを一部手直ししたり、アクセス数を増やすための SEO や PR を行ったりと、100%の自動化は中々難しく今後の課題であると感じています。</p> <h1 id="WordPress + Vue.js を用いてどうだったか"><a href="#WordPress+%2B+Vue.js+%E3%82%92%E7%94%A8%E3%81%84%E3%81%A6%E3%81%A9%E3%81%86%E3%81%A0%E3%81%A3%E3%81%9F%E3%81%8B">WordPress + Vue.js を用いてどうだったか</a></h1> <h2 id="WordPress"><a href="#WordPress">WordPress</a></h2> <p>サービス開発においても使用感は悪くなかったです。</p> <p>そもそもとして、開発フレームワークではない WordPress を開発に用いる事に対する心配をお持ちの方は多いと思われますが、上に記載した通り</p> <blockquote> <p>データモデルの構造上、複数のデータ項目への検索実装が難しい点が弱点</p> </blockquote> <p>問題はこの程度だと考えています。</p> <p>大規模な開発になった際に、規約が少なくコードの品質が担当者間で不揃いになりやすかったり、<br /> データモデルの都合上パフォーマンスの問題も出てきますが、<br /> 個人開発レベルにおいてはほとんど心配する事ではないだろうと思いますし、<br /> 現実的な対策は十分可能ですので今後業務の開発でも用いると思います。</p> <h2 id="Vue.js"><a href="#Vue.js">Vue.js</a></h2> <p>リリース後に SEO 面の問題が発生した為、フロントエンド技術に頼った開発は難しそうだと実感させられました。<br /> ただ、今回のようなサーバーサイド技術との併用であれば小回りも効くため、十分実用的ではと思います。</p> <h2 id="WordPress と Vue.js の併用"><a href="#WordPress+%E3%81%A8+Vue.js+%E3%81%AE%E4%BD%B5%E7%94%A8">WordPress と Vue.js の併用</a></h2> <p>下記2点があり、併用には全く支障がありませんでした。</p> <ul> <li>WordPress 標準で API が提供されている</li> <li>WordPress コアに含まれている jQuery と Vue.js が併用可能</li> </ul> <h2 id="その他"><a href="#%E3%81%9D%E3%81%AE%E4%BB%96">その他</a></h2> <p>Semantic-UI と Vue.js のかみ合わせがあまりよろしくなく、<br /> Semantic-UI 内の JS ライブラリで作成したフォームの value が Vue.js 側で上手く取得できませんでした。<br /> Semantic-UI に value を直接返す関数が提供されておりどうにかなりましたが、<br /> サードパーティ製ではあるものの <a target="_blank" rel="nofollow noopener" href="https://semantic-ui-vue.github.io/">Semantic UI Vue</a> と呼ばれる UI コンポーネントも存在している事から、今後はそちらを使っていく可能性があります。</p> <h1 id="これから取り組みたいこと"><a href="#%E3%81%93%E3%82%8C%E3%81%8B%E3%82%89%E5%8F%96%E3%82%8A%E7%B5%84%E3%81%BF%E3%81%9F%E3%81%84%E3%81%93%E3%81%A8">これから取り組みたいこと</a></h1> <h2 id="サービスの継続運用、機能拡張"><a href="#%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%81%AE%E7%B6%99%E7%B6%9A%E9%81%8B%E7%94%A8%E3%80%81%E6%A9%9F%E8%83%BD%E6%8B%A1%E5%BC%B5">サービスの継続運用、機能拡張</a></h2> <p>一部不具合も残っているため、それの改善も含めた継続的なサービス運用を目指したいです。<br /> また、ある程度機能を絞ってリリースしており、残りの機能もしっかり開発できればと考えています。</p> <h2 id="数字、結果"><a href="#%E6%95%B0%E5%AD%97%E3%80%81%E7%B5%90%E6%9E%9C">数字、結果</a></h2> <p>現状、Twitter のフォロワーは 50 に満たず、まだ SEO の効果も出ていないことからアクセス数はご察しのとおりです。<br /> 趣味のサービスのため、数字や結果が最優先ではありませんが、折角ですのでにじさんじファンの半数程度(数万人)に利用して頂けるサービスを目指せればと考えています。</p> <h2 id="別サービスの新規開発"><a href="#%E5%88%A5%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%81%AE%E6%96%B0%E8%A6%8F%E9%96%8B%E7%99%BA">別サービスの新規開発</a></h2> <p>上で記載の通り、継続運用の為の対策を打ったり、機能拡張も計画しており、新規着手までは中々骨が折れそうですが、平行開発も踏まえ新しいサービス開発にも取り組めればと考えています。</p> <h1 id="ありそうな質問"><a href="#%E3%81%82%E3%82%8A%E3%81%9D%E3%81%86%E3%81%AA%E8%B3%AA%E5%95%8F">ありそうな質問</a></h1> <h2 id="仕様書や設計書はきちんと書いたの?"><a href="#%E4%BB%95%E6%A7%98%E6%9B%B8%E3%82%84%E8%A8%AD%E8%A8%88%E6%9B%B8%E3%81%AF%E3%81%8D%E3%81%A1%E3%82%93%E3%81%A8%E6%9B%B8%E3%81%84%E3%81%9F%E3%81%AE%EF%BC%9F">仕様書や設計書はきちんと書いたの?</a></h2> <p>ぶっちゃけるとほとんど書いていません。要件を前述のメモ (Apple) に数行書いた程度です。</p> <ul> <li>上記の機能一覧</li> <li>コード上の役割分担 <ul> <li>投稿タイプ、API、情報フィルタリング、テンプレートなどデータ定義・表示制御は「nijisanji」と呼ばれるテーマが担う</li> <li>YouTube API へのアクセス、スクレイピングなどデータ更新は「nijisanji-cron」と呼ばれるプラグインが担う</li> </ul></li> </ul> <p>代わりにコードへのコメントはしっかり入れています。<br /> また、可能な限り WordPress コア標準の仕組みを用いています。<br /> さらに作業中に発生した不要なコードやデータは逐次削除するなど、<br /> 仕様書が無くとも現状の確認で全体像が見えやすい工夫を行いました。</p> <p>趣味の個人開発だから出来ることだと思います。</p> <p>念の為補足ですが、余裕があれば情報は残すに越したことは無いと思います。</p> <h2 id="広告は入れないの?"><a href="#%E5%BA%83%E5%91%8A%E3%81%AF%E5%85%A5%E3%82%8C%E3%81%AA%E3%81%84%E3%81%AE%EF%BC%9F">広告は入れないの?</a></h2> <p>数年前に月間数十万PVのサイトを運営していた事もありますが、 Adsense も大した額にはなっていませんでした。<br /> 本サービスでも同等のアクセス数が稼げれば広告の導入を検討しますが、利便性も下げますので、導入は慎重に判断したいと思います。</p> <h2 id="事業化はしないの?"><a href="#%E4%BA%8B%E6%A5%AD%E5%8C%96%E3%81%AF%E3%81%97%E3%81%AA%E3%81%84%E3%81%AE%EF%BC%9F">事業化はしないの?</a></h2> <p>そもそも趣味のサービスですし、権利問題も絡みますので考えてないですが、公式関係者の方々にも使って頂けるサービスにはしたいと考えています。</p> <h1 id="おわりに"><a href="#%E3%81%8A%E3%82%8F%E3%82%8A%E3%81%AB">おわりに</a></h1> <p>自分のような素人の書いた記事が参考になるのだろうか、と思う節もあり、中々重い腰が上がらなかったのですが、</p> <blockquote class="twitter-tweet"><p lang="ja" dir="ltr">すごいですね~。個人開発はじめたい人とかだとどうやってるか知りたい人多いかもしれないので、もし気が向いて且つ12月もたまたま無茶苦茶暇だったらカレンダーも是非w<a target="_blank" rel="nofollow noopener" href="https://t.co/iGA3PpFL6U">https://t.co/iGA3PpFL6U</a></p>— だら@技術系投稿サービス運営中 (@dala00) <a target="_blank" rel="nofollow noopener" href="https://twitter.com/dala00/status/1067083123005902848?ref_src=twsrc%5Etfw">November 26, 2018</a></blockquote> <p>Crieit の<a href="https://crieit.net/users/dala00">だら</a>さんに直接お誘い頂き執筆するまでに至りました。<br /> 改めてお誘い頂きありがとうございました。</p> <p>何かしらの Advent Calendar への参加は初となりますが、夢でもあったので参加出来たことはとても光栄でした。</p> <p>また、これからウェブサービス開発を考えている方や、ウェブサービス開発中の方の一助になれば幸いです。</p> <p>ご質問、ご指摘、アドバイス大歓迎です。コメントや <a target="_blank" rel="nofollow noopener" href="https://twitter.com/">@sola_io</a> までリプライ、お気軽にお寄せ下さい。</p> <p>ここまで読んで頂いたすべてのみなさま、本当にありがとうございました。</p> <p><a href="https://crieit.net/advent-calendars/2018/technology">個人開発サービスに用いられている技術 Advent Calendar 2018</a>、明日は <a href="https://crieit.net/users/hrz31">Hiroz</a> さんの「Koretteのオモテとウラ」になります。<br /> そもそも「Korette」って何?というところも含め、とても気になりますね。</p> sola