CMSと静的ファイル管理に関する考察の(更に)続き。

| コメント(0) | トラックバック(4)

結局のところ、Movable TypeのCMSは現状「コンテンツマネジメントシステム」ではあっても「ファイルマネジメントシステム」ではないということなんだろう。

アップロードしたファイルをMTから削除したりすることができないというのも典型的な例か(TypePadベースのココログとかでは可能だし(インターフェイスは最悪だけど)、今後のバージョンでは実装されるのではないだろうか)。

で、前回・前々回の続きである。

結局どうプログラミングしてどう実装するというよりも、どう設計するか。

現状は産んだら産みっぱなし...というかファイルを生成したら生成しっぱなしなので、書き出したファイルの情報を保持しておくのが楽だろう。アーカイブマッピングやファイル名、カテゴリが変わるごとに旧パス情報と新パス情報を比較して何らかの処理をするという方法もあるにはあるだろうが色んな意味でコストが高くつきそうだし。

ということで以下のようにしてみた。


package MT::Content;
use strict;

use MT::Object;
@MT::Content::ISA = qw( MT::Object );
__PACKAGE__->install_properties({
   columns => [ 'id', 'file', 'content',
       'modified', 'size', 'blog_id',
       'digest', 'status',
   ],
 indexes => {
  id => 1,
  file => 1,
  modified => 1,
  blog_id => 1,
  status => 1,
 },
 datasource => 'content',
});

MT::Content(MT::Objectのサブクラス)

フィールド名タイプ説明
idinteger
(primary key,auto_incriment)
一意なID
filetextファイルのパス
contenttext書き出される(べき)HTML
modified(※1)integer書き出し時刻(Unixtime)
sizeintegerファイルサイズ
blog_idintegerブログのID
digesttexttextの要約(digest)
statusintegerステータス

利用方法は様々。一例として、前回の例であげたような「疑似的」ダイナミックパブリッシング等で使える。再構築の際にファイルシステムにファイルを書き出すのとデータベースに保存する違いだけで、構築されるデータは(プラグインの処理も含めて)まったく同様になる(一部BuildPage, BuildFileコールバックの際の処理は反映されないが、これはプラグインを書き換えるかコールバックも含めて上書きしてやることで(=プラグインの中からさらにコールバックを呼び出すことが可能なら)対応できるだろう)。

環境にかなり依存すると思うが、実際にテストしてみた環境ではファイルに書き出す約半分強の時間で全再構築が完了した。

あとは、ダイナミックパブリッシングの閲覧プログラム側でConditional GET([HTTP_IF_MODIFIED_SINCE]によって304を返してブラウザキャッシュを使わせる)に対応させたり、何ならリクエストが発生した段階でファイルを書き出すような処理も簡単だろう。

ダイナミックパブリッシングを利用しないのであれば content フィールドにHTMLを丸ごと入れる必要はなく、digest(※2) と size のみを比較して更新されたかどうかをチェックすれば良い。


my $digest = &md5_hex($html);
my $len = length($html);
use MT::Content;
my $content = MT::Content->load({ file => $file });
my $if_mod = 1;
unless (defined $content) {
 $content = MT::Content->new;
} else {
 if (($content->size == $len) && ($content->digest eq $digest)) {
  $if_mod = 0;
 }
}
if ($if_mod) {
# 更新されていたらDBを更新
}

CMSから吐き出されたファイルのパス/書き出されたファイルの時間を保持しているので、例えば「前回サイトを更新した以後に更新されているファイルの一覧」をリストアップすることも簡単(※3)

また、status フィールドをうまく使えば、

  • 全レコードの status を 一旦 0 にする
  • 全再構築して status を 1 にする
  • status が 0 のファイルが存在していたら(ゴミ)ファイルとレコードを削除する

というようなしくみも作れる。(※4)


  • ※1) modified_on にしてはいけない。というか modified_on にするのであれば timestamp 形式にしないといけない...みたいだ。
  • ※2) MT::Utilの perl_sha1_digest_hex を使ってdigestを生成したところ、再構築の時間が2倍くらいかかったのでDigest::MD5(md5_hex)を利用した。
  • ※3) 以前にも必要があって作ったことがあって、「CMSはコンテンツ管理のみに利用, 納品は出来上がったファイルのみ, 更新時には差分ファイルだけ納品」というケースがWeb制作の現場では良くある。
    以前作った時はまだMTのしくみがよく分かっていなかったのでPHPからMySQLにアクセスしたりファイルのタイムスタンプをチェックしたりという感じでかなり力技の実装だった。
  • ※4) というか既に殆ど出来た。

nph-mtview.cgi(それなりにintelligence ? なHTTPサーバ)


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

use lib qw (/Applications/MAMP/htdocs/mt/lib/);
use lib qw (/Applications/MAMP/htdocs/mt/extlib/);
my $file = '/Applications/MAMP/htdocs';
my $index = 'index.html';

use MT;
use MT::Content;
use HTTP::Date;

my $CRLF = "\r\n";

my $mt = MT->new(Config => '/Applications/MAMP/htdocs/mt/mt-config.cgi');

$file .= $ENV{"REDIRECT_URL"};

if ($file =~ /\/$/) {
 $file .= $index;
}

my $content = MT::Content->load({ file => $file });

if (defined $content) {
 my $length = $content->size;
 my $http_if_mod = $ENV{'HTTP_IF_MODIFIED_SINCE'};
 my $http_if_none = $ENV{'HTTP_IF_NONE_MATCH'};
 my $modified = &time2str($content->modified);
 my $etag = $content->digest;
 if (($http_if_mod && ($http_if_mod < $modified)) ||
   ($http_if_none && ($http_if_none != $etag)) ||
   ! $http_if_mod ) {
  print "HTTP/1.1 200 OK$CRLF";
  print "Content-length: $length$CRLF";
  print "Last-modified: $modified$CRLF";
  print "Etag: $etag$CRLF";
  print "Content-Type: text/html$CRLF$CRLF";
  print $content->content;
 } else {
  print "HTTP/1.1 304 Not Modified$CRLF";
  print "Content-length: $length$CRLF";
  print "Last-modified: $modified$CRLF$CRLF";
 }
} else {
  print "HTTP/1.1 404 File Not Found$CRLF";
  print "Content-Type: text/html$CRLF$CRLF";
  print "404";
}

結局のところ、誰が、どこでコストを負担するかの話なんだよな。色んな意味で。


まだ続く...(Movable Type用ファイルマネージャーの設計と実装(1))

トラックバック(4)

トラックバックURL: http://junnama.alfasado.net/cgi/mt/mt-tb.cgi/367

MTでサイト制作をしている時に「ゴミ」が出来てしまう件について調べているうちに... 続きを読む

CMSと静的ファイル管理に関する考察。 こちら↑の続き。考察だけじゃなんだから... 続きを読む

showBOO's delicious BOOKMARK - links for 2007-04-30 (2007年5月 1日 04:24)

ITmedia エンタープライズ:最速Firefoxをビルドしよう【前編】 (1/2) (tags: Firefox Tips) ... 続きを読む

「CMSと静的ファイル管理に関する考察の(更に)続き。」のさらに続き。 具体的... 続きを読む

コメントする

Facebook

Twitter

このブログ記事について

このページは、Junnama Nodaが2007年4月30日 11:54に書いたブログ記事です。

ひとつ前のブログ記事は「CMSと静的ファイル管理に関する考察の続き。」です。

次のブログ記事は「SQLite(メモ)。」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 6.2.6