2016年1月アーカイブ

PowerCMS の Pager や PageBute を利用したページ分割は非常に効率が悪いので記事の件数が半端無く多いシチュエーションでは使わない方が絶対にいいです。

記事の更新頻度によって月別、年度別、年別等の time-basedなアーカイブにしたほうがいい。理由は、time-basedなアーカイブは更新対象のアーカイブのみが再構築されるためです。ページングって、1件増えたら、1件削除されたら全アーカイブが1件だけ「ずれて」全再構築されるのです。1件更新されても全アーカイブが再構築対象になります。

というようなことを口を酸っぱくして言ってんのに、結局破綻してしまったというケースに出くわしたので作成しました。

これ、カテゴリとかもニーズあるよね、MT7では標準機能になるよね、と振るだけ振っておいて。

アーカイブマッピングで「手動」を選択

  • https://github.com/alfasado/mt-plugin-monthly-entries-publisher
  • プラグインをインストール
  • ウェブサイト(ブログでも良い)月別アーカイブを作成し、include_blogsで含めるブログを指定する
  • テンプレートマップの再構築オプションは「手動」とする(「再構築しない」を選択しないこと:「再構築しない」だと書き出されない)
  • MTEntriesの__first__ もしくは MTEntriesHeader 内に 「<!--EntriesCount:<mt:EntriesCount>-->」記述を入れる(ファイル出力時にはこの値は削除されます)
  • mt-config.cgi に MonthlyEntriesPublisherTemplateIds テンプレートのIDカンマ区切りを記載
  • mt-config.cgi に MonthlyEntriesPublisherBlogIds として、記事保存時にキューに入れる対象のブログIDをカンマ区切りで記載

再構築はキューで実行されます。ダイナミックパブリッシングには対応していません。

Data APIから1日数千件のエントリを更新、新規追加するというような要件の案件で現場から「スピードがでないんっすよ」ということでヘルプ要請が来たのですが、「CGIの起動がクソ重いんじゃないの?」ということで複数件のJSONを纏めて投げられるエンドポイントを作成して対応しようとしたのですが、それでもまっっっったくと言っていいほどパフォーマンスの改善が見られない。再構築をキューにして凌ごうと思ったのですがそれでも一件 Insert するのに10秒も20秒もかかるのです。

  • Data APIで記事インサート、アップデート
  • 1件10〜20秒を要する

調べたところ、こいつが問題。

  • 記事カスタムフィールドが200個近く!

コードを見たり、SQLのクエリを見たり。犯人見つけましたぜ。

MTのカスタムフィールドは1フィールド1レコードで、1フィールド1SQLを発行するのです

なのです。こんなこと知ってたらカスタムフィールド200個近くも作成しないですよね? 5件単位でインサートだったらSQL1000クエリ、カスタムフィールドのためだけに投げるわけです。

なので、MySQLの Bulk Insertを使うようにしてみたらめっちゃ速くなったよというお話でした。単位は秒。Updateの場合は Insertの倍のスピードになります。SQLの数が半端ないので、1台構成より DBとCMSがわかれている複数台構成の方が効果は顕著です。

カスタムフィールドをBulk Insertにしたら300%以上高速化されたという話し(効果測定結果)

ObjectDriver が DBI::mysql で、mt-config.cgiに「BulkInsertMeta」環境変数を指定しているときのみ有効になります。あくまでも実験的な位置づけなのでノンサポート、自己責任でお願いします。

/mt/lib/MT/Meta/Proxy.pm

Oracle や SQL Serverに対応できていないので、その辺りが課題ですが、いずれにしても MTには足回りの強化をお願いしたいところです(既にお願いはしておいたんですがね)。

ま、回答数が少ないんだけど半数以上があるという回答ですね。「ある」人がこういうのに反応したんだと捉えることもできるけど、これ、僕が目にしたからこういうポストしたんですね。同じ案件で3回。

MTのアーカイブの柔軟なところは評価されていいんですが、デフォルトだとウェブページのアーカイブマッピングは以下のようになっています。

デフォルトのウェブページのアーカイブマッピング

%-c/%-f

フォルダの指定を忘れて、出力ファイル名を「index」にしてしまうと...

メインページを上書きしてしまうではないですか。

ウェブページのパス指定箇所

マニュアルに書いたでしょ? とか言わずにこういうのはシステムの方でミスを防いでやるのがスマートですよね?

plugins/NoOverwriteMainIndex/config.yaml を置いて(フォルダ名は何でもいいけど)、以下の短いコードをぺたっとするだけです。

プラグインでメインページを上書きしないように設定できる

こういう小さな工夫が使い勝手を向上させ、オペレーションミスによる問題を防いでくれる、ひいては顧客からの質問攻めによる負荷を下げてくれるってもんだと思います。

title要素やHTMLの属性値に出力する箇所

属性値やtitle属性中にはタグが使えないため。

<img src="<mt:AssetURL>" alt="<mt:ImageAlt escape="html">" />

または

<img src="<mt:AssetURL>" alt="<mt:ImageAlt remove_html="1" escape="html">" />

H1要素など、HTMLを含めることが可能な箇所

改行を含めたい等のケースがあるので要件、サイトのルールに応じて。

<h1><mt:PageTitle></h1>

URLを入力するカスタムフィールドの場合

trimを指定するのはフィールドへのコピペで前後に空白が入る可能性があるため。

<mt:ImageLinkURL trim="1" encode_url="1">

外部ユーザーが改ざん可能な値を出力する時

XSSに繋がるため

<mt:Var name="request.foo" escape="html">

MTSetVarBlock - テンプレートタグリファレンス

このブロックタグで囲んだ内容を値にした変数を設定します。このタグの中ではテンプレートタグが利用できます。変数を呼び出すときは、MTGetVar, MTVar ファンクションタグを使います。

MTSetVarTemplate ブロックタグとの違いは、囲んだ内容が処理された結果が値となるか、囲んだ内容が処理されずテンプレートのまま値となるかです。MTSetVarBlock ブロックタグでは囲んだ内容が処理された結果が値となります。

設定した値は $name_foo として、モディファイアの値としても利用することができます。

MTSetVarTemplate - テンプレートタグリファレンス

このブロックタグで囲んだ内容を値にした変数を設定します。変数を呼び出すときは、MTGetVar, MTVar ファンクションタグを使います。

MTSetVarBlock ブロックタグとの違いは、囲んだ内容が処理された結果が値となるか、囲んだ内容が処理されずテンプレートのまま値となるかです。MTSetVarTemplate ブロックタグでは囲んだ内容が処理されずテンプレートがそのまま値となり、MTGetVar, MTVar ファンクションタグで呼び出されたテンプレートで処理をおこないます。

使いどころが良くわからない的な話しがあるようですが、ひとつわかりやすい例を。

ナビゲーションブロックの組み立てのための Loop 系タグの呼び出しを1回にまとめる

グローバルナビ、サイドナビ、フッターの3カ所に MTTopLevelCategories が使われているとします。良くある話しですよね? でもHTMLの形は違うと。

ワイヤーフレーム

この時、MTTopLevelCategories の呼び出しを一回にまとめたい。だってその方が速いし。カテゴリが多く、テンプレートに MTTopLevelCategories が3回も4回も呼ばれてるケースなら相当速くなりますよ。

以下のようにすればループは一回で済みます。モジュール化して呼び出すときはキャッシュに注意ね。キャッシュされたテンプレートは(キャッシュヒットすると)評価されないので変数にセットされません。

<mt:TopLevelCategories>
<mt:SetvarBlock name="カテゴリリスト・グローバルナビ">
    カテゴリリスト・グローバルナビのMTML
</mt:SetvarBlock>
<mt:SetvarBlock name="カテゴリリスト・サイドナビ">
    カテゴリリスト・サイドナビのMTML
</mt:SetvarBlock>
<mt:SetvarBlock name="カテゴリリスト・フッタナビ">
    カテゴリリスト・フッタナビのMTML
</mt:SetvarBlock>
</mt:TopLevelCategories>
# 呼び出し
<mt:Var name="カテゴリリスト・グローバルナビ">
<mt:Var name="カテゴリリスト・サイドナビ">
<mt:Var name="カテゴリリスト・フッタナビ">

もし各ブロックのHTMLの違いが一部である場合、例えば下記のような場合は MTSetVarTemplate の出番です(class名だけが違うなど)。

<mt:SetVarTemplate name="カテゴリリスト">
    <mt:SubCatIsFirst><ul class="<mt:Var name="nav_class_name">-list"></mt:SubCatIsFirst>
    <mt:If tag="CategoryCount">
    <li class="widget-list-item"><a href="<$mt:CategoryArchiveLink$>"><$mt:CategoryLabel$></a>
    <mt:Else>
    <li class="widget-list-item"><$mt:CategoryLabel$>
    </mt:If>
    <$mt:SubCatsRecurse$>
    </li>
    <mt:SubCatIsLast></ul></mt:SubCatIsLast>
</mt:SetVarTemplate>

<mt:TopLevelCategories>
    <mt:Var name="カテゴリリスト" nav_class_name="gnavi" setvar="カテゴリリスト・グローバルナビ">
    <mt:Var name="カテゴリリスト" nav_class_name="snavi" setvar="カテゴリリスト・サイドナビ">
    <mt:Var name="カテゴリリスト" nav_class_name="fnavi" setvar="カテゴリリスト・フッタナビ">
</mt:TopLevelCategories>
# 呼び出し
<mt:Var name="カテゴリリスト・グローバルナビ">
<mt:Var name="カテゴリリスト・サイドナビ">
<mt:Var name="カテゴリリスト・フッタナビ">

ちょっと自分でもわかりにくいのを先日書いてしまったので懺悔の意味で書いた。後悔はしていない。

2015年は東京へ居を構えたことを始め、2オフィスの移転、MT Commerce の事業譲受、会社初のクラウドサービスのローンチ、人材の採用、W3C への加盟、経営理念策定とVIの刷新を行ないました。投資フェイズと考えて一気にことを進めましたが、うまくいったこともあり、いかなかったこともあり。

アルファサード ロゴ Improve the Web

例えば企業の B/S を見る時に「誰の立場でそれを見るか」という視点が必要です。 以前、CSS Niteではこの図を例に出して「すぐに出ていかないお金が多くを占めて早く現金化できる資産の多いBが望ましい」という話しをしました。

AとBどちらのB/Sが優秀か?

確かにBの経営は安定しているのは事実でしょう。銀行視点ではこれが正解です。ところがAの決算書の左下に注目すると見方が変わってきます。つまり、将来の利益を生み出すためにその会社は何に投資をしたのかが表れてきます。つまり、どういう視点で見るかによって正解は違うのです。

去年の我々の事業で言えば、オフィス移転(引越し代は経費だけど、内装費などは資産に計上される)、事業の譲受といった費用はB/Sの左下に入ります。つまり、アルファサードがやろうとしていることは Bから Aへ近づけて(もちろん大勢に影響はない範囲ではありますが)、より成長を目指して活動したということになります。

何故、仕事力か

結果的に去年は一昨年やそれ以前よりも多くのリソース、ヒト、モノ、カネをつぎ込んだにも関わらず、自分の目指すゴールには届きませんでした。結果、昨年の後半に自分で巻き返すために現場仕事を数多くこなしたのですが、ここにヒントがありました。結局、経験やスキルや仕事をうまく進めるメソッドは人数やお金に勝るということ。仕事力には「製品力」も含みます。もちろん PowerCMSや MT Commerceがもっと売れるに越したことはないですが、ここでいう製品力とはもっと違うもの。PowerCMSや MT Commerceを選択していただいたパートナー様やクライアント様をハッピーにするための総合力ということです。

  • PowerCMS を選択したはいいが、カスタマイズが思うように行かない
  • 想像以上のコストや時間がかかってしまった
  • カスタマイズしすぎてメンテナンス性が低下してしまった
  • 結局スキルが追いつかなくて手戻りを繰り返し方針変更を余儀なくされた

サポートを売りにして一定の評価を得たと思ってはいるものの、今一度そこを見直さなければ伸びていけない。これは、社内だけでなく、PowerCMSのパートナー様や MTコミュニティの皆さんと一緒に取り組んでいきたい。コミュニティ全体が「仕事力」を磨くことでソフトウェアは強くなるんだと思うのです。これらはリリーススケジュールの遅れなんてことにすぐ繋がる。

そのためにひとつ、宣言を

今年は本を書きたいと思います。出版という形をとるかどうかは別にして、これまでの自分のノウハウ、経験からくるベスト・プラクティスを後進に伝達しなければ後継者のいない職人になってしまう。なので、ハンズオンのためのテキストになるかもしれないし、書籍になるかもしれないけれど、書いてみたいと思っている。

今年は、あたりまえだと思っていたことに疑問を持つ一年に

以下のエントリ等で書いたように、現場にガッツリ入ることで仕事改善のたくさんのヒントがあります。

世の中には二通りの人がいます。

  • 常識を疑わないひと
  • 常識を疑ってかかる人

これまであたりまえのように、この機能を実装するのには何日かかるとか、MTでの構築だとこうやるのがセオリーとか、そういう殻を破っていかないと先はないということです。

最後に当社の経営理念の中、行動指針から、僕の好きな言葉を

  • 常識にとらわれずに他者と違うやりかたを模索せよ。不可能を可能にするために考え抜け。変化を好み、楽しめ。
  • 常に小さなイノベーションを起こせ。小さなイノベーションの積み重ねこそ、我々の成長のエンジンである。

Facebook

Twitter

このアーカイブについて

このページには、2016年1月に書かれたブログ記事が新しい順に公開されています。

前のアーカイブは2015年12月です。

次のアーカイブは2016年2月です。

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

Powered by Movable Type 6.2.6