サーバサイドなおじさんがSPAを趣味で初めて作ってみてわかった...
-
Upload
ken-muryoi -
Category
Software
-
view
642 -
download
5
Transcript of サーバサイドなおじさんがSPAを趣味で初めて作ってみてわかった...
サーバサイドなおじさんが SPAを趣味で初めて作ってみて わかった n のこと(仮)
2015/07/11 関西Ruby会議06
無量井 健(@muryoimpl)
https://www.flickr.com/photos/bongonian/8534960933/
ここに提供
自己紹介•無量井 健(むりょうい けん)
• 永和システムマネジメント 10ヶ月目
• Ruby関西, 関西Ruby会議04・05 etc
• :white_large_square: 改め :b::b::a:
サーバサイドなおじさんが SPAを趣味で初めて作って始めてみて
わかった n のこと(仮) ハマった n のこと
2015/07/11 関西Ruby会議06
無量井 健(@muryoimpl)
https://www.flickr.com/photos/bongonian/8534960933/
使った技術要素(server)Rails4.2 rails-api
jwt google-api-clientactive_model_serializers
pumahamlit
foremanbootstrap-sass poltergeist
使った技術要素(client)React react-router
webpackjsUri
reqwest
cjsxunderscore
react-draggable
https://www.flickr.com/photos/thomasletholsen/8719637939/
盛大にハマったり わかったりしたこと n 個を紹介します
1
とあるRubyistに 電車の中で
“SPAという単語を 使うとモヒカンが現れて
炎上しますよ”
((((;゚Д゚))))
https://www.flickr.com/photos/alvarez-tostado/363243449/
SPAという単語は 用法・要領を守って 使いましょう
2
使った技術要素(client)React react-router
webpackjsUri
reqwest
pumacjsxunderscore
使った技術要素 React• sprockets との共生を選択した(時間なくて)
• npm install react save-dev => package.json
• webpack で結合した js を//=require で固める
• loaders(coffeescriptの慣れでcjsx使用)
• webpack.config.js 書くだけでいけそう(安易)
• 実際foreman 実行だけで済むので楽だった
使った技術要素 webpack
• 理由はreact-jade用のloaderがすでにあったから
•でも、開発開始当時、依存関係で入る react のバージョンが古かったので、react-jadeは今回お見送り🙏
{ "name": "kpton", 中略 }, "dependencies": { "cjsx-loader": "^2.0.1", "coffee-loader": "^0.7.2", "coffee-script": "^1.9.2", "jsuri": "^1.3.1", "jsx-loader": "^0.13.2", "node-libs-browser": "^0.5.0", "react": "^0.13.3", "react-hot-loader": "^1.2.7", "react-router": "^0.13.3", "reqwest": "^1.1.6", "underscore": "^1.8.3", "webpack": "^1.9.7" } }
package.json
var webpack = require('webpack'); var path = require('path'); var assetsPath = path.join(__dirname, 'app', 'assets', 'client');
module.exports = { // the base path which will be used to resolve entry points context: __dirname, // the main entry point for our application's frontend js entry: { main: [ 'webpack/hot/only-dev-server', path.join(assetsPath, 'main.cjsx') ] },
output: { path: path.join(__dirname, 'app', 'assets', 'javascripts'), // for Rails Assets Pipeline filename: "[name]-bundle.js" }, - 中略 - resolve: { extensions: ['', '.js', '.jsx', 'cjsx', '.coffee'] },
module: { loaders: [ {test: /\.jsx$/, loaders: ['jsx-loader', 'react-hot']}, {test: /\.coffee$/, loaders: ['coffee']}, {test: /\.cjsx$/, loaders: ['coffee', 'cjsx']},
webpack.config.js
entry point なファイルを 指定する
上が配置場所 下が固めた後のファイル名
loaderの対象とする拡張子
どの拡張子にどのloaderを 割り当てるか
entry point な js
React = require 'react' Router = require 'react-router' routes = require './config/routes.cjsx'
Router.run routes, Router.HistoryLocation, (Handler) -> React.render(<Handler/>, document.body)
app/assets/client/main.js
ここでRailsのお決まり!!! %html{lang: :ja} %head %meta… 中略 %title KPT = javascript_include_tag ‘client' %body
app/views/layouts/application.html.haml
ここに main.js 等React 使った js を固めている
全く動かない❗
https://www.flickr.com/photos/alvarez-tostado/363243449/
どうも main.jsの 手前に対象のDOMが
ないと 動かないらしい…
https://www.flickr.com/photos/alvarez-tostado/363243449/
サンプルどおりの位置に配置する
!!! %html{lang: :ja} %head %meta… 中略 %title KPT %body = javascript_include_tag ‘client'
app/views/layouts/application.html.haml
ここに配置すると問題なく 動いた
http://facebook.github.io/react/docs/tutorial.html
Reactのサンプル
http://facebook.github.io/react/docs/tutorial.html
Reactのサンプル
位置関係、大事であった…
3
使った技術要素(server)Rails4 rails-api
jwt google-api-clientactive_model_serializers
pumahamlit
foremanbootstrap-sass poltergeist
使った技術要素 poltergeist
• acceptance test を turnip でやろう
• 折角なので、wercker で CI してみよう
• thecaddy/node-ruby の boxを使ってみる
• ローカルで動いたし、おっしゃ push…
謎のエラーを吐く
Capybara::Poltergeist::JavascriptError: One or more errors were raised in the Javascript code on the page. If you don't care about these errors, you can ignore them by setting js_errors: false in your Poltergeist configuration (see documentation for details).
TypeError: 'undefined' is not a function ( evaluating 'ReactElementValidator.createElement.bind( null, type )') TypeError: 'undefined' is not a function ( evaluating 'ReactElementValidator.createElement.bind( null, type )')
ちょっと調べてみると poltergeist 1.x系 の問題らしい
https://www.flickr.com/photos/alvarez-tostado/363243449/
https://www.flickr.com/photos/alvarez-tostado/363243449/
• https://github.com/teampoltergeist/poltergeist/issues/292
• 確かにローカルのphantomjsは 2.0.0 だった
• phantomjs2.0に対応していない環境もある
• facebook/react がpolyfillを用意しているらしい
• https://github.com/facebook/react/issues/945#issuecomment-39694748
phantomjs 1.9系は bind に対応していない
ただ今認証周りの スタブが2回目実行時 に無反応になる問題に
直面中 (原因調査中)
https://www.flickr.com/photos/alvarez-tostado/363243449/
4
使った技術要素(server)Rails4 rails-api
jwt google-api-clientactive_model_serializers
pumahamlit
foremanbootstrap-sass poltergeist
痛恨のコピペミス…
# 当初 rails-api を使っていなかったが導入してみた。 # API 用の親クラスを作成しようとした class ApiController < ActionController::API
# コピペをミスってActionController::APIに… include ActionController::Serialization end
痛恨のコピペミス…
class BoardsController < ApiController
# client 側の js からの request があったので # 子クラスで render json を呼び出す def index render json: @current_user.boards end end
痛恨のコピペミス…SystemStackError (stack level too deep): app/controllers/api_controller.rb:8:in `current_user' app/controllers/api_controller.rb:8:in `current_user' app/controllers/api_controller.rb:8:in `current_user' app/controllers/api_controller.rb:8:in `current_user' app/controllers/api_controller.rb:8:in `current_user' app/controllers/api_controller.rb:8:in `current_user' app/controllers/api_controller.rb:8:in `current_user' app/controllers/api_controller.rb:8:in `current_user' app/controllers/api_controller.rb:8:in `current_user' app/controllers/api_controller.rb:8:in `current_user' app/controllers/api_controller.rb:8:in `current_user' app/controllers/api_controller.rb:8:in `current_user' app/controllers/api_controller.rb:8:in `current_user' app/controllers/api_controller.rb:8:in `current_user'
これが 228 行続く……
マシンのメモリ8G 食いきって
カーソルが挙動不審 になりました💦
https://www.flickr.com/photos/alvarez-tostado/363243449/
OOM killer 発動! で
finish👼https://www.flickr.com/photos/alvarez-tostado/363243449/
5
使った技術要素(client)React react-router
webpackjsUri
reqwest
pumacjsxunderscore
React 使ってみた所感• getInitialState, componentWillMount, componentDidMount などの役割は名前から イメージつきやすい感じする。FWレベル。
• render 内に、最上位のタグが1つしか書けないのが私は意外にひっかかった。component != partial
• やはり view とロジックは分けて書きたくなるのと、htmlの閉じタグを書きたくないでござる… react-jadeは開発 始めたときに対応している react が古くて諦めた。今は?
top level は1つのみReact = require “react” module.exports = React.createClass render: -> ( <div className=“nav”> <p>あいうえおっすおっす</p> </div> <form className=“inline-form”> </form> )
top level は1つのみReact = require “react” module.exports = React.createClass render: -> ( <div className=“nav”> <p>あいうえおっすおっす</p> </div> <form className=“inline-form”> </form> )
先に書かれているtop level のtagが render されない…
partial とは違う…
あと
わかりにくい エラー・警告が 多い(気がする…)
ReactMount: Root element has been removed from its original container. New container: null が大量に並ぶ
react consoleみると、 同じ要素が2つできてる…
https://github.com/rackt/react-router/issues/600#issuecomment-73364948
同じだ❗https://www.flickr.com/photos/alvarez-tostado/363243449/
※平日 深夜4時の出来事である…
https://github.com/rackt/react-router/issues/600#issuecomment-74795259
https://www.flickr.com/photos/alvarez-tostado/363243449/
Reactがrenderする前の関数で transitionすると 発生するみたい😱
https://www.flickr.com/photos/alvarez-tostado/363243449/
transitionTo 辞めると
確かに黙った😷
https://www.flickr.com/photos/thomasletholsen/8719637939/
まとめ
https://www.flickr.com/photos/thomasletholsen/8719637939/
まとめ•n番煎じでした。
•ハマってみないと穴の深さはわからない
•まだ抜け出せてない穴がある
•涙の数だけ強くなれるよ…
https://www.flickr.com/photos/thomasletholsen/8719637939/
無駄にハマらずに楽しく
開発できる人が増えると
いいなぁ
EnjoyProgramming!