herokuでのデプロイが便利すぎる件について

はじめに

railsでかいたwebアプリを公開したいなと思い、herokuを使用しました。
https://www.twi-reviews.jp/
こちらが公開したwebアプリです!今人気のゲームを、最新AI技術を用いた独自のシステムで評価しているサイトです。分析は、該当商品に関するツイートを集計し、評価・星付けをしています。ゲームが好きな人はよかったらのぞいて行ってください。

herokuとは

サーバやOS、データベースなどの「プラットフォーム」と呼ばれる部分を、インターネット越しに使えるようにしてくれるサービスの一つです。
今まで別々に扱っていたものを一緒に扱え、さらにgui操作(コマンドで打つんじゃなくて、目に見える形で操作すること)で様々なことができるので扱いやすいです。
さらに、基本的なことは全て無料でできます。優しい世界ですよね。

hetokuの便利な機能

そんなherokuの、特に便利だなって感じた機能をまとめていきます。

heroku Scheduler

今まで、自動的にコードを走らせたい場合は、シェルスクリプトを書かなければいけませんでした。
シェルスクリプトについてはこちらを参考にしてください。
【1分でわかる】シェルスクリプトとは?
それがguiで操作できるのがこのheroku Scheduler、予想以上にわかりやすいです。

add-onsインストール方法

herokuのアプリ管理画面の、Resourcesの下のFind more add-onsからheroku Schedulerをインストールしてください。Add-onsに追加されたら成功です。

Schedulerを登録

heroku Schedulerから、Add new jobを押してください。そこで繰り返し処理させたいコマンドを打ち込みましょう。
当webサイトでは表示している商品情報をamazonのs3に置いていて、そこのファイルを編集すれば自動的にサイト内容が変わるようにしています。f:id:saegusa41010:20190217181751p:plain こうすれば毎日走ってくれます。ここで注意しなければいけないのは、ここに表記されているのは協定世界時なので、日本の標準時間に直さなければなりません。このwebサイトを利用して変換しましょう
UTC/協定世界時とJST/日本標準時の変換と時差の計算

ステージング環境が容易に作れる

webアプリにおいて、localだけでは確認できないことがたくさんあります。どう作動するのかよくわからないものを本番環境にあげることは許されないので、本番環境と全く同じ環境のステージング環境を用意する必要があります。それが容易に作れちゃうのがすごい。
Heroku Pipelineを使ってみる - Qiita この記事がとても親切に方法について書いてありました!参考にしてください。

herokuのここが惜しい

そんな便利なherokuですが、ここはもう少し頑張って欲しかったって感じた点を載せていきます。

独自ドメインは無料じゃない

独自のドメインを載せるには、無料のfreeプランではできませんでした。月7ドルの課金をして、Hobbyプランにする必要があります。
qiita.com とてもわかりやすくまとめてありました。

fileのコードによるアップロードができない

ファイルシステムに画像をアップロードする処理を実装してHerokuにアップロードしたところ、Herokuは1日1度のDynoの再起動に伴いアップロードしたファイルを全消去するという仕様があることが判明しました。なのでそのような機能を使いたい場合はamazon s3などの外部ストレージサービスを用いる必要があります。
その方法については後ほど記事ににしたいと思います。

最後に

随時更新していきたいと思います。最後までお読みいただきありがとうございました!
ご意見ご感想募集しています。気軽にコメントしてね

参考

material-uiでGridのxs属性が効かずスマホ対応できない

material-uiではGridの属性でスマホ対応などが簡単にできる。

ブレークポイントの表

以下のようなブレークポイント(切り替えの値)で、スマホ対応ができる。
- xs, sm以下に適用
- sm, 600dp〜(一般的なスマートフォン)
- md, medium: 960dp〜(ipadなど)
- lg, large: 1280dp〜(一般的なノートパソコン)
- xl, xlarge: 1920dp〜(大きめのデスクトップパソコンなど)
参考:

Material-UIでGridレイアウトを試す - Qiita

例えばパソコンでは2:8:2、スマートフォンでは1:10:1にしたいときは

<Grid container>
  <Grid item xs = {1} lg ={2}>
    <Component1/>
  </Grid>
  <Grid item xs = {10} lg ={8}>
    <Component2/>
  </Grid>
  <Grid item xs = {1} lg ={2}>
    <Component3/>
  </Grid>
</Grid>

とすれば良いです。

xs属性が効かない!??

上記のようにして、Chromeのdeveloperツールでスマホ対応ができているか確認しようとしたら f:id:saegusa41010:20190216152443p:plain あれ、変わらない?となりました。原因は、スマホのPCサイトをみやすくする機能でした。スマホはPCサイトを見やすくするために独自の画面サイズが定義されていて、スマホでサイトが表示されたときに、パソコンと同じ画面サイズのスタイルで表示されるようになっています。
本来の画面サイズで適用されるようには、metaタグのviewportを利用する必要があります。 htmlのheadのなかに以下の一文を記述

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">

するとしっかりスマホ対応してくれました。めでたしめでたし。 参考:
【CSS】スマホで Media Queries が効かないときの対処法 - Qiita

最後に

最後までお読みいただきありがとうございました!ご意見、ご感想お待ちしています!
また、私heroku,rails,Reactで書かれているwebサイトを運営しています。
https://www.twi-reviews.jp/
今人気のゲームを、最新AI技術を用いた独自のシステムで評価しているサイトです。分析は、該当商品に関するツイートを集計し、評価・星付けをしています。
よかったらのぞいてみてください!

railsのherokuデプロイ時に起こるエラーまとめ

動作環境

Rails 5.2.2
heroku/7.21.0 darwin-x64 node-v11.9.0
db: local->sqlite
本番->postgresql

よくわからないエラー多すぎない?

railsでwebサイトを書いている人は多くの人がherokuでデプロイすると思います(公式にオススメされているので)。
これからデプロイするよって人はこの記事がとてもわかりやすいのでオススメです。

【初心者向け】railsアプリをherokuを使って確実にデプロイする方法【決定版】 - Qiita

しかし、予期せぬところでエラーに遭遇し、ググってもその原因の対処法が古かったり特定の状況のみにしか対応していなかったりで困る体験が多い印象です。 なので、ここでは遭遇したエラーをまとめていきたいと思います。(随時更新していきます。)

はじめに

herokuデプロイ時のエラーで一番嫌なのがデプロイのために数分待って初めてエラーに遭遇することです。
なので、エラーに遭遇したらできる限りlocal環境でエラー原因を特定、修正、テストをできるようにしましょう。

エラー集

Precompiling assets failed.

rake assets:precompileが失敗したというメッセージです。まずはlocalで原因を確認してみましょう。 RAILS_ENV=production bundle exec rake assets:precompile これでエラー内容を確認して、修正しましょう。
私の場合は、以下のコードをconfig/application.rbに加えたら改善しました。

参考:

RailsでアプリをHerokuにあげる時のエラー各種 - Qiita

postgresqlにはnumberがない

localではsqlite, 本番環境ではpostgresqlを使っている人が注意すべきポイントです。sqliteにはnumberがあるけれど、postgresqlにはnumberは用意されていません。代わりに用意されているのはnumericです。なのでdb/migrete以下のfileでnumberを使っていたら、numericに書き換えましょう。

最後に

最後までお読みいただきありがとうございました!ご意見、ご感想お待ちしています!
また、私heroku,rails,Reactで書かれているwebサイトを運営しています。
https://www.twi-reviews.jp/
今人気のゲームを、最新AI技術を用いた独自のシステムで評価しているサイトです。分析は、該当商品に関するツイートを集計し、評価・星付けをしています。
よかったらのぞいてみてください!

UXにこだわったReactの書き方

最近、Reactで書かれたSPAのサイトがどんどん増えてきました。
そこでReactでどのような書き方をしたら早く動くのか、逆にどんな書き方をしてしまったら重くなってしまうのかまとめてみました。

まずはReactで書かれたwebサイトを見てみよう

https://www.twi-reviews.jp

今人気のゲームを、最新AI技術を用いた独自のシステムで評価しているサイトです。分析は、該当商品に関するツイートを集計し、評価・星付けをしています。 このwebサイトはReactで書かれており、サックサク動きます。このようなサイトがどのような工夫をしてReactを書いているのかをまとめてみました。

Reactの強み

  1. めっちゃ早い

なのでUXもめっちゃよくなります。 それは、DOMツリー作成時に、差分だけを描画するアルゴリズムが採用されているからです。 簡単に言うと、一度作ったComponentは再利用しちゃおうってことです。

  1. めっちゃ書きやすい

今までhtmlでテンプレート作って、cssで見た目整えて、jqueryでイベントを処理して、、、という作業を繰り返していたと思います。それがjsで全てかける分楽です。画期的です。

ミスると重くなる

上記のように早いかつ書きやすいReactですが、書き方のお作法を守らないと途端に遅くなります。今回はそんな例をいくつか紹介したいと思います。

mapでのkey忘れ

これが一番ありがちですね。
ex)

<div>
  {[1, 2, 3, 4, 5].map(index => {  
  return (
  <div>
    <Component/>
  </div>
  );
})}
</div>

正しくは

<div>
  {[1, 2, 3, 4, 5].map(index => {  
  return (
  <div key = {index} >
    <Component/>
  </div>
  );
})}
</div>

としましょう。
この理由は、先ほど紹介した、Reactの差分アルゴリズムにあります。uniqueなkeyを割り当てて置かないと、差分がどこにあるのか特定できず、結局全てのcommponentを再描画することになってしまいます。mapを用いる場合は必ずuniqなkeyを割り当てましょう(uniqなkeyとは、そのmapのなかでのみuniqであればよく、プログラム全体でuniqなkeyである必要はありません。) そうしていないと、以下のようなwarningが出るので、これを見たらkeyをつけましょう。

Each child in an array should have a unique "key" prop. Check the render method of KeyTrap. See http://fb.me/react-warning-keys for more information.

参考:

React.jsの地味だけど重要なkeyについて - Qiita

render内でメソッドを定義

これは盲点だと思います。keyつけてるのに遅い、、、なんで、、、ってなったらこれを疑いましょう。
しかも公式のドキュメントでもこのような書き方をしている部分があるので、多くの人が陥りがちな記法です。
ex)

render(){
return(
<div>
  {[1, 2, 3, 4, 5].map(index => {  
  return (
  <div key = {index}>
    <Button onClick={()=>this.hogeFunction()}/>
  </div>
  );
})}
</div>
)
}

、、、え、なんでダメなの?って思った人が多いと思います。この記法でダメなポイントは
()=>this.hogeFunction()をrender内で定義しているため、メモリリークとなってしまう
という点です。この例ではlistのサイズは5なので、さほど問題はないのですが、このlistが大きくなればなるほどメモリは消費されます。 なので、以下のように書きましょう。

render(){
return(
<div>
  {[1, 2, 3, 4, 5].map(index => {  
  return (
  <div key = {index}>
    <Button onClick={this.hogeFunction}/>
  </div>
  );
})}
</div>
)
}

この書き方で大丈夫です
()をなくすだけの簡単なお仕事ですね

関数に引数をもたせたい場合

この時が少し厄介です。
ex)

render(){
return(
<div>
  {[1, 2, 3, 4, 5].map(index => {  
  return (
  <div key = {index}>
    <Button onClick={()=>this.hogeFunction(index)}/>
  </div>
  );
})}
</div>
)
}

先ほどのmapでlistを回した際に、indexの値を引数としてもたせたい場合は先ほどの記法ではうまくいきません。
そんな時はmapの中身をclass化しましょう

render(){
return(
<div>
  {[1, 2, 3, 4, 5].map(index => {  
  return (
 <HogeActionButtonClass key={index} index={index} hogeFunction={this.hogeFunction}/>
  );
})}
</div>
)
}
...
class HogeActionButtonClass extends React.Component {
  constructor(props) {
    super(props);
    this.hogeFunction = this.hogeFunction.bind(this);
  }

  hogeFunction(){
  this.props.hogeFunction(this.props.index)
  }

  render(){
  return(
  <div>
    <Button onClick={this.hogeFunction}/>
  </div>
  );}
}

このようにかくと、render内の()=>という記法が無くなります!イメージとしては、全体の関数であったHogeFunctionを各Buttonにも持たせることで、引数をpropsとして扱えるようにした点です。これでメモリリークを防ぐことができます。
上記サイト(https://www.twi-reviews.jp)では、ランキングの各ComponentはClass化してあります。

f:id:saegusa41010:20190215165919p:plain
Class化されたComponent

最後に

最後までお読みいただきありがとうございました!不適切な表現やわかりにくい表現等ご意見お待ちしています。