2019年に得た技術
自分のホームページを作った話
概要
紆余曲折を経て、自分の音楽活動用のホームページを作った。
(追記: いろいろあって閉鎖した)
その苦労した箇所を適当に書きなぐっておく。
事の発端
流石にTwitterだけじゃ自分の今までの活動をまとめきれないと思い、 せっかく技術的にアプローチできるのだから自サイトを立ち上げることを決意した。
あと流行りの技術とか使ってみたかったので、いいきっかけだった。
使用技術
frontend
React.js + Material-UI
どこの勉強会いってもReactがVueの話が出てくるので、せっかくだし使ってみようと思って1から勉強。
せっかくだしついででTypescriptで書くことを決意。
backend
まだガワしか作ってないからAPIもクソもないが、そのうち作る。 じゃないと機能拡大ができない。
いまのところElixir(Phoenix)かNode使うかって考えている。
DevOps
Travis-CIによるテスト&デプロイを利用。 ここが一番大変だった。後述。
苦労したところ・わからないところ
React.js
そもそもちゃんとjsとかts書いたことなかったので、かなり基礎的なところを書きながら勉強した。
結局 create-react-apps
があったので、これを利用して開発を開始。
未だに正解がわからないが、コンポーネントとかstateの管理とかは「それっぽく」動くようになった。
Typescriptで書くチュートリアルがないため、しょっちゅうエラーをはいていた。 特にPropsやStateの型関連?
interface IProps {}; interface IState { value: number }; class Hoge extends React.Components<IProps, IState> { ... }
結局上記のように書いて解決できることを知ったが、なんで型引数が必要なのかわかってない。
constructorで暗黙的に呼び出しているからなのかな…?
一応エラーは解消できたので書き方としては正しいんだと思う。
しかしここは完全に勉強不足なので、他のReactで構成されたOSSとかを覗いてみるのもいいかもしれない。
Reactのテストについて
どういうことを検証するためにどんなテストをしていいのかわからなかった。
単純にメソッドのインプット・アウトプットを見るだけのテストならわかるが、 多分それだけじゃ不足しているっぽい。
どうやらスナップショットテストというのがあるらしいのは分かったが、それによって何がわかって嬉しいのかがわからずじまい。
もう一回ドキュメント読むなりして解決しないといけない。
Travis-CI
大きく苦戦したのがこいつ。
計画として、下図のような構成を考えていた。
このうち、masterへのpushをトリガーにテストするのはとても簡単だったのだが、 デプロイがなかなかうまくいかずにだいぶ時間をかけた。
Travis上でbuildまでして、buildが成功したらそれをrsyncでサーバにデプロイしようと考えた。
一応ドキュメントを読んで秘密鍵の暗号化とかはできていたのだが、何故か入れない。
結局何が行けなかったかというと、サーバ側に置く公開鍵の所有者問題だった。
開発ローカル上で作った鍵をサーバに送って配置したのだが、 所有者が自分のPCになってしまっていたため、動いていなかったのである。
要するに、chownでデプロイ用ユーザに所有権を移したら動いた。
そしてデプロイ。
サーバ上のホームページルートにデプロイ先のシンボリックリンクを貼ってみたが、動かなかった。
403 Forbidden
が出るのだ。
しかしこれも調べたら非常に単純で、権限問題だった。
Nginxがデプロイ先のディレクトリにアクセスできていなかっただけだった。
参考:
書いてみるとあっけないが、これをすべて解決するのに丸3日かかった。
完全に調査力不足だったと思う。
今後
ガワはひとまず動くものが作れたので、今後やるべきは以下のこと。
- DB設計
- 自分の曲や曲の詳細、曲につけるタグ、更新情報、DiscographyなどをDBでしっかり管理できるようにしなければ
- API作成
- PhoenixかNode,js、もしくはDeno…?
- Microserviceにも挑戦してみたいが、サーバ代が…
- 管理画面作成
- このままだと1曲追加するのにわざわざコードいじらなきゃいけないので、DBだけ変更できるように自分用管理画面を作らないとこの先が辛い
- Reactのテスト
- そもそもフロントエンドに関しての知識が壊滅的に足りないので、フロントエンドでは何がテストできていれば安心できるのかをちゃんと知る必要がある
- Reduxの導入
- State周りが結構つらいのを、どうやらある程度解決できるらしい…?流行ってるし使って見る価値アリだと思う
- monitoring
- 一応現状Mackerelを使っているが、せっかくならPrometheus + Grafana もやってみたい
- デザインの見直し
- 圧倒的にデザインできないので、かっこいいUIにしたい、でもこれは後回し
雑な感想
まずは形になるものができてよかった。
だが、圧倒的に勉強不足が目立った。
わからないけど動いてる、みたいなのがあまりに多すぎるので、継続的に開発を続ける中で解決していきたい。
react-router v4 でホームディレクトリだけを表示したい
概要
react-router で ルーティングをする際、ホームディレクトリ("/")だけを表示したいのに、他のページ("/hoge")なども一緒に描画される
解決策
ホームディレクトリ("/")のRouteのプロパティに exact={true}
を入れる
class App extends React.Component { public handleState(item: number) { this.setState({item}); } public content() { return ( <div> <Route exact={true} path="/" render={props => <Top handleState={this.handleState} />} /> <Route path="/hoge" component={Hoge} /> <Route path="/fuga" component={Fuga} /> </div> ); } public render() { return ( <BrowserRouter> {this.content()} </BrowserRouter> ); } }
create-react-appをtypescriptで始める
$ create-react-app --scripts-version=react-scripts-ts project_name
yarn start
で実行すると自動でブラウザが開く
Phoenix Frameworkでお手軽にAPI作成
環境
- Elixir 1.7.4
- Phoenix v1.4.0
プロジェクト作成
表示関連はいらないのでオプションで指定する。
$ mix phx.new api_project --no-html --no-webpack
DBでMySQLを使いたいときは --database=mysql
も必要。
その後は表示に従って、
$ cd api_project $ mix ecto.create
を実行する。
データモデル作成
今回はjsonを返すAPIを作るので、そのためのデータモデルを作成する。
$ mix phx.gen.json Blog Article articles title:string body:text
表示に従って、ルーティングの追加とマイグレーションをする。
defmodule ApiProject,Router do use ApiProjectWeb, :router pipeline :api do plug :accepts, ["json"] end scope "/api", ApiProjectWeb do pipe_through :api # 以下を追加 resources "/articles", ArticleController, except: [:new, :edit] end end
上記を変更したらマイグレーション。
$ mix exto.migrate
実行
$ iex -S mix phx.server
http://localhost:4000/api/articles
へ以下のようにPOSTするとデータが登録できる。
{ "article": { "title": "記事のタイトル", "body": "記事の本文" } }
レスポンスで以下のようなものが帰ってきたら成功。
{ "data": { "title": "記事のタイトル", "id": 1 "body": "記事の本文" } }
http://localhost:4000/api/articles
をGETすると一覧が見れる。(データは上のレスポンスの内容と一致してるはず)
tips
resources "/articles", ArticleController, except: [:new, :edit]
上記の except: [:new, edit]
の箇所でHTTPメソッドの制限ができる。
例えば表示だけにしたければ
resources "/articles", ArticleController, only: [:index, :show]
とかやるとGETだけ受け付けるようになる。
ルーティングがどうなってるのか知りたければ、
$ mix phx.routes
で一覧を見れるので、そこを見ながらやると良さそう。