Pureを使い会社のホームページをレスポンシブウェブデザインにした

今更という感じもありますが、私の会社のホームページ をレスポンシブウェブデザインに対応しました。

f:id:yuum3:20160608143213p:plain

レスポンシブ CSS フレームワークの選定

レスポンシブウェブデザインにするのには、何らかの レスポンシブ CSS フレームワーク を使うのが早道です、 ネットを検索すると、たくさんの レスポンシブ CSS フレームワーク がありま、有名どころは Bootstrap でしょうか。

会社のホームページは複雑なフォーム等はないので、

  • CSSのサイズが小さい
  • JQueryやJSを前提としてない
  • シンプル

という条件で調べてみましたところ、 Kube, Skeleton, Pure などが候補になりました。

Kube は以前、「お問い合わせフォーム」で使っていたのですが、ホームページに Version 5.0 があるのに GitHubは Version 4.03 だったので怪しいと思い止めました。Skeletonはシンプルで良さそうでしたが、使用例がなくGitHubも2年ほど更新されてないので止めました。ということで Pure になりました。

Pure を使った感想

  • シンプルで良かったです
  • レイアウトのサンプルが ホームページのLayoutsにあり助かりました。
  • ただし、スマフォ画面でメニューを表示する JSのコードが YUI を使っていて戸惑いましたが、無事に素のJSで書けました。
    • if (document.querySelector) {} があるのは古いIEで表示した際にエラーにならないようにするためです。
if (document.querySelector) {
  document.querySelector('.moble-menu-button').addEventListener('click', function() {
    document.querySelector('#nav').classList.toggle('active');
  });
}
   ...

共通+スマフォ用CSS

   ...

@media (min-width: 40em) {
   ...

  タブレット、PC用CSS 

   ...

}

@media (min-width: 60em) {

   ...

  PC用CSS 

   ...

}

React Nativeアプリを別のMacで動かそうとしてハマった メモ

あるセミナー向けに作った、React Nativeアプリを別のMacで git clone して実行しようとしたら 下の画像のエラーが出て解決まで時間がかったのでメモしておきます。

f:id:yuum3:20160523142141p:plain

React Native 開発環境の構築

React NativeのGetting Startedにある手順で

$ npm install -g react-native-cli
$ brew install watchman
$ brew install flow

インストールされた react-nativeコマンドでプロジェクトを作成

$ react-native init react_native

ボタンやTabBarのアイコンが使いたかったので、以下をインストール。 react-native-vector-icons をプロジェクトに設定するにのrnpm (React Native Package Manager) を利用

$ npm install --save react-native-button
# npm install --save react-native-vector-icons 

$ npm install rnpm -g
$ rnpm link

ここで react-native run-ios を実行すると、iOS用コードのコンパイルや別ウインドーに React packager が起動され、しばらくすると iOS Simulator が起動されるます。 後は index.ios.js を修正し、 iOS Simulator で⌘+R でリロードする事で開発が進められます。完成したものを GitHubに置きました。

Macでの作業

別のMac で git clone し

$ npm install -g react-native-cli
$ brew install watchman
$ brew install flow

$ nam install
$ react-native run-ios

iOS Simulator が起動されるのですが、上のような赤い画面が表示されました

画面に書かれている issue を眺め

  1. watchman watch-del-all
  2. rm -rf node_modules && nam install
  3. rm -rf $TMPDIR/react-packager-*

を実行しても同じ・・・・

落ち着いてターミナルを見ると

npm WARN react-native@0.26.1 requires a peer of react@15.0.2 but none was installed.

通常この手のワーニングが出っていても動く事が多いのですが、調べてみると react@15.1.0 がインストールされていました。そこで

$ npm uninstall --save react@15.1.0
$  npm install --save react@15.0.2

したところ、ワーニングは消え、

iOS Simulator で無事にアプリが起動されました ^^)/

このサンプルアプリは 私のGitHub react-native ブランチにあります。

React.js + Photon.css + Webpack で Electronのサンプルアプリを作ってみた

React.js + Photon.css + Webpack で Electronのサンプルアプリを作ってた時のメモです。

f:id:yuum3:20160523105315p:plain

開発環境

まず、以前書いた サーバーサイドプログラマーのためのReact.js 入門 2. 開発環境の構築の続き のように React.js の開発が出来る環境を準備します。

追加するのは electron-prebuiltMac OS X風なUIが作れる Photon を追加するのみです。

npm install photon で入る Photon は違うものなので注意して下さい。

  • インストール
$ npm install --save react react-dom
$ npm install --save-dev babel-loader babel-preset-es2015 babel-preset-react
$ npm install --save-dev eslint eslint-loader eslint-plugin-react babel
$ npm install --save-dev css-loader style-loader
$ npm install --save isomorphic-fetch
$ npm install -g webpack

$ npm install --save-dev electron-prebuilt
$ npm install --save https://github.com/connors/photon
$ npm install --save-dev url-loader file-loader
  • webpack.config.js は
module.exports = {
  entry: {
    "app": "./src/js/index.js",
  },
  output: {
    path: './build/',
    filename: "[name].js"
  },
  module: {
    preLoaders: [{
      test: /\.js$/,
      exclude: /node_modules/,
      loader: "eslint-loader"
    }],
    loaders: [{
      test: /\.css$/,
      loader: "style!css"
    }, {
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader'
    }, {
      test: /\.(eot|woff|woff2|ttf|svg|png|jpg)$/,
      loader: 'url-loader?limit=30000&name=[name]-[hash].[ext]'
    }]
  },
  resolve: {
    extensions: ['', '.js', '.css']
  },
  eslint: {
    configFile: './.eslintrc'
  }
};
  • package.js に以下の設定を追加(変更)します
  "scripts": {
    "start": "electron main.js"
  },
  • main.js は ElectronのQuick Start からコピーし windowサイズを変更します

  • index.html は photon 用の class を指定しましたが、良くある React.js 用の index.html です。

<!DOCTYPE html>
<html>
<head>
  <title>じゃんけん ポン!</title>
  <meta charset="utf-8">
</head>
<body>
 <div id="example" class=window"></div>
  <script type="text/javascript" src="build/app.js" charset="utf-8"></script>
</body>
</html>
  • src/js/index.js は通常の React.js のコードです photonを使うために import 'photon/dist/css/photon.css' を追加したくらいです。

開発コマンド

Electron の開発は electron コマンドを起動する アプリのウィンドウが起動され、リロード(⌘+R) でコードが再ロードされるので開発できます。ただし electron コマンド は動き続けるので バックグラウンドで起動しました。

$ nam start &
$ webpack -d -w

今回つくったサンプルアプリ

React.js紹介セミナー 用に作ったサンプルコードは 私のGitHub を clone し electron ブランチです。 他のブランチには React Native 等のコードもあります ^^)

楽々GitLabサーバー作成手順

教育の仕事でGitLab(プライベートでpull requestなどが出せる安いサービス)が必要になり、サーバーを立ち上げました。以前は自社のコードもGitLabで管理していたのですが、今は 改造版Ginatra を使っているので、教育の期間のみGitLab用のサーバーを立ち上げる事にしました。

f:id:yuum3:20160516151328p:plain

GitLabのインストール

以前はGitLabのインストールはたいへんでしたが、今は apt や yum でインストールできます。 IaaSクラウドサービスでサーバーを準備し、インストールすれば簡単に完了です。 RDB(PostgreSQL), nginx 等もインストールされます。

私は Ubuntu が慣れているので、Ubuntu 14.04 にインストールしましました。

$ sudo apt-get update
$ sudo apt-get -y dost-upgrade

$ sudo apt-get install curl openssh-server ca-certificates postfix
$ curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
$ sudo apt-get install gitlab-ce
$ sudo gitlab-ctl reconfigure

SSL化しよう

この手のサーバーは今時 https で運用しますよね。 ということで無料でつかえる Let’s Encrypt を使う事にしました。有効期間は3ヶ月ですが教育期間は休みを含め 2ヶ月なので 更新作業も不要ですね ^^)

作業手順は Qiita にありました。ほぼこのままです。

$ git clone https://github.com/letsencrypt/letsencrypt.git
$ cd lets encrypt
$ ./letsencrypt-auto  --help      # installが行われる
$ sudo vi /etc/gitlab/gitlab.rb
---- custom_gitlab_server_config を変更
nginx['custom_gitlab_server_config'] = "include /etc/letsencrypt/nginx.conf;"
---

$ sudo mkdir /etc/letsencrypt
$ sudo vi /etc/letsencrypt/nginx.conf
--- 以下を追加
location ^~ /.well-known {
    alias /var/letsencrypt/.well-known;
}
---

$ sudo mkdir /var/letsencrypt
$ sudo gitlab-ctl reconfigure
$ ./letsencrypt-auto certonly --webroot --webroot-path /var/letsencrypt -d gitlab.ey-office.net
$ sudo vi /etc/gitlab/gitlab.rb
--- 以下の行を変更
external_url 'https://gitlab.ey-office.net'    # サーバーのURLを指定
nginx['redirect_http_to_https'] = true
nginx['ssl_certificate'] = "/etc/letsencrypt/live/gitlab.ey-office.net/fullchain.pem"
nginx['ssl_certificate_key'] = "/etc/letsencrypt/live/gitlab.ey-office.net/privkey.pem"
---

$ sudo gitlab-ctl reconfigure

デモなどで使えるGitコミットを簡単にresetし切替えるツールを作りました

私は仕事がら、人前でコード作成のデモを行う事がよくあります。その場でバリバリとライブ・コーデイング出来るとカッコ良いですが、間違えたり、コードを書くことに気を取られ説明がおろそかになったりすることも起こりがちです。

f:id:yuum3:20160506094523p:plain

そこで説明のストーリに沿ってコード作成の過程をgitにコミットしておき、コマンドで簡単に git reset を行い、その時点でのコードを説明したり、動かしたりできるツールを作りました。

上の画像のように、このコマンドを起動するとgit logが表示され、現在のコミットが赤い色で表示されます、ここで n キーを押すと次のコミットに git reset できます。また p キーで前のコミットに git reset したり、カーソル上下キーでコミットを移動して RETURNキーでそこにgit reset できます。

このコマンドを実行すると git reset されてしまうので、 -c オプション指定で 予めファイルに全git logを書いておきます。

rubyで作ってあります、 gem 等のインストールは不要です。

#!/usr/bin/env ruby

require 'io/console'

GIT_LIST_PATH = "#{ENV['HOME']}/tmp/git-demo.lst"

RED = "\e[31m"
YELLOW = "\e[33m"
BLACK = "\e[30m"
FIN = "\e[0m"

UP = "\e[A"
DOWN = "\e[B"
RETURN = "\r"


def show_log_item(item, current)
  if current
    print "#{RED}#{item[0]} #{BLACK}#{item[1]}#{FIN}#{RETURN}"
  else
    print "#{YELLOW}#{item[0]} #{BLACK}#{item[1]}#{FIN}#{RETURN}"
  end
end

def show_git_log(log, current_index)
  log.each_with_index do |item, ix|
    show_log_item(item, ix == current_index)
    puts
  end
end

def get_current_hash
  IO.read("|git log --pretty=format:'%h' -1")
end

def find_current_hash(log, current_hash)
  log.find_index {|item| item[0] == current_hash}
end

def wait_key
  key = STDIN.getch
  if key == "\e" && STDIN.getch == "["
    case STDIN.getch
    when "A" then ""
    when "B" then ""
    else ""
    end
  else
    key
  end
end

def cursor_up
  print UP
  STDOUT.flush
end

def cursor_down
  print DOWN
  STDOUT.flush
end

def set_cursor(log, current_index)
  (log.size - current_index).times { cursor_up }
end

def reset_cursor(log, current_index)
 (log.size - current_index).times { cursor_down }
end

def move_current_postion(log, index, delta)
  show_log_item(log[index], false)

  if delta > 0
    if index < log.size - 1
      cursor_down
      index += 1
    end
  else
    if index > 0
      cursor_up
      index -= 1
    end
  end

  show_log_item(log[index], true)
  index
end

def get_git_log
  IO.readlines(GIT_LIST_PATH).map {|s| s.scan(/^(\w+) (.*)\n?/)[0]}
end

def put_git_log
  system "git log --pretty=format:'%h %s' > #{GIT_LIST_PATH}"
end

def git_reset_hard(log, index)
  system "git reset --hard #{log[index][0]}"
end

def main
  log = get_git_log
  current_index = find_current_hash(log, get_current_hash)
  show_git_log(log, current_index)
  set_cursor(log, current_index)
  do_reset = false

  while true
    case wait_key
    when 'n'
      current_index = move_current_postion(log, current_index,  - 1)
      do_reset = true
      break
    when 'p'
      current_index = move_current_postion(log, current_index,  + 1)
      do_reset = true
      break
    when "\r", "\n"
      do_reset = true
      break
    when "\C-c", "q"
      break
    when ""
      current_index = move_current_postion(log, current_index,  - 1)
    when ""
      current_index = move_current_postion(log, current_index,  + 1)
    end
  end
  reset_cursor(log, current_index)
  git_reset_hard(log, current_index)  if do_reset

end

if ARGV.size > 0
  if ARGV[0] == "-c"
    put_git_log
    puts "#{GIT_LIST_PATH} created."
  else
    puts "#{$0} -c"
    puts "     or  "
    puts "#{$0} "
    puts "  n: git reset --hard Next commit"
    puts "  p: git reset --hard Pervious commit"
    puts "  ↑ ↓: seek commit"
    puts "  RETURN: git reset --hard Current commit"
    puts "  q: quit"
  end
else
  main
end

Gistにも置きました

React.jsの紹介的なセミナーを行います

React.jsの開発も終わり、得られた知見をもとに 5月23日 に React.jsの紹介的な無料セミナーを行います。

atnd.org

内容は、React.js がなぜ良いのか、開発環境について、簡単なアプリをライブで作成・・・ などの React.jsの紹介的な内容になります。

会場は人材系の会社で、終了後に軽食の出る懇親会をスポンサーしてもらっています。人材系の会社ですがブラックな会社ではないので安心して御参加ください。

React.js の仕事 ほぼ完了しました!

ここ数ヶ月、久々に詰めて行っていた Recat.js の仕事がほぼ終わりました !!

f:id:yuum3:20160204101138p:plain

仕事の詳細は書けませんが。 既存のjQueryベースのWebアプリがメンテナンス不可能に近くなっているので Recat.js に置き換えました。

既存のアプリは

  • Backend は Ruby on Rails
  • jQueryで作られてた Frontend の JS は約 14K 行 + テンプレート 4K 行
  • アプリは大きく3つに別れるが、共有部分無しでコピーペーストで作られている

今回の仕事

  • Backend は 落ちていたテストを修正したくらい
  • End to End テストが無かったので書いた
    • Turnip(RSpec, Gherkin) + Capybara + Poltergeist + Phantom.js
    • Featureファイル 2K行、 steps 1.2K行
    • 開発期間 約1ヶ月
  • jQuery から Reactへの移行

感想など

  • 既存アプリは構成など初期設計は良く出来ている感じで実はそれほど悪いものではないが、実装はコピーぺの山だし無意味な部分も多数あった
  • jQueryベースのものはページの変更後の再表示がかなりの部分で全書き換えになっていたが、 React版は Reactのおかげで最小限の書き換えになり高速化された!
  • End to End テストを書くことでFrontendの動き、実装に関する理解が深まりました
  • React.js は評判通りコードが長くなる、しかし構造が判りやすくメンテナンスしやすいのではと思える
  • アプリの行っている事が比較的シンプルで Flux/Redux 等は コード量が増える割に、メリットが少なそうだと思えたので採用しなかった
  • さすがに1万行くらいになるとWebpack(ESLint+Babel)に時間がかかるように成るがなんとか使えるレベルではあった
  • Reactのコードは長くなるが難しいコードを書いているわけではないので CoC(convention over configuration)なライブラリー/トランスレータが出たら良いな・・・
  • 今回得られた知見を元に React.js の教育も開始したいなと思います。そのために React.jsの入門記事を書きました。
  • End to End テストのおかげで幾つかのバグが発見できましたが、それ以上に修正した後でテストが通れば「まあ酷いバグはないさ〜!」という安心感が良いですね ^^)