今更ながらWindows環境でgulpを試してみた

cssやjsのminifyをするために今更ながらgulpを試してみたのでメモ

目標

gulpを使ってcssとjsをminifyする

環境

Windows10 Pro 64bit

順番

  • node.jsのインストール
  • npmで必要パッケージのインストール
    • gulp
    • gulp-clean-css
    • gulp-uglify
    • gulp-strip-debug
    • gulp-sourcemap
  • gulpfile.jsを書く

node.jsのインストール

npmを使うにはnode.jsをインストール必要があるのでダウンロード | Node.jsからWindows Installer版をダウンロードしてインストールする
ダウンロードした .msi ファイルをダブルクリックで開いて Next 連打で問題なかった

npmで必要パッケージのインストール

gulpでcssとjsをminifyするのに必要なパッケージをインストールしていく
gulp自体はグローバルにインストールしてそれ以外はプロジェクトの中にインストールする方針
グローバルにインストールするには -g をつけて npm install する
プロジェクトの中にインストールするにはプロジェクトのトップディレクトリで npm install を実行する

下準備として package.json を作る必要があるので、プロジェクトのディレクトリに移動して npm init する

cd project_dir
npm init
#色々質問されるがそのままエンター押していけば大丈夫
gulp
npm install -g gulp
gulp-clean-css

cssをminify化するためのパッケージ

npm install --save-dev gulp-clean-css
gulp-uglify

jsをminify化するためのパッケージ

npm install --save-dev gulp-uglify
gulp-strip-debug

console.logを削除するパッケージ

npm install --save-dev gulp-strip-debug
gulp-sourcemap

chromeなどの開発環境でminify化されたものを見やするためにmapファイルを作るパッケージ

npm install --save-dev gulp-sourcemap

gulpfile.jsを書く

gulpコマンドでminify化するための処理を書く
書く場所はプロジェクトのトップに gulpfie.js というファイルを作ってそこに書く

ディレクトリ構成は編集する元ファイルを source/js source/css に置いておき、minify化したファイルを dist/js dist/css に置くようにする

// 使用するパッケージを require で読み込む
var gulp = require('gulp');
var uglify = require('gulp-uglify');
var cleanCSS = require('gulp-clean-css');
var sourcemaps = require("gulp-sourcemaps");
var stripDebug = require("gulp-strip-debug");

// js圧縮
gulp.task('minify-js', function() {
    return gulp.src("source/js/*.js")
        .pipe(stripDebug()) // console.logを削除
        .pipe(sourcemaps.init()) // mapファイル作成のための初期化処理
        .pipe(uglify()) // jsのminify化
        .pipe(sourcemaps.write('./')) // mapファイルの作成
        .pipe(gulp.dest('dist/js/')); // 出来たファイルをコピーする
});

// css圧縮
gulp.task('minify-css', function() {
    return gulp.src("source/css/*.css")
        .pipe(sourcemaps.init()) // mapファイル作成のための初期化処理
        .pipe(cleanCSS()) // cssのminify化
        .pipe(sourcemaps.write('./')) // mapファイルの作成
        .pipe(gulp.dest('dist/css/')); // 出来たファイルをコピーする
});

// デフォルトの処理
gulp.task('default',['minify-css', 'minify-js']);

gulp.task('タスク名', function(){〜〜〜}) のタスク名の部分は gulp コマンドの引数として実行時に渡す文字列を入れておく
defaultは引数なしで実行した場合に処理される、上記ではcssとjsのminify化のタスク名を指定してデフォルトでは全てのminify化を行うようにしている

#jsのminifyを行うとき
gulp minify-js

#cssのminifyを行うとき
gulp minify-css

#デフォルト jsとcssのminifyを行う
gulp

備考

触ってみるまではnode.js入れたり、npmで色々パッケージを入れたり、gulpfile.jsを書いたりと手順が多く見えて面倒に感じていたけれど、順番に一つずつやってみるとそれほど大変そうではなかった
ほぼ参考ページのコピペで済ませたというのも最初の導入としては良かった

上記のminify化以外にもgulpを使って以下のようなことも出来るようだ

  • HTMLのvalidation
  • JSのvalidation
  • CSSやJSを一つのファイルにまとめる
  • gulp.watch を使って監視対象のファイルが更新されたら処理を実行する
    • ブラウザのリロードを走らせる
    • 更新されたファイルをサーバにアップする

ざっと調べているうちに最近ではgulpやGruntに頼らずにnode-scriptsでやってしまおうという動きもあるようだが、調べた中では自分としてはgulpの方がとりあえずの障壁が低かった

Windows でアイコンオーバーレイが表示されなくなったので調べた

WindowsTortoiseSVNを使っているんだけども、アイコンオーバーレイ(更新されたとか、変更されていないとかの状態がアイコンに付与される機能)が表示されなくなったので、もろもろ調べた

オーバーレイアイコンが表示されなくなった原因はなんとクラウドサービスだった | どらまちっくー…ばーすとぉ!

上記ページを参考にShellExViewをダウンロードして、使っていなさそうなIcon Overlay Handlerをオフにした

しかし ShellExView のダウンロードリンクがページの最下部にあったので、ダウンロードするのに迷ってしまった
今回は使っているOSが64bitだったのでDownload ShellExView for x64をダウンロードした
言語ファイルもあるので、Japaneseをダウンロードして、解答したものをShellExViewと同じディレクトリに入れれば日本語化された

PHPで do switch while という書き方が出来るのを知った

とある調べものをしているときに見つけた記述方法

へー、ってなったのでメモ

<?php
// 動作確認用のコードなので、適当

$running = true;
$hoge = 1;
do switch($hoge){
    case 1:
        echo '[' . $hoge . ']' . PHP_EOL;
        $hoge++;
        break;

    case 2:
        echo '[' . $hoge . ']' . PHP_EOL;
        $hoge++;
        break;

    case 3:
        echo '[' . $hoge . ']' . PHP_EOL;
        $hoge++;
        break;

    default:
        echo '[' . $hoge . ']' . PHP_EOL;
        $running = false;
        break;
}while($running);

CURLOPT_FILEでHTTPレスポンスをファイルに直接書き込んでいくサンプル - Qiita

スマートフォン向けサイトで横に分割レイアウト

スマートフォン向けのサイトで「横に3つ並べて配置」みたいなのをfloatでやると端末のピクセル数によって微妙な隙間が出来たりしていたので、調べた

スマートフォンサイト制作にdisplay:tableとdisplay:table-cellが便利! | Kana-Lier カナリエ

やりかたとしては display:table でくるんで、中身を display:table-cell するだけだった

メモ用に上記サイトからソースを引用

HTML部分

<nav class="g_nav">
	<ul>
		<li><a href="#">HOME</a></li>
		<li><a href="#">BLOG</a></li>
		<li><a href="#">CONTACT</a></li>
	</ul>
</nav>

CSS部分

.g_nav ul{
	display:table;
	table-layout: fixed;
	width:100%;
}
.g_nav li{
	display:table-cell;
	text-align:center;
}
.g_nav li a{
	display:block;
}

PHPの無名関数とeAccelerator の相性にに関して

以前以下のようなポストをした

spl_autoload_registerで無名関数を使ったときのエラーが出て解決できない - にっき

思い立って再調査

環境

  • PHP5.4

現象

cliでは無名関数が使えるのに、WEB経由だと無名関数がNULLになってしまう

同等の環境を手元に作ってWEB経由で検証したら、普通に無名関数が使えたので環境的な差分をチェック

環境的な違いはeAcceleratorが入っているか、いないかの違い

んで

eAcceleratorを.htaccess使ってオフにしてみた

php_flag eaccelerator.enable 0
php_flag eaccelerator.optimizer 0

そしたらビンゴ!

WEB経由でも無名関数が使えるようになった


予想ではあるけど、eAcceleratorのキャッシュが無名関数に非対応とかそんなんじゃないのかな?

設定でなんとかなるのかもしれないし、その他の方法で大丈夫になるかもしれないし

原因はつきとめたけど、解決方法はこれから探します


ちなみにPHPマニュアルの無名関数のところにコメントついてた・・・orz
PHP: 無名関数 - Manual

eAcceleratorのgithubのissuesにも載ってた
eAccelerator not compatible with anonymous function/closure under php 5.4.6 · Issue #12 · eaccelerator/eaccelerator · GitHub
Dose eaccelerator latest version support PHP5 CLOSURE FEATURES? · Issue #36 · eaccelerator/eaccelerator · GitHub

っていうかeAcceleratorは推奨しないプロジェクトですよってPullRequestも来てるし・・・orz
Explain that eAccelerator is a deprecated project by mattab · Pull Request #44 · eaccelerator/eaccelerator · GitHub

APCを検討だな

jQueryのAjax通信success時に戻り値を返す方法

jQueryをつかってAjax通信して、その結果を関数の外に返したい場合の方法

  • asyncをfalseにする

Ajax通信は非同期通信なので、通常は呼び出しを行ってsuccessの中で処理を行う。
Ajax通信を関数の中に入れて、その結果を関数の外でで受け取りたい場合は非同期通信をオフにして、通信が完了するまで待ってからreturnすれば大丈夫だった。

return_value = hoge();

alert(return_value);

function hoge(){
	var url	= '/hoge';
	var return_value;
	$.ajax({
		url:url,
		async: false,		// asyncをfalseにすることで、通信が終わるまで処理が待たれる
		success: function(msg, status){
			return_value
		},
		error: function(XMLHttpRequest, textStatus, errorThrown){
		}
	});
	return return_value;
}

ただ、この方法だとレスポンスが著しく悪い場合には処理がとまったような感じになりそう。

ajaxSuccessを使ってコールバックを登録するような感じがいいのだろうか?
ajaxSuccess(handler) - jQuery API 1.4.4 日本語リファレンス - StackTrace
jQuery リファレンス:ajaxSuccess

PHP の crypt で Blowfish を使う

PHPでパスワードをDBとかに格納する際にハッシュ化するのは常識として、その場合のハッシュ化をどうするか

5.5以上ではpassword_hashという関数があるので、それを使えばいいとして、それ以前のバージョンでの場合

PHP: crypt - Manual
PHP: パスワードのハッシュ - Manual

マニュアルを見てわかりにくかったので自分用メモ

CRYPT_BLOWFISH - Blowfish ハッシュ。salt の形式は、 "$2a$" か "$2x$" あるいは "$2y$"、2 桁のコストパラメータ、"$"、そして文字 "./0-9A-Za-z" からなる 22 文字となります。 この範囲外の文字を salt に使うと、crypt() は長さゼロの文字列を返します。 2 桁のコストパラメータは反復回数の 2 を底とする対数で、 これは Blowfish ベースのハッシュアルゴリズムで使います。 この値は 04 から 31 までの範囲でなければならず、 それ以外の値の場合は crypt() は失敗します。 5.3.7 までのバージョンの PHP では、salt のプレフィックスとして "$2a$" だけしか使えませんでした。PHP 5.3.7 で新たなプレフィックスが導入され、 Blowfish の実装にあったセキュリティ上の弱点に対応しました。 セキュリティ修正の対応の詳細については ≫ この文書 を参照ください。 簡単にまとめると、PHP 5.3.7 以降しか使わないのなら "$2a$" ではなく "$2y$" を使うべきだということです。

crypt関数のサンプルを見ると下記のような感じになっている

<?php
$hashed_password = crypt('mypassword'); // saltを自動的に生成させます

/* 異なったハッシュアルゴリズムが使用された際の問題を避けるために
   crypt()の結果全体をパスワード比較用のsaltとして渡す必要があります。
   (上記のように標準DESに基づくパスワードハッシュは2文字のsaltを使用します
   が、MD5に基づくハッシュは12文字のsaltを使用します) */
if (crypt($user_input, $hashed_password) == $hashed_password) {
   echo "Password verified!";
}
?>

Blowfish用に若干書き換え

<?php

$password = 'mypassword';

$hashed_password = crypt($password, '$2y$04$abcdefghijklmnopqrstuv');

$user_input = 'mypassword';

if(crypt($user_input, $hashed_password)==$hashed_password){
	echo 'Password verified!' . PHP_EOL;
}

var_dump(
	$hashed_password,
	crypt($user_input, $hashed_password)
);

上記の実行結果

Password verified!
string(60) "$2y$04$abcdefghijklmnopqrstuu9oZQP0E7UMk4NbKn6RLt8mFl9OFuldW"	# $hashed_passwordの中身
string(60) "$2y$04$abcdefghijklmnopqrstuu9oZQP0E7UMk4NbKn6RLt8mFl9OFuldW"	# crypt($user_input, $hashed_password) の中身

crypt関数の第2引数にハッシュ化した後の値を渡して、それとハッシュ化したパスワードを比較してて???ってなったんだけど
なんてことはないcrypt関数の第2引数はsaltで必要な部分までしか参照されないのであった

ちなみにマニュアルには色々書いてあって、簡単には内容把握しづらいんだけど、用はsaltで渡された値の最初の部分を元にどのアルゴリズムを使用するかが判別されてます。

Blowfishを使いたい場合は下記のような29桁のsaltを使うことで対応できる

$[プレフィックス]$[反復回数]$[22桁のランダム文字列を"0-9a-zA-Z"で指定]

$salt = '$2y$04$abcdefghijklmnopqrstuv';
  • 反復回数
    • Blowfishアルゴリズムで使う反復回数
    • 04〜31までの値で指定できる
    • 数が大きければ複雑にハッシュ化されるが、その分時間もかかる
  • ランダム文字列部分
    • 0-9a-zA-Z の文字で構成された22桁の文字列

22桁の部分は共有しないで、ユーザー個別に生成して保持しておいたほうがなにかとよろしいのかな?

てことで、自分用のメモ

Composer で CakePHP をセットアップしたら超絶楽だったのでメモ

CakePHPでなんか作ってみようと思って、前々から気になっていたComposerを使ってインストールしてみることに

@yando さんの書いた以下の記事を元に作業してみた
http://www.engineyard.co.jp/blog/2013/install-cakephp-on-composer/
基本的には上の記事を見れば全部書いてあるのですが、自分用のメモってことで

まずはComposerのインストール

アプリを置くルートディレクトリに行って以下を事項

$ curl -s http://getcomposer.org/installer | php

composer.pharがダウンロードされます

composer.jsonを作る

composer.json に以下を記述する

{
    "name": "status-site",
    "repositories": [
        {
            "type": "pear",
            "url": "http://pear.cakephp.org"
        }
    ],
    "require": {
        "pear-cakephp/cakephp": "2.4.3"
    },
    "config": {
        "vendor-dir": "Vendor/"
    }
}

CakePHPの最新バージョンが2.4.3らしいのでバージョン指定を2.4.3に変更してみた

Composerを使ってCakePHPをinstall

$ ./composer.phar install

色々メッセージが出てきてVendorディレクトリ内にCakePHPが設置される

これで、もうCakePHPが使える状態になってしまった

あとはappをbakeしてappを作る

$ ./Vendor/pear-pear.cakephp.org/CakePHP/bin/cake bake --app app

CakePHPに色々質問されるので、質問に答えていけばappディレクトリができてアプリのベースが出来てしまう

あとは出来たappディレクトリ内のwebrootをDocumentRootに設定して、ブラウザからアクセスするだけでおっけー

つまり

  • Composer使ってインストールすると楽チン
  • bakeすっげー楽チン

ということで、みんなもComposerとかbakeとか使って楽すると良いよって話でした

さーて、「CakePHP2 実践入門」買ってくるかー

新しくシステムを作るにあたって

新しいシステムを作ろうとして、全然進まないなぁと思って
なんでこんなに取り掛かるまでに時間がかかっているのか、色々と洗い出してみた

  • vimを使いこなせるようになる
  • deployスクリプト書く
  • MVCに対する知識
  • 開発環境をVM上での開発に切り替える
  • バージョン管理をsvnからgitに変える
  • フレームワークの選定
  • テストを書く
  • vimプラグインで入力補完、プロジェクト管理
  • vimで複数ファイルを開いての開発
  • git pushによるdeploy
  • bitubucketアカウントをとってプライベートリポジトリを作る
  • git-svnを使ってsvnリポジトリにも対応する
  • ローカルでのVMを使った開発環境を整える
  • ローカルで開発をする際に新規VMを簡単に立ち上げられるようにchefでレシピを作っておきたい
  • ていうかvagrantも情報仕入れなきゃ
  • etc...

以前は自分の知ってる少ない知識の中でやっていたので、選択肢も少なくてすんなりと取り掛かり始められていたのが、色々な情報を目にしてしまったがために「あれもこれも」となっていることが判明
これだけのこと一気にやろうとしてるから、取り掛かるまでが非常に億劫になってしまっているのですね

とりあえず一つずつ片付けていくしかないわけですな


んで、ここんところrebuild.fmを聞いていて、そのなかで「yak shaving」についての話が出ていたんだけれども
今回のケースもまぁ自分限定の「yak shaving」状態なのではないかと思ってしまいましたとさ

Rebuild: 4: bkノート, Yak Shaving, Code Reviews (高林哲)
yak shaving で人生の問題の80%が説明できる問題 - bkブログ

WebViewでProgressDialogを出す場合の注意

AndroidのWebViewでProgressDialogを出すときに以下のようなエラーがでることがあったので調査

android.view.WindowManager$BadTokenException: Unable to add window ? token android.os.BinderProxy@44e04f18 is not valid; is your activity running?
  • isFinishing()でActivityが有効になっているかチェック

何にも考えずに dialog.show() みたいなことをするとエラーが出た
isFinising()で対象のActivityがちゃんと有効な状態になっているかを確認してから dialog.show() する

if (!isFinishing()) {
	dialog.show();
}
  • new ProgressDialog()に渡す引数はActivityを渡してあげる

これも色々なところで書いてあったんだけど、getContext() とかでとってきたものを渡すとダメらしい

public void onCreate(Bundle savedInstanceState) {
	// this とかちゃんとActivityを継承しているものを渡してあげる
	ProgressDialog progress = new ProgressDialog(this);
}
  • 参考にしたページ

【Android】WebViewで読み込み中にダイアログを表示する(2)
Androidアプリサービス開発者ブログ:android.view.WindowManager$BadTokenException について
Dialogを表示しようとしてWindowManager$BadTokenExceptionが出る場合の対処 - Qiita
Day After Neet: AndroidのWebViewをできるだけ早く表示する(UI編)
Android 処理待ちダイアログの設定(ProgressDialog) | 株式会社ランチェスター

apache2のMultiViewsではまった話

新規に環境構築しようとしてはまった話

DocumentRoot直下に下記のようなファイルを用意しておく

<?php
var_dump($_SERVER['PHP_SELF']);

で、それぞれ下記のようなURLにアクセスしていく

string(9) "/hoge.php"
string(19) "/hoge.php/fuga.html"


ん?
どうゆうこと?

で、色々探し回ったあげく、apacheの設定でMultiViewsを外したらちゃんとしたURLでアクセスできた

mod_rewriteかと思って探し回っていたので、かるくはまってしまった

  • 参考

http://1-byte.jp/2010/09/18/multi_views_for_php_and_apach2/

spl_autoload_registerで無名関数を使ったときのエラーが出て解決できない

spl_autoload_register()に無名関数を渡す下記のようなコードを書いた

<?php
spl_autoload_register(function($name){
	require './classes/' . strtolower($name) . '.php';
});

$sample = new Sample();

んで、ブラウザからアクセスすると、以下のようなエラーのどちらかが出る

Fatal error: Uncaught exception 'LogicException' with message 'Illegal value passed (no array or string given)' in /home/hogehoge/spl_autoload_register.php:xx Stack trace: #0 /home/hogehoge/spl_autoload_register.php(xx): spl_autoload_register(NULL) #1 {main} thrown in /home/hogehoge/spl_autoload_register.php on line xx
Fatal error: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 1643394337 bytes) in /home/hogehoge/spl_autoload_register.php on line xx

モリーアロケーションエラーは何回かに1回
行数はspl_autoload_registerの閉じ括弧

環境は
CentOS 6.4
PHP 5.4.15

環境的には問題なく使えるはずなんだけどなぁ・・・

ちなみにcli環境からは問題なく動作する

なんかの依存関係くさい気はしてるんだけど、現状不明

教えてえらい人w

旧Androidブラウザの罠

特定の機種に限ったことか、OSのバージョンによるものかわからないけど、割と初期のAndroidブラウザでの不具合?に遭遇したのでメモ

border-radius で % 指定できない

border-radius:50%;

みたいな書き方が出来ないっぽい
ピクセル指定にしたら普通に表示できたので、とりあえずそれで対処

background-size はベンダープレフィックスをつける

背景画像のサイズ指定をするには -webkit- とベンダープレフィックスをつけてあげないと解釈してくれず、元のサイズのまま表示されてしまう

background-size:100px 100px;
-webkit-background-size:100px 100px;

PHP5.4 における htmlspecialchars の挙動変更に関して

いままで、5.4で動かしてなかったやつでhtmlspecialchars()を通すと空が返ってきて、あれれ?と思ったら5.4になってデフォルトの文字コードUTF-8になったために挙動が変わってしまったようだ

まぁ、詳細は徳丸さんのブログに1年半くらい前に書いてあるのですが
PHP5.4のhtmlspecialcharsに非互換問題 | 徳丸浩の日記

過去の技術的負債にやられて、ゴリゴリと書き直すことにします orz