tag:crieit.net,2005:https://crieit.net/tags/GoogleAppEngine/feed
「GoogleAppEngine」の記事 - Crieit
Crieitでタグ「GoogleAppEngine」に投稿された最近の記事
2020-12-25T17:23:36+09:00
https://crieit.net/tags/GoogleAppEngine/feed
tag:crieit.net,2005:PublicArticle/15667
2020-01-07T23:15:57+09:00
2020-12-25T17:23:36+09:00
https://crieit.net/posts/GCE-DB-GAE
GCEをDBサーバーにしてGAEでサービスを無料運用する(を構築したけど費用がかかった)
<p>GCPでリリースしたサービスが1年経ち無料クレジットの期限をむかえそうになりました。Cloud SQLを使ってデプロイしたためその後は有料になってしまうのですが、誰も使っていないサービスのためなんとか無料で運用できる方法は無いかと考えました。ちなみに下記のような構成です。</p>
<ul>
<li>Node.js</li>
<li>MySQL5.7</li>
</ul>
<p>しかしサービスの性質上ちょっとデータベースのデータも多めで、HerokuのMySQLだと無料プランでは無理なのかな…という気がしました。そうするとMySQLを使えて無料で運用できるサービスが他にはありません。</p>
<p>そこでふと、アプリケーション・サーバーはGoogle App Engine、データベースサーバーをGoogle Compute Engineで運用してみたらどうだろう、と思い立ちやってみました。</p>
<p><a href="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e14888763bb5.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e14888763bb5.png?mw=700" alt="" /></a></p>
<h2 id="後日談の追記"><a href="#%E5%BE%8C%E6%97%A5%E8%AB%87%E3%81%AE%E8%BF%BD%E8%A8%98">後日談の追記</a></h2>
<p>こういうのが出るみたいなので無料は無理なのかもしれません。Micro instance with burstable CPU running。</p>
<p><a href="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e440681eb425.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e440681eb425.png?mw=700" alt="" /></a></p>
<p>普通にサーバーとして使ってる時は出ないのでGAEかネットワークから必要以上に接続が来てしまうのかもしれませんね…。(もしくは最近新しく作ったGCEだと出るようになったとかだったり?)</p>
<p>追記)<br />
GCEにWeb+DB全部入れにしたら費用がかからなくなったのでやはりこの構成だと費用がかかるみたいです。</p>
<h2 id="GAEからGCEにローカル接続する"><a href="#GAE%E3%81%8B%E3%82%89GCE%E3%81%AB%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B">GAEからGCEにローカル接続する</a></h2>
<p>結局のところ、今回の話ではこれが一番重要です。そもそもApp EngineからCompute Engineにローカル接続できるのか、と。</p>
<p>これは実はこの記事を書いている2020/1時点では日本語マニュアルではまだβ版という表記が残っている、リリースされたばかりの「サーバーレスVPCアクセス」という機能を使うことによって可能です。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://cloud.google.com/appengine/docs/standard/nodejs/connecting-vpc">Connecting to a VPC network | App Engine standard environment for Node.js docs | Google Cloud</a></p>
<p>Compute EngineはVPCネットワーク内に位置しているのですが、App Engineはこれとは別のネットワークに存在しています。そのため、このサーバーレスVPCアクセスという機能を使うことで、下記にも書かれていますがApp Engineのスタンダード環境やCloud FunctionsからCompute EngineやCloud SQLに内部IPでアクセスできるようになります。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://cloud.google.com/vpc/docs/configure-serverless-vpc-access?hl=ja">Serverless VPC Access の構成 | VPC | Google Cloud</a></p>
<p>日本語だとデプロイ時にbetaをつけろと書かれていますが恐らく今は不要だと思います。</p>
<h3 id="サーバーレスVPCアクセスの設定"><a href="#%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%83%AC%E3%82%B9VPC%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%AE%E8%A8%AD%E5%AE%9A">サーバーレスVPCアクセスの設定</a></h3>
<p>サーバーレスVPCアクセスのページを開くとコネクタを作成というリンクがあるのでクリックします。</p>
<p><a href="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e148b1948283.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e148b1948283.png?mw=700" alt="" /></a></p>
<p>作成画面に必要な項目を入力して作成します。</p>
<p><a href="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e148b657d6f0.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e148b657d6f0.png?mw=700" alt="" /></a></p>
<p>注意が必要な点としてまだリリースされたばかりのためリージョンが少ないです。最初にApp Engineを登録してしまうと、同じリージョンがない…! みたいなことになるので気をつけましょう。us-central1であればGAEのus-centralと合います。</p>
<p>IP範囲は補足に書かれている感じで大丈夫です。要するに、既存のVPCネットワークのIPとかぶっていないIP範囲であれば大丈夫です。</p>
<h3 id="App Engineの設定"><a href="#App+Engine%E3%81%AE%E8%A8%AD%E5%AE%9A">App Engineの設定</a></h3>
<p>App Engineのリージョンは先程作成したコネクタのリージョンに合わせて作成しましょう。多分作ってしまった後は変更できないのではないかと思います……。ただ、ちょっとApp Engineを作り直せない関係で色々試すことができたわけではないので、リージョンが違ったらダメかどうかは詳しく検証できていません。</p>
<p>あとはapp.yamlに、このコネクタに接続するための設定を追記します。</p>
<pre><code class="yaml">vpc_access_connector:
name: "projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR_NAME"
</code></pre>
<p>REGIONとCONNECTOR_NAMEはコネクタのものです。これでデプロイすれば接続され、Compute Engineの内部IPと接続することができるようになります。</p>
<h3 id="Compute Engineの設定"><a href="#Compute+Engine%E3%81%AE%E8%A8%AD%E5%AE%9A">Compute Engineの設定</a></h3>
<p>デフォルトだとCompute Engineの内部IPはエフェメラルになっているため、時々勝手に変わってしまいます。</p>
<p><a href="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e148d61aba91.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/6e2af66c610d88bc766649f72032893a5e148d61aba91.png?mw=700" alt="" /></a></p>
<p>静的内部IPアドレスを予約して固定にしておきましょう。外部IPは不要です。固定外部IPを使っていた場合は、ただそれを外すだけだと使われない外部IPになってしまい、費用が発生してしまいますのでIPを解放しておきましょう。</p>
<p>あとはMySQLをインストールして設定しましょう。どこからもアクセスできないのでMySQLユーザーは <code>ユーザー名@'%'</code> とかでいいのではないかと思います(違ったら教えていただけると助かります)。</p>
<p>問題なければこれで接続できます(のはず……)</p>
<h2 id="諸々設定"><a href="#%E8%AB%B8%E3%80%85%E8%A8%AD%E5%AE%9A">諸々設定</a></h2>
<p>とはいえGAEは無料枠があるというだけでそれ以降は有料となってしまいます。こにさんのブログを参考にしてなるべくオーバーしないようにすると良いでしょう。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://koni.hateblo.jp/entry/2016/01/06/130613">Google App Engineを無料で運用する方法(2018年版) - koni blog</a></p>
<p>スタンダード環境にてAutoScalingのF1というプランです。スケールしないプランもありますがそちらは無料枠が少なく毎月有料になってしまいます。</p>
<p>どちらにしろすごくアクセスのあるサイトだと有料になってしまうと思いますので今回のようにもう誰も使っていないサービスを残しておくとか、作ったばかりのサービスで試す場合とかにこの構成だと良いのではないかと思います。</p>
<p>あとCloud SQLのように便利な機能はないので適宜バックアップを取っておきましょう。</p>
<p><a href="https://crieit.net/posts/Google-Cloud-Storage-DB">Google Cloud Storage無料DBバックアップ</a></p>
<p>また、DBサーバーはメモリが不足してしょっちゅう止まる可能性もありますので、swapの設定もしておいた方が良いでしょう。</p>
だら@Crieit開発者
tag:crieit.net,2005:PublicArticle/15477
2019-10-13T23:43:10+09:00
2019-10-13T23:43:10+09:00
https://crieit.net/posts/960b0aeb50068c42582d201c7dd14467
熨斗(のし)の王様を作ったときに気をつけたこと
<h1 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h1>
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://noshi-king.matsubarase.com">のし王</a>というWebサービスを作った。<br />
<a href="https://crieit.now.sh/upload_images/fffb317da90f57ce80e2986ead5be3bd5da337e03f206.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/fffb317da90f57ce80e2986ead5be3bd5da337e03f206.png?mw=700" alt="のし王サムネイル" /></a></li>
<li>のし作成サービスが既に存在する中で、下記に気をつけたというお話。
<ul>
<li>サービス作成のきっかけになった不満点・ニーズをもれなく仕様に落とし込む</li>
<li>仕様策定時は技術的な楽さに甘えず、ユーザー体験を優先する</li>
<li>上記を実現するため必要最低限の技術を選定する</li>
</ul></li>
</ul>
<h1 id="不満点の解消、ニーズを仕様に落とし込む"><a href="#%E4%B8%8D%E6%BA%80%E7%82%B9%E3%81%AE%E8%A7%A3%E6%B6%88%E3%80%81%E3%83%8B%E3%83%BC%E3%82%BA%E3%82%92%E4%BB%95%E6%A7%98%E3%81%AB%E8%90%BD%E3%81%A8%E3%81%97%E8%BE%BC%E3%82%80">不満点の解消、ニーズを仕様に落とし込む</a></h1>
<ul>
<li>ちょっとした贈り物に「のし」をつけたかった。</li>
<li>既存サービスは、以下の点で不満が残った。
<ul>
<li>「のし紙」のテンプレート(背景画像)だけが提供されており、Wordなどに貼り付けた後、自分で文字を描かないとダメだった</li>
<li>Web上で任意の文字まで入れられるサービスでは、最後になるまで仕上がり具合がが分からなかった</li>
<li>最終画像にサービス名のロゴが入ってしまい、贈り物には不向きだった</li>
<li>フォントがしょぼかった</li>
<li>水引き(背景画像)や表書き(御礼などの上部の文字)をどう選んでよいか分からなかった</li>
</ul></li>
<li>不満点の解消をもれなく仕様に落とし込んだ。
<ul>
<li>背景画像と任意の文字を組み合わせてPDFで出力できるようにする</li>
<li>最終出力結果には広告を入れない</li>
<li>有料でもカッコいいフォントを採用する</li>
<li>用途に応じて自動で「水引き」と「表書き」が選択できるようにする</li>
</ul></li>
<li>マッスルの神様 = マ神 → 熨斗の王様 = のし王</li>
</ul>
<h1 id="ユーザー体験を最優先する"><a href="#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E4%BD%93%E9%A8%93%E3%82%92%E6%9C%80%E5%84%AA%E5%85%88%E3%81%99%E3%82%8B">ユーザー体験を最優先する</a></h1>
<div class="table-responsive"><table>
<thead>
<tr>
<th align="left"></th>
<th align="left">技術的な楽さを優先</th>
<th align="left">ユーザー体験を優先</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">文字描画</td>
<td align="left">ユーザー自身がWordなどで描画</td>
<td align="left">Webサービス上で描画</td>
</tr>
<tr>
<td align="left">仕上がり確認</td>
<td align="left">プレビュー不可 or プレビューボタンクリックで表示</td>
<td align="left">リアルタイムプレビュー表示</td>
</tr>
<tr>
<td align="left">水引き、表書き</td>
<td align="left">ユーザーの選択したものを表示</td>
<td align="left">用途を選ぶと最適な水引き、表書きを自動で選択</td>
</tr>
<tr>
<td align="left">描画フォント</td>
<td align="left">無料の範囲で選択可能</td>
<td align="left">有料で質の良いフォントが選択可能</td>
</tr>
<tr>
<td align="left">ユーザーが泥酔状態</td>
<td align="left">酔いが冷めてから使う</td>
<td align="left">泥酔状態でも直感で使える</td>
</tr>
</tbody>
</table></div>
<h1 id="仕様の実現方法を考える"><a href="#%E4%BB%95%E6%A7%98%E3%81%AE%E5%AE%9F%E7%8F%BE%E6%96%B9%E6%B3%95%E3%82%92%E8%80%83%E3%81%88%E3%82%8B">仕様の実現方法を考える</a></h1>
<ul>
<li>使用した技術
<ul>
<li>Webサービス上で文字描画しPDF出力
<ul>
<li>水引きの種類や表書きなどの情報をブラウザ上で選択させる</li>
<li>サーバーでPDFを作成してダウンロードさせる(Golang/Google App Engine)</li>
</ul></li>
<li>リアルタイムプレビュー表示
<ul>
<li>サムネイル描画サーバー(Golang/Google App Engine)を準備</li>
<li>水引きの種類や表書きなどの情報が変更されたらAjax(jQuery)でサーバーからサムネイル画像を取得し、ブラウザ上に即時反映</li>
</ul></li>
<li>用途を選ぶと最適な水引き、表書きを自動で選択
<ul>
<li><a target="_blank" rel="nofollow noopener" href="https://wikiki.github.io/components/quickview/">Bulma-ExtensionsのQuickView</a>で用途一覧を表示</li>
<li>用途を入力させて絞り込み(jQuery)</li>
<li>用途クリックで「水引き」と「表書き」を最適なものに変更(jQuery)</li>
</ul></li>
</ul></li>
<li>選定理由
<ul>
<li>仕様実現に際して最低限/シンプルなものを選ぶ</li>
<li>最新の技術よりも枯れて安定した技術を選ぶ</li>
<li>なるべくメンテナンスが不要なものを選ぶ</li>
</ul></li>
</ul>
Matsubarase.com公式
tag:crieit.net,2005:PublicArticle/15451
2019-10-04T17:10:28+09:00
2019-10-04T17:13:27+09:00
https://crieit.net/posts/Nuxt-js-Firebase-GAE-2-PV
Nuxt.js+Firebase+GAEで作った個人サービスが半月で2万PV超えたので実績値を全て公開する
<blockquote>
<p>Qiitaへ<a target="_blank" rel="nofollow noopener" href="https://qiita.com/kinmi/items/ce39b52ff712098431c4">投稿した記事</a>のクロス投稿になります。</p>
</blockquote>
<h1 id="こんなサービス作りました"><a href="#%E3%81%93%E3%82%93%E3%81%AA%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E4%BD%9C%E3%82%8A%E3%81%BE%E3%81%97%E3%81%9F">こんなサービス作りました</a></h1>
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【<a target="_blank" rel="nofollow noopener" href="https://twitter.com/hashtag/%E6%8B%A1%E6%95%A3%E5%B8%8C%E6%9C%9B?src=hash&ref_src=twsrc%5Etfw">#拡散希望</a>】🙌🎉🎊サービス開始🎊🎉🙌ボケをツイートして「いいね❤️」「リツイート🔁」の数でランキング!Twitter連動型 大喜利サイト「ついぎり」サービス開始しました‼️<a target="_blank" rel="nofollow noopener" href="https://twitter.com/hashtag/%E3%81%A4%E3%81%84%E3%81%8E%E3%82%8A?src=hash&ref_src=twsrc%5Etfw">#ついぎり</a><a target="_blank" rel="nofollow noopener" href="https://t.co/bkXfzHyVSs">https://t.co/bkXfzHyVSs</a></p>— ついぎり@公式アカウント (@twigiri_app) <a target="_blank" rel="nofollow noopener" href="https://twitter.com/twigiri_app/status/1161589000223641600?ref_src=twsrc%5Etfw">August 14, 2019</a></blockquote>
<p>Twitterで大喜利するサービスです。<br />
8月中頃にローンチしたのですが、有難いことに半月で約2.5万PVいきました。</p>
<p>開発に至ったポエム記事はCrieitに投稿しています。<br />
<a href="https://crieit.net/posts/19b75796b5c032c728ebab48ae064af4">なぜ大喜利サービスを作ったのか</a></p>
<h1 id="この記事について"><a href="#%E3%81%93%E3%81%AE%E8%A8%98%E4%BA%8B%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6">この記事について</a></h1>
<p>やっぱり公開直後は怖かったです。</p>
<p>そう、<strong>クラウド破産</strong>。<br />
<a target="_blank" rel="nofollow noopener" href="https://gigazine.net/news/20180803-spent-much-money-in-firebase/">Firebaseの設定を間違えて72時間で300万円以上請求されてしまったウェブサービス</a><br />
<a target="_blank" rel="nofollow noopener" href="https://qiita.com/itkr/items/745d54c781badc148bb9">BigQueryで150万円溶かした人の顔</a></p>
<p>上記以外にもネット上にはインパクトのある高額請求の記事がたくさんあり、<br />
内容を確認すれば「なんだそんな事か」となるのですが、<br />
実績値というのはセキュリティやNDAの関係からか、なかなか出回ってません。</p>
<p><strong>個人開発ならそんなの関係ねぇ</strong></p>
<p>って事で全て公開します。<br />
使い方によって大きく変わる所かと思いますが、何かの参考(個人開発の後押し)になれば幸いです。</p>
<h1 id="環境構成"><a href="#%E7%92%B0%E5%A2%83%E6%A7%8B%E6%88%90">環境構成</a></h1>
<ul>
<li>Nuxt v2.8.1
<ul>
<li>SSRモード</li>
</ul></li>
<li>GAE
<ul>
<li>standard</li>
<li>runtime: nodejs10</li>
<li>instance_class: F1</li>
</ul></li>
<li>Firestore
<ul>
<li>改めて別記事書こうと思いますが一般的な構成だと思います</li>
</ul></li>
<li>Cloud Functions for Firebase
<ul>
<li>engine: node8</li>
<li>ユーザー登録/脱会/ツイート/いいねRT集計/バックアップ で使用</li>
</ul></li>
<li>Cloud Storage for Firebase
<ul>
<li>OGP画像の保存に使用</li>
</ul></li>
<li>Regionは全てasia-northeast1</li>
</ul>
<h1 id="使用量"><a href="#%E4%BD%BF%E7%94%A8%E9%87%8F">使用量</a></h1>
<h2 id="PV数"><a href="#PV%E6%95%B0">PV数</a></h2>
<p><img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F127547%2F24881933-651c-4c96-824c-39736e729605.png?ixlib=rb-1.2.2&auto=compress%2Cformat&gif-q=60&s=6fb0cd97a92b355d9c652e4ab302b671" alt="PV数" /><br />
トータルで約2.5万PV。<br />
デイリーだとローンチ直後の約5,500PVがMAXです。</p>
<h2 id="割り当て"><a href="#%E5%89%B2%E3%82%8A%E5%BD%93%E3%81%A6">割り当て</a></h2>
<p><img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F127547%2Fb76116ed-9fff-e787-4c78-bee5045b0550.png?ixlib=rb-1.2.2&auto=compress%2Cformat&gif-q=60&s=aa7c74d1f29cd701cbaaf4fd11b3492f" alt="割り当て" /><br />
アクセス数に比例した増加は見られませんでした。</p>
<p><code>GCP Storage egress between NA and APAC</code><br />
使用量: 3.59GB<br />
一番費用が発生してるこれ、よく分かってません・・・<br />
GAEのデプロイにかかる項目なのかな?と思ってます。</p>
<p><code>Cloud Firestore Entity Writes Japan</code><br />
<code>Cloud Firestore Read Ops Japan</code><br />
Write: 480,077<br />
Read: 606,253<br />
Firestoreは<a target="_blank" rel="nofollow noopener" href="https://firebase.google.com/docs/firestore/quotas?hl=ja#free-quota">1日単位で無料枠がリセットされる</a>のですが、リリース直後はちょっと無料枠から足出た程度ですね。<br />
21日辺りは障害等でデータいじってた・・・気がします。</p>
<h1 id="諸経費"><a href="#%E8%AB%B8%E7%B5%8C%E8%B2%BB">諸経費</a></h1>
<h2 id="サーバー代"><a href="#%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E4%BB%A3">サーバー代</a></h2>
<p><img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F127547%2F79b2afae-5344-fea9-34f5-2f1b7e7e7b7f.png?ixlib=rb-1.2.2&auto=compress%2Cformat&gif-q=60&s=5a86fdff390d11dcb2a1529bde970ce9" alt="サーバー代" /><br />
0円でした。<br />
使用量として57円かかってるのですが、<br />
GCPには1年間有効な$300のトライアルクレジットがあるので、そこに収まってます。<br />
クレジットを$0.5消費しました。使い切れる自信がありません。</p>
<h2 id="ドメイン代"><a href="#%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E4%BB%A3">ドメイン代</a></h2>
<p><img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F127547%2F47080e38-4045-f28d-c4d8-e55661e5af2d.png?ixlib=rb-1.2.2&auto=compress%2Cformat&gif-q=60&s=4106c6c479ee293fc185f0b086063bc9" alt="ドメイン代" /><br />
1,600円です。<br />
<a target="_blank" rel="nofollow noopener" href="https://domains.google.com/">Google Domains</a>でappドメインを取りました。<br />
appドメインはSSL証明書無しでは使えないという安全なドメインです。<br />
GAEの場合、SSL証明は<a target="_blank" rel="nofollow noopener" href="https://cloud.google.com/appengine/docs/standard/nodejs/securing-custom-domains-with-ssl?hl=ja">デフォルトで有効&無料</a>です。</p>
<h1 id="収益"><a href="#%E5%8F%8E%E7%9B%8A">収益</a></h1>
<p>AdSense広告を導入しています。<br />
キャプチャは載せて良いのか分からなかったので・・・<br />
半月で約1,300円でした。</p>
<h1 id="所感"><a href="#%E6%89%80%E6%84%9F">所感</a></h1>
<h2 id="環境構成について"><a href="#%E7%92%B0%E5%A2%83%E6%A7%8B%E6%88%90%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6">環境構成について</a></h2>
<p>一番びっくりしたのはNuxt.jsがF1インスタンスで落ちずに稼働していることです。<br />
公式ドキュメントでも<a target="_blank" rel="nofollow noopener" href="https://ja.nuxtjs.org/faq/appengine-deployment/">F2が推奨されてる</a>のですが、F2では無料枠に収めることが難しいです。<br />
バックエンド処理をFirebaseに任せてるおかげで負荷が少ない構成になってるのかなーと思います。</p>
<h2 id="費用について"><a href="#%E8%B2%BB%E7%94%A8%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6">費用について</a></h2>
<p>正直「バズった」と言える数値ではないと思ってるので「バズっても大丈夫」とは言えないです・・・<br />
座布団数(ボケツイートのいいね/RT総数)も、現在のランキング1位は3桁です。<br />
「バズっても大丈夫」と分かったら改めて記事書くので、誰かバズってください。</p>
<p>しかし、まぁバズが発生してない個人開発としてはそれなりのアクセス数だと思ってます。<br />
それで数十円なので「そんなに怖くないよ!」とは言えるかと。</p>
<h2 id="安心して使うために"><a href="#%E5%AE%89%E5%BF%83%E3%81%97%E3%81%A6%E4%BD%BF%E3%81%86%E3%81%9F%E3%82%81%E3%81%AB">安心して使うために</a></h2>
<ul>
<li>GCPの課金アラートを設定する</li>
<li>Rulesはちゃんと書く</li>
</ul>
<p>は最低限やっとくべきです。<br />
ただ、Rulesはちゃんと書くと一般的なバックエンド処理と同レベルの規模になると思います。<br />
最低限の尺度が難しいですが、認証/取得件数/タイムスタンプ比較辺りは最低でもやっておくべきです。</p>
<h2 id="マネタイズについて"><a href="#%E3%83%9E%E3%83%8D%E3%82%BF%E3%82%A4%E3%82%BA%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6">マネタイズについて</a></h2>
<p>AdSenseに頼ったサービスの運営は凄く難しいという体験をしました。<br />
PV落ちたら施策を打たないといけないので放置出来ないし、<br />
収益率はAdSenseの匙加減1つで大きくブレそうです。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://qiita.com/kinmi/items/c66aa98718acad84621b">前作</a>ではマネタイズしてなく、正直「もしバズったらお金かかるよな・・・」とアクセス数に対してネガティブになってました。<br />
その経験を踏まえ、広告を貼りました。<br />
結果、素直に「バズれ!」と思えるようになったので、それだけでも導入した価値はあったかと思います。</p>
<h1 id="おわり"><a href="#%E3%81%8A%E3%82%8F%E3%82%8A">おわり</a></h1>
<p>今後、この個人開発で得た知見で記事書こうと思ってます。</p>
<ul>
<li>TwitterAPIがBANされた話</li>
<li>Firestoreの構成について</li>
<li>文字入れ画像を作るソースコード</li>
<li>オレオレアトミックデザイン</li>
</ul>
<p>他に「ここ知りたい」等あれば公開しますし、ボリュームある内容であれば記事書きます!</p>
<p>ただ、一番書きたいのは「バズっても大丈夫だった件」です。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://twigiri.app/">Twitter連動型 大喜利サイト「ついぎり」</a><br />
<img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F127547%2F61391e21-cd2f-0ca3-734e-f96beee4a3b5.png?ixlib=rb-1.2.2&auto=compress%2Cformat&gif-q=60&s=1d4d37fe422a9c228abb233de8b07382" alt="ついぎり" /><br />
面白い投稿お待ちしてます😋</p>
きんみ
tag:crieit.net,2005:PublicArticle/14569
2018-10-17T21:00:29+09:00
2018-10-31T19:23:29+09:00
https://crieit.net/posts/GAE-Nuxt-js-Firebase
GAE+Nuxt.js+Firebaseでネココさんを喋らせるだけのサービス作成
<p>昔mixiアプリでネココレースというアプリを作ったのですが、その素材が放置状態でもったいない事に気づいたので、ネココさんを着替えさせて喋らせてTwitter上に投稿できる簡易なWebアプリを作ってみました。</p>
<p><a href="https://crieit.now.sh/upload_images/9c02acacc8e85cad30e244aa8f8f46595bc685d547bab.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/9c02acacc8e85cad30e244aa8f8f46595bc685d547bab.png?mw=700" alt="yf4qcSgR8rZR0fmmSwS7.png" /></a></p>
<p><a target="_blank" rel="nofollow noopener" href="https://nekoko.alphabrend.com/">ネココさんトーク</a></p>
<p>ログインなど不要ですぐ使えます。</p>
<h2 id="構成"><a href="#%E6%A7%8B%E6%88%90">構成</a></h2>
<h3 id="Google App Engine"><a href="#Google+App+Engine">Google App Engine</a></h3>
<p>この手のWebサービスにはあまり意味がないのですが、SSR(サーバーサイドレンダリング)で一応全部ページクロールできるようにして多少SEO的な効果も期待し、静的ホスティングサービスではなくGoogle App Engineにしてみました。</p>
<h3 id="Nuxt.js"><a href="#Nuxt.js">Nuxt.js</a></h3>
<p>最近は簡単なアプリケーションはNuxt.jsだととにかく簡単に色々作れるのでよく使っています。前述と同様、SSR目的でもあります。</p>
<h3 id="Firebase"><a href="#Firebase">Firebase</a></h3>
<p>今回はデータを登録して表示するだけというシンプルなデータ構成のため、わざわざサーバーを用意しなくてもよいFirebaseを使ったサーバーレス構成にしました。</p>
<p>データの保存にFirestore、画像の保存にStorageを使っています。</p>
<h3 id="Buefy"><a href="#Buefy">Buefy</a></h3>
<p>Bulmaというやわらかい感じのデザインを実装できるフレームワークを使っています。ただ、Bulma自体はほんとにCSSだけで、動きなどは自分で付けなければなりませんので、動き部分も実装されているBuefyを使っています。これを入れるだけでBulma自体のCSSもそのまま使うことができ汎用的で非常に便利です。</p>
<h2 id="仕組み"><a href="#%E4%BB%95%E7%B5%84%E3%81%BF">仕組み</a></h2>
<h3 id="プロジェクトの作成"><a href="#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90">プロジェクトの作成</a></h3>
<p>プロジェクトはcreate-nuxt-appを使って作成し、TypeScriptを追加しました。以前下記でまとめていた方法になります。</p>
<p><a href="https://crieit.net/posts/Nuxt-js-Express-TypeScript">Nuxt.js+ExpressのプロジェクトをTypeScript化する</a></p>
<h3 id="Storeの利用"><a href="#Store%E3%81%AE%E5%88%A9%E7%94%A8">Storeの利用</a></h3>
<p>動物や着せ替えの選択は、選択したコンポーネントだけでなく、画像のダウンロードやシェアする画像を作成する等、他の場所でも使うためにStoreのStateとして保持しておきます。</p>
<p>StoreはNuxt.jsのマニュアルを見ると非常に理解しやすく、下記の記事でも以前まとめています。</p>
<p><a href="https://crieit.net/posts/Vuex-Store-Nuxt">VuexのStoreはNuxt.jsのマニュアルを見るとすぐ理解できる</a></p>
<h3 id="画像の作成"><a href="#%E7%94%BB%E5%83%8F%E3%81%AE%E4%BD%9C%E6%88%90">画像の作成</a></h3>
<p>画像は html2canvas で作成しました。今回はサーバーが無いためこれを使ってブラウザ上で画像を作成する形です。<code>left: -2000px</code> とかにしたdiv上にあれこれ配置し、それをhtml2canvasで変換しているだけです。</p>
<p>一点注意点として、デフォルトの挙動では端末のサイズによってcanvasのスケールが変わってしまうようですので、下記のように等倍で作成します。</p>
<pre><code class="javascript"> const canvas = await html2canvas(this.$refs.canvas, { scale: 1 })
</code></pre>
<p>Blobに変換する方法は下記等、色々情報があります。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://qiita.com/0829/items/a8c98c8f53b2e821ac94">Canvasで描画した画像を送信してサーバに保存する - Qiita</a></p>
<p>canvas.toBlob もあるみたいですね。早く全てのブラウザで実装されてほしいものです。</p>
<p>あとはStorageへの登録はマニュアル通りです。ファイル名は登録したメッセージデータのID名にしています。</p>
<pre><code class="javascript"> const ref = firebase.storage().ref()
const imageRef = ref.child(`images/${messageId}.png`)
const imageSnapshot = await imageRef.put(blob)
</code></pre>
<p>画像のURLも取っておきます。調べた情報によると、上記のimageRefでなく、再度Storage側から取ってきたものを使わないとダメなようです。</p>
<pre><code class="javascript"> const ref = firebase.storage().ref()
const imageRef = ref.child(`images/${messageId}.png`)
const url = imageRef.getDownloadURL()
</code></pre>
<p>このURLもメッセージデータに保存しておけば完成です。</p>
<p>あとは表示画面で入力されたメッセージや画像のURLをメタタグに入れておけば、その詳細ページのURLをシェアしてもらうことでツイートでシェアすることができます。</p>
<p>Nuxt.jsの場合メタタグの設定はページコンポーネント内で下記のように行います。</p>
<pre><code class="javascript"> head() {
const title = this.getTitle() + ' - ネココさんトーク'
const description = `${this.categoryExplanation}:${this.message.message}`
return {
title,
meta: [
{
name: 'description',
content: description
},
{ name: 'og:title', content: title },
{
property: 'og:image',
content: this.message.imageUrl
},
{
property: 'og:description',
content: description
},
{
name: 'twitter:card',
content: 'summary_large_image'
},
{
name: 'twitter:image',
content: this.message.imageUrl
}
]
}
}
</code></pre>
<p>SSRのためデータはasyncDataで取っておきましょう。</p>
<pre><code class="javascript"> async asyncData({ params }) {
const messageRef = messagesCollection.doc(params.id)
const message = await messageRef.get()
const messageData: any = message.data()
messageData.id = message.id
return {
message: messageData
}
}
</code></pre>
<p>シェアする画面へのURLの作成は下記のような感じです。</p>
<pre><code class="javascript"> tweetUrl() {
const url = encodeURIComponent(
process.env.URL + `/messages/${this.message.id}`
)
const text = encodeURIComponent(this.categoryExplanation)
const hashtags = encodeURIComponent('ネココさんトーク')
return `https://twitter.com/share?url=${url}&text=${text}&hashtags=${hashtags}`
}
</code></pre>
<h3 id="デプロイ"><a href="#%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4">デプロイ</a></h3>
<p>Google App Engineへのデプロイは下記で以前解説しています。</p>
<p><a href="https://crieit.net/posts/App-Engine-Nuxt-SSR">App Engineの標準環境でNuxtを使って無料SSR</a></p>
<p>ZeitのNowでも良いと思います。GAEはFirebaseのプランが変わってしまう(無料枠は利用可能です)、Zeitは無料でのデプロイ回数制限がある、という違いがあるので適宜良い方を選択してください。</p>
<h3 id="おまけでGA"><a href="#%E3%81%8A%E3%81%BE%E3%81%91%E3%81%A7GA">おまけでGA</a></h3>
<p>Google Analyticsの導入は下記をインストールして設定するだけでした。めちゃくちゃ簡単。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://github.com/nuxt-community/analytics-module">nuxt-community/analytics-module: Google Analytics Module</a></p>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>大雑把になりますが作り方をざっと紹介しました。興味のある方は是非試してなにか作ってみてください!</p>
<p>不明点があればTwitter等で聞いてもらえれば可能な範囲で答えます。</p>
だら@Crieit開発者
tag:crieit.net,2005:PublicArticle/14568
2018-10-15T20:58:55+09:00
2018-10-24T18:03:52+09:00
https://crieit.net/posts/Google-App-Engine
Google App Engineでさくらのドメインを使ってカスタムドメイン
<p>Google App Engineではカスタムドメインを設定できるため、自分の持っているドメインで運用できるようになっています。さくらのドメインでそれの設定を行う時にエラーが出てしまったのですが、とりあえずうまくいったのでメモしておきます。</p>
<h2 id="エラー"><a href="#%E3%82%A8%E3%83%A9%E3%83%BC">エラー</a></h2>
<p>Google App Engineでカスタムドメインの設定を行う際に、DNSに設定すべきレコード一覧が表示されます。Aレコード4つ、AAAAレコード4つとCNAME1つです。</p>
<p>さくらのドメインのDNS設定にてこれを登録しようとした場合、AレコードとAAAAレコードは問題なく追加できたのですが、CNAMEを追加しようとした時に「レコードが存在するエントリへの、CNAMEレコード追加はできません。」というエラーが表示されました。</p>
<p>仕方なく先にCNAMEを追加してからAレコードを追加しようとしましたが、それもダメでした。</p>
<h2 id="解決方法"><a href="#%E8%A7%A3%E6%B1%BA%E6%96%B9%E6%B3%95">解決方法</a></h2>
<p>CNAMEは登録しなくてもカスタムドメインでアクセスできました。試していませんが、もしかしたらCNAMEを追加するだけでもいけるのかもしれません。</p>
だら@Crieit開発者
tag:crieit.net,2005:PublicArticle/14498
2018-08-03T20:50:24+09:00
2018-11-25T22:03:58+09:00
https://crieit.net/posts/GAE-Nuxt-SSR-Firestore
GAE+NuxtのSSRでFirestoreを使う
<p><a href="https://crieit.net/posts/App-Engine-Nuxt-SSR">App Engineの標準環境でNuxtを使って無料SSR</a> を先日やってみたので、今度はFirebaseのCloud Firestoreでデータの保存を試してみました。</p>
<p>ちなみにGAEのスタンダード環境ではNode8が動くため、ローカルでも全てNode8で動かす必要があります。</p>
<p>※また後日記事を書きますが、通常セキュリティルールが入っているため、実際にはcloud functions経由でfirebase-adminを利用してデータを取ってくる必要があります。</p>
<h2 id="Firebaseの初期設定"><a href="#Firebase%E3%81%AE%E5%88%9D%E6%9C%9F%E8%A8%AD%E5%AE%9A">Firebaseの初期設定</a></h2>
<p>plugins/firebase.jsに下記のように設定を保存します。</p>
<pre><code class="javascript">import * as firebase from "firebase";
require("firebase/firestore");
if (!firebase.apps.length) {
const config = {
apiKey: "your firebase api key",
authDomain: "your firebase auth domain",
databaseURL: "your firebase database url",
projectId: "your google cloud platform project id",
storageBucket: "your google cloud platform storage bucket",
messagingSenderId: "your firebase messaging sender id"
};
firebase.initializeApp(config);
}
firebase.firestore(); // もしかしたら要らないかも
</code></pre>
<p>そしてnuxt.config.jsで上記を読み込むようにしておきます。</p>
<pre><code class="javascript"> plugins: ["~/plugins/firebase.js"],
</code></pre>
<p>これでFirebaseのライブラリがNuxt上で利用できるようになります。</p>
<h2 id="Firestoreへのデータ追加&取得"><a href="#Firestore%E3%81%B8%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E8%BF%BD%E5%8A%A0%EF%BC%86%E5%8F%96%E5%BE%97">Firestoreへのデータ追加&取得</a></h2>
<p>元々あるindex.vueを下記のように修正し、データの一覧を追加してボタンを押すとデータを登録できるようにした最小のサンプルを作ってみました。(関係ないところは削っています)</p>
<h3 id="テンプレート"><a href="#%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88">テンプレート</a></h3>
<p>テンプレートは単にデータを表示しているだけで特筆するところは無いです。</p>
<pre><code class="html"><template>
<section class="container">
<div>
<div v-for="text in texts" :key="text.id">
<span>{</span><span>{</span> text.body <span>}</span><span>}</span>
</div>
<input type="text" v-model="textInput">
<button type="button" @click="add">add</button>
</div>
</section>
</template>
</code></pre>
<h3 id="スクリプト"><a href="#%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88">スクリプト</a></h3>
<h4 id="初期化"><a href="#%E5%88%9D%E6%9C%9F%E5%8C%96">初期化</a></h4>
<pre><code class="javascript">import db from "../lib/db";
</code></pre>
<p>DBを簡単に使える様にインポートしてすぐ使えるようにしています。これは別に必ず作らなければならないわけではありません。中身は単にdbを初期化して取ってきているだけです。</p>
<pre><code class="javascript">import * as firebase from "firebase";
export default firebase.firestore();
</code></pre>
<h4 id="データをFirestoreから取得してくる"><a href="#%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92Firestore%E3%81%8B%E3%82%89%E5%8F%96%E5%BE%97%E3%81%97%E3%81%A6%E3%81%8F%E3%82%8B">データをFirestoreから取得してくる</a></h4>
<p>ページを読み込むと、まずFirestoreからデータを取ってきて一覧します。</p>
<pre><code class="javascript">async function getTexts() {
return new Promise(callback => {
let texts = [];
db
.collection("texts")
.get()
.then(query => {
query.forEach(doc => {
texts.push(doc.data());
});
callback(texts);
});
});
}
export default {
data() {
return {
texts: [],
textInput: ""
};
},
async asyncData({ params }) {
return { texts: await getTexts() };
}
}
</code></pre>
<p>データの初期化にmountedを使うことは多いと思いますが、これはサーバーサイドレンダリングでは動作しないため、代わりに<code>asyncData</code>や<code>fetch</code>を使う必要があります。<code>asyncData</code>は下記URLに使い方が載っていますが、async/awaitを使ったり、Promiseやcallback形式など自由に選べるようです。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://ja.nuxtjs.org/guide/async-data/">非同期なデータ - Nuxt.js</a></p>
<p>あとこの中では<code>this</code>が使えないため、仕方なく適当にクラスの外にfunctionを定義してそれを呼び出しています。</p>
<p>あ、あとasyncDataはコンポーネントでは使えないため、今回はページ上で実行しています。実際の開発の際もコンポーネントで値を使いたい場合はプロパティで渡すか、storeを使うかになると思います。</p>
<h4 id="データをFirestoreに追加する"><a href="#%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92Firestore%E3%81%AB%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B">データをFirestoreに追加する</a></h4>
<p>あとは追加ボタンをクリックした時の処理を追加します。</p>
<pre><code class="javascript"> methods: {
add() {
db
.collection("texts")
.add({
body: this.textInput
})
.then(docRef => {
this.textInput = "";
return getTexts();
})
.then(texts => (this.texts = texts));
}
}
</code></pre>
<p>追加してとりあえず先程の一覧取得処理を実行しているだけです。</p>
<p>これでFirestoreにデータが保存され、画面上にも表示されます。Firebase Consoleのデータ一覧でも確認できます。</p>
<h2 id="サーバーサイドレンダリングされているか確認"><a href="#%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%B5%E3%82%A4%E3%83%89%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E7%A2%BA%E8%AA%8D">サーバーサイドレンダリングされているか確認</a></h2>
<p>Google App Engineで動作させればサーバーサイドレンダリングされますので、一度ページをリロードして確認すればソース上に登録した文字列が存在するのが確認できると思います。(間違って<code>mounted</code>で処理しているとSSRされません)</p>
<p>FIrebaseだとデプロイもあっというまでサーバー側の処理とか何も気にしないでいいので楽ですね!</p>
<p>あとはFirestoreには<a target="_blank" rel="nofollow noopener" href="https://firebase.google.com/docs/firestore/query-data/listen?hl=ja">リアルタイム アップデート</a>の機能もありますので、一覧取得とかは頻繁に更新されるのであればそっちでやってみるのも良いかもしれません。</p>
だら@Crieit開発者
tag:crieit.net,2005:PublicArticle/14496
2018-08-02T18:33:54+09:00
2019-08-19T21:06:18+09:00
https://crieit.net/posts/App-Engine-Nuxt-SSR
App Engineの標準環境でNuxtを使って無料SSR
<p>Google App Engine(GAE)のStandard EnvironmentにNode.jsが追加されているようです。元々Node.jsは有料のFlexible環境でしか使えなかったため、無料で使えるようになったのは非常に嬉しいです。</p>
<p>元々Firebase HostingやNetlifyで無料でNuxtを動かす事はできるのですが、それらは静的ホスティングサービスのためSSR(サーバーサイドレンダリング)ができません。(Functionsを使ったり等で可能ではあるようですが、アクセスが増えると費用がかさむようになると思います)</p>
<p>GAEであればサーバー上でNodeが動くためSSRも問題なく可能でSEO的にも良さそうです。ということでとりあえずGoogle App Engine上でNuxtを動かしてSSRできるところまで試してみました。</p>
<p>Windows SubsystemのUbuntu上で動かしました。</p>
<h2 id="ローカルでNuxtプロジェクトの初期化"><a href="#%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E3%81%A7Nuxt%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E5%88%9D%E6%9C%9F%E5%8C%96">ローカルでNuxtプロジェクトの初期化</a></h2>
<p>まずはローカルでNuxtプロジェクトを作成し、動作するようにします。</p>
<pre><code class="sh">vue init nuxt-community/starter-template nuxtproject
cd nuxtproject
yarn
</code></pre>
<p>とりあえずこれで動くかざっと確認しておきます。</p>
<pre><code class="sh">yarn run dev
</code></pre>
<p><a target="_blank" rel="nofollow noopener" href="http://localhost:3000にアクセスして動いていればOKです。">http://localhost:3000にアクセスして動いていればOKです。</a></p>
<p>GAEにはビルド済みのものをデプロイするため、予めNuxtプロジェクトのビルドまで行っておきます。</p>
<pre><code class="sh">yarn run build
</code></pre>
<h2 id="Google App Engine用の設定"><a href="#Google+App+Engine%E7%94%A8%E3%81%AE%E8%A8%AD%E5%AE%9A">Google App Engine用の設定</a></h2>
<p><a target="_blank" rel="nofollow noopener" href="https://qiita.com/SatoTakumi/items/4f418dc5c700b9d66d7d">Nuxt.js on Google App Engine(GAE)</a></p>
<p>上記のページを参考にし、package.jsonのstartスクリプトにポートとホストの設定を行っておきます。(ポートは不要とコメントには書かれているようです)</p>
<pre><code class="json">"start": "HOST=0.0.0.0 PORT=8080 nuxt start",
</code></pre>
<p>app.yamlも作っておきます。handlersを設定して静的ファイルをキャッシュするようにしないとメモリ不足で止まってしまうらしいです。</p>
<pre><code class="yaml">runtime: nodejs8
env: standard
handlers:
- url: /_nuxt
static_dir: .nuxt/dist
- url: /.*
script: auto
</code></pre>
<p>Nuxt.js2の場合はstatic_dirが .nuxt/dist/client でした。</p>
<p>費用節約のために<code>max_idle_instances</code>を設定したりも必要になると思います。下記のページが詳しいです。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://koni.hateblo.jp/entry/2016/01/06/130613">Google App Engineを無料で運用する方法(2018年版) - koni blog</a></p>
<p>僕の場合はいつの間にか<code>.gcloudignore</code>ファイルがあったので、そちらにデプロイしないファイルを設定しておきました。ない場合は作っておきましょう。<code>.git</code>や<code>node_modules</code>をデプロイしてしまうとうまくデプロイできないらしいです。</p>
<p>あとはGAEにデプロイします。</p>
<pre><code class="sh">gcloud app deploy
</code></pre>
<p>ただ、僕の場合エラーになりました。下記を参考にし、sqlite3のライブラリをインストールします。その後Pythonもインストールし直しが必要のようです。僕はpyenvを使っていたためアンインストールとインストールし直しが楽だったので助かりました。</p>
<p><a target="_blank" rel="nofollow noopener" href="https://qiita.com/chatrate/items/bc37e3b7b303e834dd1e">【ubuntu】ImportError: No module named '_sqlite3'とでたときの対処法【Python】</a></p>
<pre><code class="sh">sudo apt-get install libsqlite3-dev libbz2-dev libncurses5-dev libgdbm-dev liblzma-dev libssl-dev tcl-dev tk-dev libreadline-dev
</code></pre>
<h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2>
<p>あとはGAEへのデプロイが完了したらメッセージに表示されているようにコマンドやURL直接アクセスで動作確認することができます。問題なくNuxtが動作している画面が表示されていれば完成です。</p>
<p>ソースを見てみるとVueコンポーネント内の文字列などが表示されていると思います。</p>
<p>ただ、Google App EngineのStandard Environmentはデフォルトで128MBのメモリしか無いようです。無料枠だとそれを使うしかないのですが、Nuxtを利用したNode環境だとどの程度の動作まで耐えきれるのかが謎です。引き続き試していってみたいと思います。</p>
だら@Crieit開発者