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

albatrosary's blog

Azure と Angular と Wercker CI とか

そんなにメンテナンスが大変ならAngularでも入れなよ 〜 簡単なサイトをAngularに変えてみた 〜

AngularJS

html5jエンタープライズ部のサイトはベタなHTMLで出来ているのだがサイトをメンテナンスしていてイライラがピークに達したためAngularのルーターを使うことでイライラを解消しました。つまりメンテナンス制の向上というやつです。

JavaScriptフレームワークは、簡単な用途で利用すればプログラマでなくても機能を使うことができます。当然色々な機能がありますので難しいことをしようと思えば様々な難解な出来事が待ってますが、もっと気軽に使っていくべきものです。 

何を変更したのか

簡単なサイトでもヘッダー部とフッター部というのは存在します。html5jエンタープライズ部のサイトだと

ヘッダー部は

f:id:albatrosary:20140625163152p:plain

フッター部は

f:id:albatrosary:20140625163218p:plain

です。この部分はどのページに行っても変化しませんので複数のHTMLに同じことが書かれているのは好ましくありません。一事実一カ所ではありませんが重複を省きメンテナンスの向上をめざします。

ソースレベルで見てみる

ソースレベルではもっと複雑です。実際に目にするコンテンツ意外の部分が次のHTMLソースに成ります。このコードが殆どすべてのHTMLに記載されています。html5jエンタープライズ部以前html5jえんぷら部と言ってましたのでこの文言を変更するだけでも至難の業でした。置換すればいいというお話もありますが。。。

<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<!--Facebookソーシャル対応用 begin -->
<meta property="og:title" content="html5jエンタープライズ部">
<meta property="og:type" content="article">
<meta property="og:url" content="http://www.html5biz.org/">
<meta property="og:image" content="http://www.html5biz.org/img/html5logo.png">
<meta property="og:site_name" content="html5biz">
<!--Facebookソーシャル対応用 end -->
<title>html5jエンタープライズ部</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="./css/bootstrap.min.css">
<style>
body {
padding-top: 60px;
padding-bottom: 40px;
}

</style>
<link rel="stylesheet" href="./css/bootstrap-responsive.min.css">
<link rel="stylesheet" href="./css/main.css">
<script src="./js/vendor/modernizr-2.6.2-respond-1.1.0.min.js"></script>
<script src="./js/analytics.js"></script>
</head>
<body ng-app="html5jenterprise">
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="/">html5jエンタープライズ部</a>
<div class="nav-collapse collapse pull-right">
<ul class="nav">
<li>
<a href="https://groups.google.com/group/html5-developers-jp/subscribe" target="_blank">メーリングリスト</a>
</li>
<li>
<a href="#/readme">ML投稿ルール</a>
</li>
<li>
<a href="#/archive">アーカイブ</a>
</li>
<li>
<a href="#/aboutus">この団体について</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div class="social_apps">
<!-- Mixiボタン -->
<div class="social_button"><div data-plugins-type="mixi-favorite" data-service-key="46607bf620e72c972405f586667bf636f84b5a97" data-size="medium" data-href="http://www.html5biz.org/" data-show-faces="false" data-show-count="true" data-show-comment="true" data-width=""></div></div>
<!-- Google+ボタン -->
<div class="social_button"><div class="g-plusone" data-size="medium"></div></div>
<!-- Twitterボタン -->
<div class="social_button"><a href="https://twitter.com/share" class="twitter-share-button" data-url="http://www.html5biz.org/" data-lang="ja" data-hashtags="html5biz">ツイート</a></div>
<!-- Facebookボタン -->
<div class="social_button"><div class="fb-like" data-href="http://www.html5biz.org/" data-send="false" data-layout="button_count" data-width="80" data-show-faces="true"></div></div>
</div>
</div>
<div ng-view="" class="container">

</div>

<hr>

<div class="container">
<footer>
<p>Copyright &copy; 2013-2014
<a href="https://github.com/html5bizj" target="_blank">html5jエンタープライズ部</a> All Rights Reserved.</p>
</footer>
</div>

<!-- /container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
window.jQuery || document.write('<script src="./js/vendor/jquery-1.9.1.min.js"><\/script>')
</script>

<script src="./js/vendor/bootstrap.min.js"></script>

<script src="./js/main.js"></script>
<script src="./js/controllers/main.js"></script>

<!-- ソーシャル対応 -->
<!-- Google+ -->
<script type="text/javascript">
window.___gcfg = {lang: 'ja'};

(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
<!-- Facebook -->
<div id="fb-root"></div>
<script>(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/ja_JP/all.js#xfbml=1&appId=157307964436235";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));</script>
<!-- Twitter -->
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
<!-- Mixi -->
<script type="text/javascript">(function(d) {var s = d.createElement('script'); s.type = 'text/javascript'; s.async = true;s.src = '//static.mixi.jp/js/plugins.js#lang=ja';d.getElementsByTagName('head')[0].appendChild(s);})(document);</script>
</body>
</html>

やったこと

今回はAngularのデータバインディングとかかっこいい機能は使う必要が無く、単にルーティング機能が欲しいだけです。ですので次のことを行いました。

  • Angularのインストール
  • コンテンツ部分をすべてviewsディレクトリの中にテンプレートとして保存
  • ルーティングの設定

Angularのインストール

bowerを使ってAngularモジュールをインストールします。

$ bower install angular --save
$ bower install angular-resource --save
$ bower install angular-cookies --save
$ bower install angular-sanitize --save
$ bower install angular-route --save

あとはHTMLファイルに追加します。追加した部分を抜粋します。

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="./js/vendor/bootstrap.min.js"></script>
<script src="bower_components/angular/angular.min.js"></script>
<script src="bower_components/angular-resource/angular-resource.min.js"></script>
<script src="bower_components/angular-cookies/angular-cookies.min.js"></script>
<script src="bower_components/angular-sanitize/angular-sanitize.min.js"></script>
<script src="bower_components/angular-route/angular-route.min.js"></script>
<script src="./js/main.js"></script>
<script src="./js/controllers/main.js"></script>

コンテンツ部分をテンプレート化

コンテンツ部分をテンプレート化するというのはコンテンツのところを別のHTMLファイルに抜き出すという意味です。例えば「ML投稿のルール」というコンテンツがあるのですが

 <div class="page-header">
<h1>ML投稿のルール
<small></small>
</h1>
</div>
<div class="span11">
<p>html5jえんぷら部は、コミュニティ「html5j」と同じMLを利用して活動しております。html5jには他の部活もありますが、Web技術に関連したネタなら、全く気を使わずガンガン交流してOKです!技術的質問についても、Web技術好きが集まったこのコミュニティでは歓迎されるはずです!ここで起きている議論は、国内のWeb技術発展に大きく貢献されます!楽しみましょう!</p>
<p>ただ一点だけお願いです。部活内での議論、情報共有については、件名に【えんぷら部】と入れるようにして下さい。html5は、エンタープライズ分野にかぎらず、デザイン系、ゲーム系など、多くの分野を巻き込む懐の広いテクノロジーです。無関係な分野の方に頻繁にMLが行ってしまうことを避けられるよう、フィルタリングできる工夫をさせて下さい。</p>
<p>また、以前このMLでは、ちょっとした問題が発生したため、初投稿などでちょっとしたルールを作っています。詳しくは<a href="http://www.html5j.org/" target="_blank">html5jのサイト</a>でご確認下さい。</p>
<a href="https://groups.google.com/group/html5-developers-jp/subscribe" class="btn btn-primary btn-large" target="_blank">html5jエンタープライズ部に参加する »</a>
<div>

という部分だけを別のHTMLファイルに書き出すという意味です。 出来上がったファイル郡を参考として添付します。

f:id:albatrosary:20140625165737p:plain

ルーティングの設定

ルータ(js/main.js)は次の通りです。

angular
.module('html5jenterprise', [
'ngCookies',
'ngResource',
'ngRoute',
'ngSanitize'
])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/readme', {
templateUrl: 'views/readme.html',
controller: 'MainCtrl'
})
.when('/archive', {
templateUrl: 'views/archive.html',
controller: 'MainCtrl'
})
.when('/aboutus', {
templateUrl: 'views/aboutus.html',
controller: 'MainCtrl'
})
.otherwise({
redirectTo: '/'
});
});

あとは呼び出し元のHTMLで

<ul class="nav">
<li><a href="#/readme">ML投稿ルール</a></li>
<li><a href="#/archive">アーカイブ</a></li>
<li><a href="#/aboutus">この団体について</a></li>
<il>

と記載するだけです。所々出現するリンクは「#/hoge」に習って記載すれば良いということになります。

こうして出来たサイト

こうして生まれ変わったサイトがこれです。

html5jエンタープライズ部

見た目は何も変わってませんが「Single-page Applciation」です。静的なHTMLを配置するのは簡単ですが、そのメンテナンスは大変な労力を必要とします。Angular等のルータを利用すればこういった冗長であったものもすっきり解消することが可能です。

JavaScriptフレームワークを導入するのはデザイナー等だとハードルが高いと思われがちですが、使い方は簡単です。社内でも面倒なサイトのメンテナンスにはAngularをどうぞ。