Node.js、MongoDBでデータの保存:Node.jsを使ってみよう(2)(3/4 ページ)
Node.jsとSocket.IO、MongoDBを使用して、Webページの更新内容がリアルタイムにView画面に反映されるサイトを作ってみた
Tech Releaseで使用している技術紹介
これまで説明してきた、Node.jsとExpress、Socket.IO、MongoDBはTech Releaseでも使用している。Tech Releaseではその他にもNode.jsの便利なモジュールを使用していて、それらの技術紹介をしていこう。Node.jsでWebアプリを作ろうとしている人にとっては、同じようなモジュールを使用することになるはずだからきっと役に立つはずだ。
サーバ構成
- Windows Server 2008
- Node.js v0.8.8
- MongoDB v2.0.6
- Nginx v1.3.4
Tech Releaseが動いているサーバの主な構成は上のような構成になっている。この上にNode.jsで作られたアプリ、Handy Stadium、まじかるビンゴCOCORO、そしてTech Release、REABLOが動作している。Node.jsサーバとしてはWindows Serverを使用している例が少ないが、Node.js自体Windowsに対応しているし、npmでインストールできるライブラリは、大抵Windowsでも動作する。
node-supervisorでデーモン化
Node.jsでアプリを直接起動すると、エラーが発生時にアプリが停止する。エラーが起きるたびにサイトが表示できなくなるという問題を解決するために、デーモン化する必要がある。デーモン化で有名なツールとしてはforeverなどがあるが、今回はWindowsでも動作するnode-supervisorを使用した。
supervisorの使い方は、-g付きでnpm installし、アプリの起動にnodeコマンドで起動する代わりにsupervisorコマンドで起動するだけだ。
$ npm install -g supervisor $ supervisor -i node_modules app
supervisorでNode.jsのアプリを起動すると、エラーが発生すると自動的に再起動を行うようになる。また、対象のディレクトリ内のファイルが更新されたときにも再起動が掛かるので、修正のたびにアプリを再起動する手間を省略できて便利だ。
注意点としては、アップロードや書き込みなどでアプリが再起動してしまうので、監視するディレクトリやファイルをオプションで設定する必要がある。その場合-i(--ignore)オプションや-w(--watch)オプションで設定できる。上のコマンドの例では「-i node_modules」でnode_modules以下を監視対象外にしている。
History APIでページ全体リロードなしに遷移
リアルタイムでページ遷移させる場合は、ページをリロードせず、JavaScriptでHTML要素を書き換えて更新することになる。そのままだとURLが変わらないので、以下で変更する方法を紹介したい。
リダイレクトなしにURLを変更するには、HTML5のHistory APIを使って実装できる。Tech Releaseでもそれを利用しているので各記事のリンク(moreボタン)をクリックして確認してほしい。
History APIを使用した疑似コードは以下のようになる。history.pushState()で、引数には共有するstate(popState()で取り出して使用するデータ)、タイトル、URLを代入して実行すれば、ブラウザのURLが変わる。
$('a.entry').click(function(){ history.pushState(state,title,url); return false; });
History APIはIE9までのブラウザと、特定のバージョンのAndroidが対応していないので、代わりにlocation.hashを使用する。JavaScriptでhistory.pushStateが実装されているかどうかをチェックし、URLの表現方法を切り替えている。
生成されるのがどのようなURLになるのかTech Releaseの記事のURLを例としてみよう。下記のようにHistory API対応ブラウザの場合は、#なしのURL、非対応ブラウザでは#を付随させたURLに変わるように実装している。
- http://techrelease.mindfree.co.jp/entry/atmarkit-news115-node
- http://techrelease.mindfree.co.jp/#/entry/atmarkit-news115-node
cheerioでSEO対策
コンテンツのDOM生成をサーバサイドで行わず、クライアントサイドで動的に生成すると、Googleなどの検索ボットにコンテンツが読み込まれず、検索結果に引っ掛からないという問題が出てくる。これは検索ボットがJavaScriptを解釈しないため、空のコンテンツしか読み込めていないからである。
今回の対策としては、JavaScriptが実行されない環境でもページ情報を読み込めるように、静的なHTMLをサーバサイドで作成するという方法を採った。クライアントサイドではjQueryとjQuery tmplを使用してコンテンツ要素を作成しているのだが、これらの処理をサーバサイドにも実装しないといけない。今回はサーバサイドでもjQueryのようなDom操作ができるライブラリのcheerioを使用した。
cheerioはサーバサイドでjQueryライクなAPIがそろっているので、クライアントサイドで使用しているjQueryと同じような記述でコンテンツの生成を行っている。サーバサイドの実装を一部抜粋すると以下のような実装になっている。
コードでは、cheerio.load()でテンプレートのhtmlを読み込み、jQueryのようにDOMを修正し、$.html()でhtmlの文字列に変換している。そしてテンプレートエンジン側(今回はejs)でその要素を追加すれば実装完了だ。
var cheerio = require('cheerio'); app.get('/entry/:id', function(req,res){ var data = getEntryData(req.params.id); if(data !== null){ var $ = cheerio.load(tmpl_entryHtml); $('.entry').addClass('static-view'); $('header h2').text(entry.title); $('header time').attr('date-time',entry.date).text(entry.date); $('.storysection .content').html(entry.text); opt.entryHtml = $.html(); } res.render('index', {opt:opt}); });
各エントリーを検索ボットが認識できるように、記事のRSSを作成して、Googleのウェブマスターツールに登録する。これでうまくいけば、数日後にGoogle検索の検索結果に表示されるようになる。
chreerio自体はあくまでjQueryライクなAPIであり、メソッドなどが多少異なる場合があるので、使う場合chreerioのドキュメントは確認しておこう。
https://github.com/MatthewMueller/cheerio
Internet Explorer対応
DOMの生成にはarticleタグなどHTML5の要素などを使用しているが、IE8などではサポートしていない要素が含まれているので、表示を可能にするため下記の工夫を行っている。
作り方としては、初めにChrome、Firefoxだけで動作確認をして作成し、後から他のブラウザの対応を行った。その際、使っているのが以下のライブラリである。
HTML5のHTML要素がIEでも使用できるようにするライブラリ。
IE7でもJSONが使用できるようにするライブラリ。プロジェクトではリンク先のjson2.jsを使用している。
Array.prototype.mapなどECMAScript 5で定義されたメソッドを実装されていないブラウザにも使えるようにするためのライブラリ。
CSSのbackground-sizeが使えないIE8以下でも使用できるようにするライブラリ。
REABLOの記法について
REABLOとTech Releaseでは記事の変更をリアルタイムに見せるために、管理者が1文字文章を修正するたびにSocket.IOで、記事を見ているユーザーに、その変更内容を送信している。そこで使用している記法は、wiki記法と似た記法を採用し、独自に実装した。
編集途中もリアルタイムにユーザーに見えてしまうため、なるべく記法入力途中を見せないように記法を工夫しており、その内容をTech Releaseに記載してあるので、興味のある方は参照してほしい。
http://techrelease.mindfree.co.jp/entry/techrelease_notation
Copyright © ITmedia, Inc. All Rights Reserved.