react+rails+サーバーサイドレンダリングで開発してますよメモ④

結構ハマったエラー

→単純に違うファイル内でJSX内をコメントアウトしてたらそこで落ちてた
React.Component内のコメントアウトは要注意。。。

react+rails+サーバーサイドレンダリングで開発してますよメモ③

言葉のおさらい

仮想DOM

JSXなどで書いたファイルの中にhtmlのDOMのような記述で書いていったもの

タブ作りたいときに2つの要素の中に追加したい

根本的にjsx内にdomを書いたときにどういう値が返ってくるかわかってない(´・ω・`)
調べる

reactのclassSetアドオンを使いたいんだけどreact-railsに入ってない

としたいのだがundefinedになってしまう。
consoleでReact.addonsを出してみると

のみしかなかったのでclassSetが定義されていないのかもしれない。。。

なんか意味不明なエラーになる

react+rails+サーバーサイドレンダリングで開発してますよメモ②

react-railsのコンパイルというかリロードがマジ遅い

普通に3s位かかる。
おそらくこれはrailsのweblickのせいじゃなくてwebpackのbuildの速さなのではないかと予想。
webpackのbuild用にプラグインを追加 webpackで差分ビルドをする
developmentモードではwebサーバをweblick(rails server)からthinに変更

reactコンポーネントでSSRするものがたくさんありすぎて管理できない問題

みたいに沢山コンポーネントを登録していったらキリがないと思ったけど、page用のパーツを切り出せばよかった。
例えば/books/pages/show.jsxのようなファイルを作ってインポートする。
こうやるとスッキリする

export とかの詳細はこっち → MDNのexportの説明

react-rails内でのassets imageの参照をどうするか

Railsアプリrootの/frontendsディレクトリにreactのsrcを置いており、webpackを用いてapp/assets/javascripts/components/App[Mobile].bundle.jsxにコンポーネント群を置いている。
この場合、コンポーネント内のassetsのパスをどうするかで悩んでいる。
もともとdigestを付けずにpubic配下に置いてそこを参照しようとしていた。
しかし、アプリケーションに対するリクエストが増えるため却下。

対応策の候補としては以下があげられる。
①コンポーネントのpropsとして画像のパスを渡す(一番簡単)
②react-assets-pathとかのgemを使う?
③npmのmoduleを使う
後読み! Using webpack to build React components and their assets

①に関して
実際コンポーネントに渡す画像(ロゴとか矢印とか)が多くないためpropsに

のように渡す。
これが今のところ一番の候補。

②③これは調査なう

react+rails+サーバーサイドレンダリングで開発してますよメモ①

react+railsでアプリケーション作ってるのでメモ

まだ今作ってる最中ですがだーーーーーと殴り書きでメモっていってます(´;ω;`)

## Reactでアプリケーション作るときに参考&勉強した記事

React

公式チュートリアル
react dev tool
React.jsのComponent Lifecycle
すでに動いているRailsアプリケーションにReact.jsを投入する

Webpack

webpack最低限(JavaScript編)
【意訳】Webpackの混乱ポイント
Webpack入門編
webpackを使った Rails上でのReact開発
Node.js gulpでwebpackを使う[
ECMAScript6で書こう!WebPackとES6-loaderで環境を作り、ES6を先取り体験する方法
webpack+babel環境でフロントエンドもES6開発
webpack.config.jsの読み方、書き方
なんとなくで理解しないWebpackのCSS周辺

Redux

Redux入門 1日目 Reduxとは(公式ドキュメント和訳);
ReactとFluxとReduxについて順を追って整理する
Fluxフレームワーク戦争の現状確認(前編)
これクソほどわかりやすい!!!!Reduxチュートリアル動画を見ながらReduxを基礎の基礎から

react + webpack + rails環境構築系

React+ReduxをRails環境下で開発する環境構築テンプレート(Webpackも使うし、Reduxのサーバサイドレンダリングもあるよ)
Rails + モダンJS環境(Webpack)で新規アプリ作成
Rails環境にWebpackを導入する(前半)
すでに動いているRailsアプリケーションにReact.jsを投入する
gulp.jsを用いたフロントエンド開発環境の構築

エラー系

【エラー】Refusing to install as a dependency of itself
npmのinstall時にエラーが出た。packege.jsonのnameとインストールしようとしているパッケージが同じだった

React×ES6×JSXつかってたら怒られたError/Warning集(2016/7/3)
React.Componentを作成したら出たエラーの記事。class作ったらconstructorの記述は必須ですよ。

その他

【メモ】Frontend Meetup vol.1 -SPAを語り尽くす会! 2016/9/16 @株式会社FiNC

メモ達

rquireとimportって何が違うん

Q. reactやcomponentを読み込むときに使うrequireとimportって何が違うねん
A. requireはnode jsの使い方でimportはES2015の使い方

fluxとかreduxとかなんなん

ぶっちゃけ一個のjsでも管理できるよね
Action → onClickとか
Dispatcher → this.setState
store → this.stateで定義したやつ
状態(State)を保管する場所であるStoreは1つだけ
状態(State)は基本読み取りのみ。書き込むにはStoreが提供するメソッドであるDispatchでActionを投げる時だけ
実際にActionを受け取ってStateを変更するのはReducerが受け持つが、Reducerは副作用を持たない関数でなければならない

サーバサイドレンダリングに関して

サーバーサイドレンダリングとか難易度高いのでハマるかもしれない。この環境ではSprocketにのせる前に、gulpでcompileしているので問題ない。app/assets/javascript以下にES6とか書いてる場合、サーバーサイドレンダリングできない。react_railsのサーバーサイドレンダリングではexecjs(v8)を使うんだけどrequire()が使えないため動かない。

app/frontends/にES2015で書いたreact系のComponentファイルを入れて、gulpとwebpackを通じてapp/assets/javascripts/componentにコンポーネントをES5方式で書き出し、それをreact-railsでレンダリングする

以下の用にES2015形式で書いたものをwebpackを使ってES5形式まで落としてapp/assets/javascripts/components/に書き出す

react-railsがやってくれるのはデフォルトだと、app/assets/javascripts/components.js内に記述してあるjsをSSR時に読み込みhtmlにして返すこと

これには条件があり「SSRしたいコンポーネントはwindowオブジェクトに登録されている必要がある」ので、どれだけコンポーネントを作りまくってもwindowオブジェクトに登録されいない限りSSRは出来ない。

現在進行形で困っていること

mobileとPCのリクエストでレンダリングコンポーネントを変更

React-railsはcomponents.jsをデフォルトで読み込み、components.jsの中に書かれているソースの場所からwindowオブジェクトに登録されているReactコンポーネントをSSRする

今回のプロジェクトではRack User Agentを使用してmobileとPCのレンダリングしている。

しかし、React-railsが初期レンダリング時にcomponents.jsを登録するのはアプリケーションの初期化時であるため、リクエストに応じてレンダリングを分ける事ができない。

どういうことかというと、mobile、PCともに同じ名前のHeaderコンポーネントを作った際に、components/App.bundle.jsxとcomponents/AppMobile.bundle.jsxを作った場合、headerという名前がかぶっていると先に読み込まれたほうがレンダリングサれてしまう。

あまり気持ちよくないがHeaderコンポーネントとHeaderMobileコンポーネントを作ることで対応した。
もっとうまくやりたいです。。。

jsx内で参照する画像のパスをどうするか

<%= image_path %>とかをReactコンポーネントから参照したい場合はどうしよう。

多分propsで渡すしかない
アプリケーション全体で使うもの(logo)とかはpublic/assets配下においちゃえばいいかなぁ
ユーザーのアイコンとかはpropsで渡すのが良さそう。
コンポーネントになるし。。。もし分かる人がいたら教えてください。。。

fukamiiiiinminのtwitterまでお願いします(´;ω;`)

多言語サイト作成時のフォント指定の注意点


flickr photo shared by Jirka Matousek under a Creative Commons ( BY ) license

多言語化サービスを作成していてちょっと躓いた事があったので共有です。

多言語サイトを作成しているとその地域に合わせたフォントを指定するとユーザーにとって違和感なくサイトを使うことができると思います。
(海外のサイトで日本語対応してるサイトがあっても変なフォントの場合とかテンション下がりますよね!)

そこでIPアドレスから地域を判別してその地域のフォントに合わせればいいかというとそれだけではうまくいきません。

必要なのは2つです。

  1. htmlのlang属性を指定する
  2. font-familyに最適なフォントを指定する

僕はこの中の2番しか対応しておらず

「font-familyを指定してるのになんでfont変わんないの?dev toolsで見ても普通に指定されてるし。むむむ。。。」

という状態が続いていましたorz

 

それでは1つずつ解説します。

まず、今回の例では

この4つの言語に対応してみたいとします。

 

1.htmlのlang属性を指定する

html5に対応しているwebサイトであればwebページの書き出しは

 

で始まりますよね。

これの

この部分のlang属性の値を変えます。

今回の例で言うと

こうなります。

なので簡体中文圏に対応したい場合は上記コードを修正して

というふうに修正しましょう。

 

2.font-familyに最適なフォントを指定する

※「最適なフォント」と見出しに記述してありますが、各々のサービスで最適なフォントを選んで下さい。
これはcssで

というふうに各言語ごとにfont-familyを指定してあげましょう。

 

まとめ

この2つの方法で各地域ごとに正しいフォントを指定することができます。

僕はfont-familyしか変えていなかったので正しい挙動が起きずぐぬぬっとなっていました。

グローバルなサービスを作る際には必ず必要な処理だと思うので何かの役に立てれば光栄です。

【rails】お問い合わせをgoogle spreadsheetに書き込ももう!

スクリーンショット 2015-10-19 19.48.24

rails + google spreadsheetでお問い合わせを作成したのでやり方をまとめました!

まずこの機能を実装するために必要なデータがあるのでそれを準備しましょう!

googleの

・クライアントID
・クライアントシークレット
・リフレッシュトークン
・google spread sheetのID

です。

これさえ揃えばあとはgemを入れて少しいじるだけで完成します!

上記データを取得するためには

・google consoleでアプリケーションの登録をする
・ターミナルでわちゃわちゃしてrefresh tokenをゲットする
・spreadsheet作成してIDを取得する

の手順が必要になります。

rails初心者の僕にもできたので難しくないと思います!

google consoleにアプリケーションを登録する

https://console.developers.google.com/start
「Use google Api」を選択

スクリーンショット 2015-10-19 19.26.13

 

プロジェクト名を入力(今回はcontactにしました)
すべてのサービスと関連 API について、適用される利用規約を遵守して利用することに同意します。に同意
「作成ボタン」押す

スクリーンショット 2015-10-19 19.27.45

 

右下ににょろっとでてcontactプロジェクトが作成されました。
そのままにしておくと勝手にcontactプロジェクトに移動します。
移動しない人はロゴの右にあるプルダウンからcontactを選択して下さい。

スクリーンショット 2015-10-19 19.28.03

 

左のメニューから
APIと認証 > 認証情報
「認証情報を追加」をクリック
「OAuth 2.0 クライアントID」をクリック

スクリーンショット 2015-10-19 19.32.19

 

「同意画面を設定」をクリック

スクリーンショット 2015-10-19 19.33.21

 

サービス名を入力(その他は任意なので入れる方は入れて下さい)
「保存」をクリック

スクリーンショット 2015-10-19 19.34.05

 

クライアントIDの作成画面
「その他」を選択
「名前」を入力
「作成」をクリック

スクリーンショット 2015-10-19 19.34.21

クライアントIDとクライアントシークレットが作成されました。
メモしましょう!
こんな感じで取得できると思います!
client ID: xxxxxxxxxxxxxxxx.apps.googleusercontent.com
client secret: yyyyyyyyyyyyy

スクリーンショット 2015-10-19 19.35.54

ここからは
client IDを[your client ID]、
client secretを[your client secret]と表現します。

あと1つ作業があります。

OKを押して

左のメニューの中から

APIと認証 > API

Google Apps API > drive APIを選択

スクリーンショット 2015-10-20 10.56.47

 

 

「APIを有効にする」をクリック

スクリーンショット 2015-10-20 10.56.51

これで一旦google consoleでの作業は終わりです!!

・refresh tokenを取得

先ほど取得した[your client ID]を使用して以下のアドレスにアクセスします。

https://accounts.google.com/o/oauth2/auth?client_id=[your client ID]&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/drive&response_type=code&approval_prompt=force&access_type=offline

(url中の[your client ID]は先程入手したクライアントIDに変更してください)

すると先ほど入力したサービス名で認証を求められます。
許可をクリック

スクリーンショット 2015-10-19 19.39.31

 

コードをゲットできます!

このコードを使用してrefresh tokenを取得します!

スクリーンショット 2015-10-19 19.40.33

 

次にターミナルを開きましょう!

スクリーンショット 2015-10-19 19.41.29

 

以下のコマンドを打ち込みましょう!([your client ID]、[your client secret]、[先ほど入手した4/から始まるコード] )

curl -d client_id=[your client ID] -d client_secret=[your client secret] -d redirect_uri=urn:ietf:wg:oauth:2.0:oob -d grant_type=authorization_code -d code=[先ほど入手した4/から始まるコード] https://accounts.google.com/o/oauth2/token

そうすると以下の様な形でデータが返ってきます。

スクリーンショット 2015-10-19 19.43.49

refresh tokenが取得できましたね!
これで
・client ID
・client secret
・refresh tokenが揃いました!

今度はgoogle spreadsheetの準備をしましょう!

 

・spreadsheetの準備

https://docs.google.com/spreadsheets/u/0/にアクセス!
テスト用のアカウントでやってるのでこんな画面が…

スクリーンショット 2015-10-19 19.48.24

右下の+ボタンをクリックして新しいシートを作成しましょう!
ここで作成したシートにお問い合わせを書き込んでいくことになります。

 

スクリーンショット 2015-10-19 19.49.11

 

シートの一番上の行がそのままお問い合わせの項目になります。
今回はrailsからnameとdetailという値でお問い合わせする人の名前と内容を受け取るようにしているので画像のように、左上からname,detailとしています。

スクリーンショット 2015-10-19 19.56.20

 

 

ここでspreadsheetのIDをめもしましょう!
urlのhttps://docs.google.com/spreadsheets/d/の後をメモです。(/edit…というのは必要ないです)
画像で選択している場所です!

スクリーンショット 2015-10-19 19.56.21

 

さぁここまでの手順で
・クライアントID
・クライアントシークレット
・リフレッシュトークン
・spreadsheetのIDが揃いました!

あとはrailsを修正するだけで終了です!

 

railsの設定

まず今回利用するgemを入れましょう!

その後は普通に投げ先と処理を書くだけです!

今回はajaxを使用して/contactsにpostで投げるとjsonを返すようにしたので修正したファイルと内容は以下になります。

test.js
・/postにフォームから取得した値(名前、詳細)を送る

config/routes.rb
・test.jsによって/postに投げられたデータをcontacts_controller.rbのspreadメソッドに処理を投げる

contacts_controller.rb
・クライアントID、クライアントシークレット、リフレッシュトークンを使用してgoogle spreadsheetアクセスし、名前と詳細を書き込む

こんな感じです。

test.js

routes.rb

contacts_controller.rb

うまく言っていれば/contactsにajaxで投げるとspreadsheetに書き込まれていると思います!

 

余談

いろんな記事を参考にさせていただいたんですが、client IDとclient secretの取得の際にredirect URLも取得できるらしいのですがgoogle の仕様が変わっていたのか出てきませんでした(´;ω;`)

いろいろ調べるとurlはurn:ietf:wg:oauth:2.0:oobで大丈夫らしいです!

refresh tokenとか何やってるかいまいちわかっていないのでご教授してくださる方がいらっしゃいましたらよろしくお願いいたします!

react-nativeチュートリアル2回目

スクリーンショット 2015-10-17 14.52.20

react-nativeのチュートリアル2回目です。
なかなか面白くなってきました。
とりあえず今回完成したのがこちら

スクリーンショット 2015-10-17 14.52.20

react-native使ってajaxでjson受け取ってレンダリングしてくれるところまで!

ちなみになぜ背景にSublime textを映してるかというと基本的に開発はプロジェクト内のindex.ios.jsというものをいじりながらやっていくため。
今のところ最初のビルド時以外にxcode触ってないです。
基本的にレイアウトもjsのハッシュの中身をいじって操作していくためにjs以外まだ触ってないです。
また、ビルドも最初の初回以外はしなくてもよく、シミュレータをリロードするだけで更新されます。
いちいちビルドするのを待たなくていいのでいいですね!!

ちなみにchromeのdevツールを使っても開発できるらしいんですけどまだわかってないです。。。
スクリーンショット 2015-10-17 15.00.41

とりあえず英語苦労し過ぎで全部入ってきてるわけじゃないので大変ですが頑張りますー。

react-native導入で早速つまづいた

スクリーンショット 2015-10-15 10.31.49

react-nativeの導入で少し躓きました。

公式のreact-native getting-started を参考にreact-nativeをインストールしていました。

react-nativeインストールしてxcodeで走らせた後に

スクリーンショット 2015-10-15 10.31.49

こんな感じでエラーに(´;ω;`)
teminalのエラー見ろってログに書いてあったので見ると。

こんなコード吐いてきます。

どうやらbrew, watchman, fluxのversionがおかしいらしく、brewとwatchmanのupdateで行けるとstackoverflowさんで言われてたので実行するも

こうなり、また調べると
「とりあえずbrew updateやっとけ」みたいな記事見つけたので実行!

updateの後、

こうするとやっとさっきのエラーがなくなった!
しかし、こんなエラーが、、、

スクリーンショット 2015-10-15 11.08.06

reactのrootパスでnpm startやってくれってでてるんで

すると、

え!!
なんで!!!

てかnodeコマンドもunlinkになっており、ぐぬぬってなったのでnodebrewから入れなおしました。

インストール後

で、パスを通す(僕はzsh使ってるんでzshに通す)

一応確認

これでreacti-nativeのコードをxcodeで実行すると成功!

スクリーンショット 2015-10-15 11.49.59

あーつかれた!!!!