アルファサード株式会社 代表取締役 野田 純生のブログ


静的生成と動的生成, Webページをビルドするコストは最初の訪問者に支払ってもらいましょう(さらに続き)。


公開日 : 2007-06-26 17:59:21


追記(2007年6月29日):
一連のエントリーで作成したものを取りまとめて公開しました。


何でこんなことやってんだろ(笑)。

まぁこういう負荷軽減のためのあれこれって結構楽しいわけです。動けばえーやん、から一歩進むための色んなコツみたいなものがあって、昔非力なMac、速度の出ないスクリプト言語(AppleScriptとかREALbasicとか)で工夫しながらやっていたことがこんなところで使えるとは...

関連エントリー

Movable Type10分間Cooking!(Part3)

今回はMovable TypeというよりHTTPヘッダを使ったクライアントキャッシュのコントロールが本題。ステータス404をちゃんと返さないと弾さんに怒られちゃうし。

前々回, 前回のはそのあたり全く考慮していないので、以下きちんと実装する。

  • 最初のページへのリクエストがあった時(ページとファイルを生成する時)にクライアントに Last-Modified, Content-Length を返す(クライアントにきちんとキャッシュさせる)*
  • ロボットからのアクセスの場合 HTTP_IF_MODIFIED_SINCE をチェック。entry->modified_on と比較してエントリーが更新されていなければ304 Not Modifiedを返す。ブラウザからのアクセスであればページをBuildしてファイルを構築する(その際ファイルのタイプスタンプを entry->modified_on にあわせる。
  • エントリーが見つからなかった場合は404 Not Foundを返す。

*ETagは使わない。参考:14 rules for fast web pages (Skrentablog)

今回は理屈の説明はなし! (説明書くと15分かかるので10分間Cookingにならないし!)

チェックしているUserAgentはとりあえずGooglebotのみ。

touch しているのは、この方法だとファイルのタイムスタンプは常に modified_on よりも新しいものになってしまうので2回目のアクセスの時にHTTP_IF_MODIFIED_SINCEと時間があわなくなってしまうのでその対策。

  • テスト用ブログ : Junnama Online (Dynamic)

mtview.cgi

#!/usr/bin/perl -w
use strict;

use lib qw (/path/to/mt/lib/);
use lib qw (/path/to/mt/extlib/);

use MT;
use MT::Blog;
use MT::Entry;
use MT::Builder;
use MT::Template;
use MT::TemplateMap;
use MT::Template::Context;
use MT::Permalink;
use HTTP::Date;

my $mt = MT->new(Config => '/path/to/mt/mt-config.cgi');

my $base_url = 'http://junnama.alfasado.net';
my $base_pth = '/path/to/htdocs';

my $blog_id = 3;

my $request = $ENV{"REDIRECT_URL"};
my $url = $base_url.$request;
my $permalink = MT::Permalink->load({permalink => $url});
if (defined $permalink) {
	my $modified_on = $permalink->modified_on;
	my $yymmdd = substr($modified_on, 0, 8);
	my $hhmmss = substr($modified_on, 8, 8);
	my $yymmddhhmm = substr($modified_on, 0, 12);
	my $ss = substr($modified_on, 12, 2);
	$modified_on = $yymmdd.'T'.$hhmmss.'Z';
	my $touch = 'touch -t '.$yymmddhhmm.'.'.$ss.' ';
	$modified_on = &str2time($modified_on);
	my $http_if_mod = $ENV{'HTTP_IF_MODIFIED_SINCE'};
	$http_if_mod = &str2time($http_if_mod);
	my $ua = $ENV{'HTTP_USER_AGENT'};
	if ($ua =~ /Googlebot/i) {
		if ($http_if_mod && ($http_if_mod >= $modified_on)) {
			print "Status: 304 Not Modified¥n";
			print "Last-Modified: $modified_on¥n¥n";
			exit;
		}
	}
	my $entry = MT::Entry->load({id => $permalink->id});
	if (defined $entry) {
		my $tmap = MT::TemplateMap->load(
								{	blog_id => $blog_id,
									archive_type => 'Individual',
									is_preferred => 1
								},);
		my $template = MT::Template->load({id => $tmap->template_id});
		my $page_tmpl = $template->text;
		my $blog = MT::Blog->load({ id => $blog_id });
		my $ctx = MT::Template::Context->new;
		$ctx->stash('entry', $entry);
		$ctx->stash('blog', $blog);
		$ctx->stash('blog_id', $blog_id);
		my $build = MT::Builder->new;
		my $tokens = $build->compile($ctx, $page_tmpl);
		my $html = $build->build($ctx, $tokens);
		if ($html) {
			$modified_on = &time2str($modified_on);
			my $len = length($html);
			print "Status: 200 OK¥n";
			print "Last-Modified: $modified_on¥n";
			print "Content-Length: $len¥n";
			print "Content-Type: text/html¥n¥n";
			print $html;
			my $buildfile = $base_pth.$request;
			$touch .= $buildfile;
			open (OUT,">$buildfile");
			print OUT $html;
			close(OUT);
			my $res = system($touch);
			exit;
		}
	}
}
print "Status: 404 Not Found¥n";
print "content-type: text/html¥n¥n";
print "404 Not Found.";

さらにさらに続きはこちら↓。



このブログを書いている人
野田純生の写真
野田 純生 (のだ すみお)

大阪府出身。ウェブアクセシビリティエバンジェリスト。 アルファサード株式会社の創業者であり、現役のプログラマ。経営理念は「テクノロジーによって顧客とパートナーに寄り添い、ウェブを良くする」。 プロフィール詳細へ