JavaScriptやCSSのキャッシュ問題を回避する簡単な方法

JavaScriptとかCSSを更新した時にキャッシュが消えてくれない..

Web開発をしている方なら,経験あるのではないでしょうか.
簡単な回避方法を紹介します.


それは,
JavaScriptCSSの呼び出し時に何らかの識別子をつける,です.


サーバサイドがPHPだったとしたら,システムのバージョンなんかをdefineで定義しておいて,
JavaScriptCSSの参照を以下のように書けばいいと思います.

こう書くと,,,
<?php
define('VERSION',    '1.0.90'); // revision番号でも何でもいいと思う
?>
<link rel="stylesheet" href="/css/common.css?ver=<?php echo VERSION; ?>" type="text/css" media="all">
<script type="text/javascript" src="/js/common.js?ver=<?php echo VERSION; ?>"></script>
こう出力される...
<link rel="stylesheet" href="/css/common.css?ver=1.0.90" type="text/css" media="all">
<script type="text/javascript" src="/js/common.js?ver=1.0.90"></script>


こうしておけば,何か変更をした時にVERSIONだけ更新すれば
ブラウザは別ファイルとして認識してくれるので必然的にキャッシュ問題を回避できる,という訳です.


今回の例だとシステムのバージョンですが,
日付でもいいしアクセス毎に乱数を付加するような実装でも同じようなことが実現できます.


ただ,キャッシュと上手くつきあうというのは大事なことなので運用を考えつつですね.

spanタグのすすめ.Ajaxのクリックイベントはaタグからspanタグへ.

jQuery便利ですよね.業務でも個人でもよく使ってます.
数年前までは「onClickさん」や「javascript:void(0);さん」が跋扈していたんでしょうけど,随分少なくなってきた印象です.


そんな中,ずっと勘違いをしていたというか,「クリックのイベントはaタグに紐付けるべき」って思い込んでました.
↓みたいな,リンク要素っぽいやつです.自分はhrefに「javascript:void(0);」って書くのが嫌なのでいつも「#」にしてました.


a2span


つまり,jQueryでの以下のようなコードですね.

// タグ省略
$('#click_a').click(function() {
    alert('最新の情報にしちゃうょ');
});

<a id="click_a" href="#">郵便番号から住所を検索する</a>


これで,ひとつ気になることがあって.それは...

クリックしたらURLの後ろに「#」って付くんですけど!!ってことです.


クリック前: http://www.example.com/hoge.html
クリック後: http://www.example.com/hoge.html# ←コレ


どうしてaタグ使ってるのか回想してみました.たぶん,こんなこと思ってました.

  • IE6ではaタグ以外にhover属性とか付けられないから(専用スクリプト使えばいけるみたいです.検証してません)
  • onClickとか書いてた頃の名残
  • だってリンクっぽいじゃん
  • そもそも「#」が付くとかどうでもいい

でも,気になってしまったからには仕方ないので対策しようと思いました.

CSSでaタグっぽくすればいいとして,pタグとかかな?

いや,pタグはブロック要素だし.ってことで,spanタグでやるようにしました.
超どうでもいい話ですけど,疑問形の文章を見る度に東進ハイスクールのCM思い出します.

「いつやるの?今でしょ」


はい,全然関係ないですね.
具体的には,以下のようなCSSを書いてリンクっぽくしてみます.

// タグ省略
$('#click_a').click(function() {
    alert('最新の情報にしちゃうょ');
});

/* タグ省略 */
#click_a {
  cursol: pointer;
  text-decoration: underline;
  /* その他リンク色とか */
}
/* hover とかなんとか */

<span id="click_span">郵便番号から住所を検索する</a>


a2span


aタグと全く同じ見た目でリンクっぽい要素が出来ました.まぁ,手抜きして同じキャプチャ使ってますけど.

結論

  • aタグに縛られる必要はないと思っている.本当はいけないとかいう理由があったら教えて欲しい.
  • ちょっとCSSが面倒な気がするが,そこまでseriousじゃないと思う.
  • IE6のことが少しでも気になる人は再考したほうがいいかも.

これだけは知っておきたい!5つのApacheコマンドラインオプション.

Webサーバではnginxが好きなんですが,仕事では専らApacheを使ってます.
知ってる人多い上に,なんでも揃えられるし外せるしっていう意味で重宝してます.

そんなApacheですが,コマンドラインでの使い方を知っている人が少ない気がします.
いくつかのオプションを知っているだけでグンッとオペレーションが楽になります.

前置き

[httpd]コマンドにパスが通っていることを前提として進めます.
RHEL+yumだと[/usr/sbin/httpd]とかですね.

httpd -v

バージョン番号を出力する.

$ httpd -v
Server version: Apache/[バージョン]
Server built:   [時刻]

httpd -V

コンパイル情報を出力する.

下はRHELにyumで入れたApacheの例.

$ httpd -V
Server version: Apache/[バージョン]
Server built:   [時刻]
Server's Module Magic Number: 20051115:3
Server loaded:  APR 1.2.7, APR-Util 1.2.7
Compiled using: APR 1.2.7, APR-Util 1.2.7
Architecture:   32-bit
Server MPM:     Prefork
  threaded:     no
    forked:     yes (variable process count)
Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/prefork"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=128
 -D HTTPD_ROOT="/etc/httpd"
 -D SUEXEC_BIN="/usr/sbin/suexec"
 -D DEFAULT_PIDLOG="logs/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_LOCKFILE="logs/accept.lock"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"

httpd -l

コンパイルされているモジュールの一覧を出力する.

下はRHELにyumで入れたApacheの例.

$ httpd -l
Compiled in modules:
  core.c
  prefork.c
  http_core.c
  mod_so.c

httpd -S

設定されているバーチャルホストの一覧を出力する.

下はRHELにyumで入れたApacheにVirtualHostを2つ設定した例.

$ httpd -S
VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
_default_:443          [FQDN] (/etc/httpd/conf.d/ssl.conf:[設定ファイルの該当行数])
*:80                   is a NameVirtualHost
         default server [FQDN] (/etc/httpd/conf/httpd.conf:[設定ファイルの該当行数])
         port 80 namevhost [FQDN] (/etc/httpd/conf/httpd.conf:[設定ファイルの該当行数])
         port 80 namevhost [FQDN] (/etc/httpd/conf/httpd.conf:[設定ファイルの該当行数])
Syntax OK

httpd -t

設定ファイルの構文チェックをおこなう.

[service httpd configtest]とかと同じ意味です.
余談ですが,[service httpd XXXX]っていうコマンド(実体は/etc/init.d/httpd)を投げると,[apachctl]っていうコマンドを呼び出すようになってます.
で,この[apachectl]から[httpd]コマンドに対してコマンドを発行します.名前が複数箇所で被っていて混乱しそうですけど簡単です.

こんな感じ

Apacheの説明用キャプチャ

[apachectl]はシェルスクリプトなので読んでみたら理解深まるとおもいます.

エラーがない時
$ httpd -t
Syntax OK
エラーがある時
$ httpd -t
httpd: Syntax error on line 1064 of /etc/httpd/conf/httpd.conf: </VirtualHost> without matching <VirtualHost> section

まとめ

主要なコマンドラインオプションを5つ紹介してみました.
[httpd -h]でオプション一覧が確認できますので興味がある方は是非.

友達には秘密にしておきたいMacBookAirに作るWeb開発環境

友達に秘密にするどころかWebに発信してますけど.
ホッテントリメーカーというのを初めて使ってみました.面白いですね.


本題です.2011夏モデル(13インチ+128GB)のMacBookAirにWeb開発環境を構築したのでメモしてみます.
結構最初からインストールされてたりするので,環境作るのは簡単です.

どんな環境作ったか

Python/PHP/Perl + Apache + MySQL の開発環境.

目次

サーバ編
ターミナル編
クライアント編
補足編

■サーバ編

homebrew

Macportsは重(遅)いので,モダンなhomebrewを.
と,その前にApp StoreからXcodeをインストールしておいてください.依存してます.

以下,Xcodeが入っているとして進めます.

# /usr/local以下をhomebrew管理ディレクトリにします
$ sudo chown -R $USER /usr/local/
# homebrewインストール
$ ruby -e "$(curl -fsS http://gist.github.com/raw/323731/install_homebrew.rb)"
# gitが必要なので,まずはgitいれる
$ brew install git
# brewのアップデート
$ brew update

以上,簡単ですね.

Python/PHP/Perl

初期状態のバージョンで満足しているので,そのまま使っています.
Python 2.7.1
PHP 5.3.6
Perl 5.12.3

Apache

こちらも,初期状態のバージョンで満足しているので,そのまま使っています.
Apache 2.2.19


ただ,このままだとブラウザから見ることが出来ないのでWeb共有設定する必要があります.
自分は面倒なんでGUIから設定してしまいましたが,気持ち悪いという方はhttpd.confを触りましょう.


GUIは[システム環境設定]->[共有]と入って,[Web共有]にチェックを入れます.

MacのWeb共有キャプチャ

MySQL

homebrew入れたのに,結局使ったのはMySQLのインストール時だけというオチでした.

$ brew install mysql

簡単です.バージョンは5.5.14でした.
ただ,私の環境だと数分かかりました.なおかつファンも回ってました.


my.cnfも貼っておきます. /etc/my.cnf がパスです.
/usr/local で動かして,UTF-8で稼働させるという前提です.

[mysqld]                                        
basedir = /usr/local
datadir = /usr/local/var/mysql
pid-file = /usr/local/var/mysql/mysql.pid
max_allowed_packet=64M
socket = /usr/local/var/mysql/mysql.sock
character-set-server = utf8
character-set-server= utf8
innodb_file_per_table

[mysql]

[client]
socket = /usr/local/var/mysql/mysql.sock
default-character-set=utf8


初期化から起動はこんな感じ.

# /usr/localからでないと,mysql_install_dbでこける
$ cd /usr/local
$ mysql_install_db
$ mysql.server start


設定についてはこちらのブログを参考にさせていただきました.

■ターミナル編

zsh

私はzsh使いなので,zshに変えました.併せてScreenを使うようにしましたが割愛します.

# パスワード打ち込むとshellの指定画面に遷移するので,そこで /bin/zsh 指定しました.
$ chsh
Changing shell for [USERNAME].
Password for [USERNAME]: 

TotalTerminal

OS自体がUnixなので,やっぱりふとした瞬間にTerminal使いたくなりますよね.
TotalTerminal入れるとホットキーで呼び出せたり,更に便利になります.
こちらのブログを参考に色をカスタマイズしたりとか,透明度設定したりしました.

参考:TotalTerminal公式

■クライアント編

エディタ

PythonEclipse+PyDev,PHPNetBeans,PerlVimを使ってます.浮気しまくりですね.
基本的には公式から落としてきてインストールで問題ないですけど,Eclipseを日本語化しようとすると若干大変です.
私はこちらのブログを参考にさせていただきました.Indigoでも問題なく動いてます.


というかむしろ,Windowsに慣れてるとEclipseの起動の速さに驚きます.

その他のアプリ

SkitchとかDropboxとかいろいろ使ってますけど,Web開発環境というところからは外れてしまうので,
アプリに関してはまた機会があったら紹介したいです.

■補足編

MacBookAirの良かったところ

キーボードは慣れると打ちやすい.慣れるまではちょっと大変かもしれない.
このMacBookAirは想像以上に軽いし,早い.正直,ここまで早いと思ってなかった.

MacBookAirの残念だったところ

よく言われているところですが,バッテリーの持ちはイマイチですね.
私は,ディスプレイを少し暗めにして作業するようにしていますがそれでもイマイチです.

Web開発環境としてのMacBookAir

標準で入っているソフトウェアが多く,なおかつ実用に耐えうるバージョンだと思います.
速度的にも申し分ないですね.あと,モニタは結構広く感じます.


そして,「ライオンの皮をかぶったUnix」という言葉を広めようとしているのですが,手応えは全くありません.



最後に.
家ではMac,会社ではWindowsなので次はWIndows + VMWareの開発環境メモでも書いてみます.

Facebookのいいね!(Like)ボタンが上手く動いてくれない時の対処法


少し前にFacebookのいいね!ボタンが上手く動かないという相談を受けた.
内容としては,製品の詳細ページのようなところにいいね!ボタンを設置しているが,動くページと動かないページがあるとのこと.


そんなことあるのかぁと思って調査をしてみると,確かに出来るものと出来ないものがあって,なおかつ規則性が見つからない.
例えば,「?id=12345」はダメだけど「?id=1234」は大丈夫みたいな感じ.桁数とか色々試してみたけど規則性は見られず.


AjaxFacebookAPIにリクエストを出しているところを監視してみたら,以下のようなエラーが返ってきていた.

for (;;);{"__ar":1,"payload":{"requires_login":false,"success":false,"already_connected":false,"is_admin":false,"show_error":false,"error_info":null}}


このエラーを元に調べたら,Stack Overflowというフォーラムに同じような現象にあっている人と解決策をコメントに書いてくれている人がいた.

php - facebook like button - Stack Overflow


要はリンクの末尾に「s=true」みたいのつけたらいいんじゃない?とのこと.「?id=12345&s=true」みたいな.
実際,これにしてみたら上手く動いているような感じでした.ただ,APIの不具合じゃないかということも書かれていたので,正しい対策かどうかはわかりません.

ハッシュ関数の比較ができる便利なコード


PHPでサポートしているハッシュ関数の一覧を比較できるコードがPHPマニュアルのnoteに掲載されていました.
あと,MD5 - Wikipediaとかにも書かれてますが,md5使っている人は,sha256以上にシフトした方がいいですよ!

<?php
// コード
// hash_algos()はPHP5.1.2以上が必要
$data = "hello";

foreach (hash_algos() as $v) {
    $r = hash($v, $data, false);
    printf("%-12s %3d %s\n", $v, strlen($r), $r);
}

// 出力
// アルゴリズム名 サイズ ハッシュ後文字列
// md2           32 a9046c73e00331af68917d3804f70655
// md4           32 866437cb7a794bce2b727acc0362ee27
// md5           32 5d41402abc4b2a76b9719d911017c592
// sha1          40 aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
// sha224        56 ea09ae9cc6768c50fcee903ed054556e5bfc8347907f12598aa24193
// sha256        64 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
// sha384        96 59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f
// sha512       128 9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043
// ripemd128     32 789d569f08ed7055e94b4289a4195012
// ripemd160     40 108f07b8382412612c048d07d13f814118445acd
// ripemd256     64 cc1d2594aece0a064b7aed75a57283d9490fd5705ed3d66bf9adfe3a58b25de5
// ripemd320     80 eb0cf45114c56a8421fbcb33430fa22e0cd607560a88bbe14ce70bdf59bf55b11a3906987c487992
// whirlpool    128 0a25f55d7308eca6b9567a7ed3bd1b46327f0f1ffdc804dd8bb5af40e88d78b88df0d002a89e2fdbd5876c523f1b67bc44e9f87047598e7548298ea1c81cfd73
// tiger128,3    32 a78862336f7ffd2c8a3874f89b1b74f2
// tiger160,3    40 a78862336f7ffd2c8a3874f89b1b74f2f27bdbca
// tiger192,3    48 a78862336f7ffd2c8a3874f89b1b74f2f27bdbca39660254
// tiger128,4    32 1c2a939f230ee5e828f5d0eae5947135
// tiger160,4    40 1c2a939f230ee5e828f5d0eae5947135741cd0ae
// tiger192,4    48 1c2a939f230ee5e828f5d0eae5947135741cd0aefeeb2adc
// snefru        64 7c5f22b1a92d9470efea37ec6ed00b2357a4ce3c41aa6e28e3b84057465dbb56
// snefru256     64 7c5f22b1a92d9470efea37ec6ed00b2357a4ce3c41aa6e28e3b84057465dbb56
// gost          64 a7eb5d08ddf2363f1ea0317a803fcef81d33863c8b2f9f6d7d14951d229f4567
// adler32        8 062c0215
// crc32          8 3d653119
// crc32b         8 3610a686
// salsa10      128 1d42409263cd0fa77196d0f658c374c45eae2ce2055bee8be0ee7a83a5dcf9068418464aec34e90ab3758ac626d811c6e5eeac4764f1e8b5d8fa3c4d9ce5973c
// salsa20      128 3521aedbf306f0e7a2f31fbc5ab44e8bcedd17287c0eaa04458578fb2d55e09a87f2051e910667b0acafe41d5492232662bf2a55c0c99882c0d341147eba2fef
// haval128,3    32 85c3e4fac0ba4d85519978fdc3d1d9be
// haval160,3    40 0e53b29ad41cea507a343cdd8b62106864f6b3fe
// haval192,3    48 bfaf81218bbb8ee51b600f5088c4b8601558ff56e2de1c4f
// haval224,3    56 92d0e3354be5d525616f217660e0f860b5d472a9cb99d6766be90b15
// haval256,3    64 26718e4fb05595cb8703a672a8ae91eea071cac5e7426173d4c25a611c4b8022
// haval128,4    32 fe10754e0b31d69d4ece9c7a46e044e5
// haval160,4    40 b9afd44b015f8afce44e4e02d8b908ed857afbd1
// haval192,4    48 ae73833a09e84691d0214f360ee5027396f12599e3618118
// haval224,4    56 e1ad67dc7a5901496b15dab92c2715de4b120af2baf661ecd9266317
// haval256,4    64 2d39577df3a6a63168826b2a10f07a65a676f5776a0772e0a877e27ec3c4c0ad
// haval128,5    32 d20e920d5be9d9d34855accb501d1987
// haval160,5    40 dac5e2024bfea142e53d1422b90c9ee2c8187cc6
// haval192,5    48 bbb99b1e989ec3174019b20792fd92dd67175c2ff6ce5965
// haval224,5    56 aa6551d75e33a9c5cd4141e9a068b1fc7b6d847f85c3ab1629578ed3
// haval256,5    64 348298791817d5088a6de6c1b6364756d404a50bd64e645035f8cd4291c482c7
?>

引用元:PHP: hash - Manual

PHPで配列の前詰めをしたい時のスマートなやり方

Kohanaについての記事を書きためているので,形になるまではメモ(changelog)から小ネタを書いていこうと思います.

今回は,PHPで配列の前詰めをしたい時の関数.
と,言いつつ専用の関数ではなく「array_merge」で出来ますよ,みたいな.

<?php

$array = array(0, 1, 2);
// 1 を消してみる
unset($array[1]);

// 配列の添字はそのまま
print_r($array);
//Array
//(
//    [0] => 0
//    [2] => 2
//)

// 配列の添字が前詰めされる
print_r(array_merge($array));
//Array
//(
//    [0] => 0
//    [1] => 2
//)

?>

実際,そこまで使う機会も無いですけど,たまにloopで作り直している人とかいるので.