読者です 読者をやめる 読者になる 読者になる

サーバサイドjQuery

サーバ側でコンテンツ作るのにjQueryでやりたいなということで、ちょいちょい探してみましたが、軽めのものとしてcheerioというのをさらっとハローワールド。

$ npm install cheerio

インプットのHTMLとスクリプト一つ。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>input.html</title>
    </head>
    <body>
  </body>
</html>
var fs = require('fs');
fs.readFile('./input.html', function(e, input) {
    var $ = require('cheerio').load(input);
    $('title').text('output.html');
    var contents = ['one', 'two', 'three', 'four', 'ファイブ'];
    contents.forEach(function(value, i) {
        var div$ = $('<div>').addClass('c' + (i + 1)).text(value);
        $('body').append(div$);
    });
    var output = $.html();
    fs.writeFile('./output.html', output, function() {
        console.log(output);
    });
});

結果は想像どおりにちゃんとでます。$('<div>')でDOM要素作れたのがちょっと感動した。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>output.html</title>
    </head>
    <body>
    <div class="c1">one</div><div class="c2">two</div><div class="c3">three</div>
<div class="c4">four</div><div class="c5">&#12501;&#12449;&#12452;&#12502;</div></body>
</html>

このcheerio、jQueryと互換のAPIを独自に実装しているので、抜け漏れはまだあるみたい。たとえばcss()がイシューにもあがってるけど無いとか。とはいえ、普通に思いつくような操作はOKです。課題は日本語(ここでは「ファイブ」)がエンコードされるので、これはちょっと調査。たぶんオプションでなんかあるのだと思う。
気になるのは入力をHTMLパースするところ(load(input)のところ)とHTML出力するところ($.html()のところ)が同期実行だけど、でかいHTMLファイルのときにどうなんだろう。ファイルIOは別途なので問題ないのかな?child_processで書くべき?そのへん見極めたいですがまだnode.jsで本番アプリ作ってない岡プログラマーなので勘所がわからん。
cheerioのソースを見ると全体的にコンパクトに実装されていて好感度高いですが、本質的にはちがうかなあと。node.jsがChromeのスクリプトエンジンであるV8をホストしているようにそれこそ

  1. ChromeレンダリングエンジンであるGoogle Blinkをホストして
  2. ヘッドレスにDOMツリー構築してwindowオブジェクトを用意して
  3. そこへjQueryの本物ライブラリを動かす

というアプローチが直感的かなと思います。すでに誰かがやってるかと思ってたのだけどいまのところ見つからない。
結局のところExpressで使える、jQuery(そのままのAPIで)を利用して極ピュアなHTMLにロジック当てるようなテンプレートエンジン作りたいんですよね。Mayaa2?cheerioで良い感じであればそんなに手間なく作れそう。