<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="http://organizeseries.com/"
	>

<channel>
	<title>JavaScript &#8211; HTML5Experts.jp</title>
	<atom:link href="/tag/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>https://html5experts.jp</link>
	<description>日本に、もっとエキスパートを。</description>
	<lastBuildDate>Sat, 07 Jul 2018 03:14:05 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.7.19</generator>
	<item>
		<title>Vue.js製フレームワークNuxt.jsではじめるUniversalアプリケーション開発</title>
		<link>/potato4d/24346/</link>
		<pubDate>Fri, 13 Oct 2017 01:49:45 +0000</pubDate>
		<dc:creator><![CDATA[花谷拓磨]]></dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Nuxt.js]]></category>
		<category><![CDATA[Vue.js]]></category>

		<guid isPermaLink="false">/?p=24346</guid>
		<description><![CDATA[Vue.jsでUniversalなSPAを開発できるフレームワークであるNuxt.jsのバージョン 1.0のリリースがいよいよ近づいてきました。 本稿では、シングルページアプリケーション（以下 SPA）開発によって生じた...]]></description>
				<content:encoded><![CDATA[<p>Vue.jsでUniversalなSPAを開発できるフレームワークである<strong>Nuxt.js</strong>のバージョン 1.0のリリースがいよいよ近づいてきました。</p>

<p>本稿では、シングルページアプリケーション（以下 SPA）開発によって生じた問題を解決するために生まれたサーバーサイドレンダリング （以下 SSR）を中心に、Vue.jsでの開発を強力にサポートするNuxtについて、その魅力と基本的な使い方をご紹介いたします。</p>

<h2>Nuxt.jsとは？</h2>

<p><img src="/wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-19.12.30.png" alt="Nuxt.js org" class="alignnone size-medium wp-image-24392" srcset="/wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-19.12.30.png 640w, /wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-19.12.30-300x195.png 300w, /wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-19.12.30-207x135.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>Nuxt.js（ナクストと読みます）はReact.jsベースのSSR用フレームワークであるNext.jsに触発されて作成された、Vue.jsベースのフレームワークです。</p>

<p>特に<strong>UIの描画サポート</strong> に主眼をおき、SSRをはじめとした様々なサポートを行ってくれるものとなります。</p>

<ul>
<li><a href="https://nuxtjs.org/" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">https://nuxtjs.org/</a></li>
</ul>

<h2>Nuxt.jsでできること</h2>

<p>それではそのNuxt.jsではどのようなことができるのでしょうか。</p>

<p>現在挙げられている主な機能一覧としては以下のようなものがあります。<br />
（現在準備中のv1.0向け日本語訳プロジェクトから抜粋。私も一部関わっております）</p>

<blockquote style="background: #f0f0f0;padding-top:15px;padding-bottom:15px;margin-bottom: 20px">
  <ul style="margin-bottom:0">
    <li>Vueファイルで記述できること</li>
    <li>コードを自動的に分割すること</li>
    <li>サーバーサイドレンダリング</li>
    <li>非同期データをハンドリングするパワフルなルーティング</li>
    <li>静的ファイルの配信</li>
    <li>ES6/ES7のトランスパイレーション</li>
    <li>JSとCSSのバンドル及びミニファイ</li>
    <li>Head要素の管理</li>
    <li>開発モードにおけるホットリローディング</li>
    <li>SASS, LESS, Stylus などのプリプロセッサのサポート</li>
    <li>HTTP/2 push headers ready</li>
    <li>モジュール構造で拡張できること</li>
  </ul>
</blockquote>

<p>こうして見てみると、Nuxt.jsが提供する機能は <strong>「SSR 基盤の提供」</strong>と<strong>「コードを書きやすい環境を提供するもの」</strong> 、そして<strong>「拡張性の高い構造を提供するもの」</strong> の3つと考えることができます。</p>

<h4>SSR基盤としての優秀さ</h4>

<p>Vue.jsの2系からはコアでSSRのシステムを内蔵しており、単体でもSSRを行うことは可能ですが、より円滑に、かつ柔軟なシステムをNuxt.jsでは提供しています。</p>

<p>単純なレンダリングだけの場合はVue.jsのものを利用しても簡単におこなうことができますが、Nuxt.jsではそれに加えルールに基づいた自動的なルーティングやプリコンパイル、<pre class="crayon-plain-tag">&lt;meta&gt;</pre>タグの編集などが可能となっており、より効率的なSSR基盤の構築が可能となっています。</p>

<h3>モダンなVue.jsによる開発環境の提供</h3>

<p>Nuxt.jsでは、vue-loaderベースでのVue.jsでの標準的なコーディング環境や、 画像などのアセットのパスの解決、そしてSassなどのCSSプリプロセッサの対応など、webpackなどのビルドツールの設定を必要とするものが一通りサポートされています。</p>

<p>その上で、それらの基本的な構成をまとめたボイラープレートをnuxt-community/starter-templateとしてNuxt.jsコミュニティが公式で提供しており、webpackなどのモジュールバンドラやbabelなどのビルドシステムに精通していない人でも簡単にモダンな環境を構築することが可能となっています。</p>

<p>また、これらのテンプレートはVue.jsコミュニティ公式のスキャフォールディングツールである<pre class="crayon-plain-tag">vue-cli</pre>を利用してセットアップが可能となっており、すぐに開発をはじめることが可能です。</p>

<ul>
<li><a href="https://github.com/vuejs/vue-cli" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">https://github.com/vuejs/vue-cli</a></li>
<li><a href="https://github.com/nuxt-community/starter-template" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">https://github.com/nuxt-community/starter-template</a></li>
</ul>

<h3>ミドルウェアやasyncDataなどの拡張システムの提供</h3>

<p>また、Nuxt.jsでは、ミドルウェアやasyncDataという構造・システムを利用することで、SSR結果に非同期処理（例えばAPIからのデータフェッチ）の結果を出力・その後SPA側からデータストアとして参照できるシステムがあります。</p>

<p>これを利用することにより、記事データを取得した上でOGPとして出力を行うことや、i18n処理の結果をHTMLとして流すなど、様々なことができるようになります。</p>

<h2>Nuxt.jsを利用すべきシーン</h2>

<h3>メディアやSNS 、求人サイトなどをSPAとして立ち上げる場合・運用している場合</h3>

<p>SPAとして立ち上げるサイトやWebサービスの中では、SEOやOGP、Twitter Cardを重視すべきものというのは非常に多く存在します。</p>

<p>メディアサイトなどであれば、そもそもWordPressなどで運用するほうが筋が良い場合も多いでしょうが、SNSや求人サイトの場合は、SPAのほうが都合が良い場合も存在します。</p>

<p>SNSでの事例でいえば、今のTwitter Lite（モバイル版）ではReactが使われていたり、求人サービスであるSCOUTERなどはサービス全体をVue.jsのSPAとして構築されており、個々の投稿やアカウントなどの情報をSSRしたいであろうサービスが SPA 化されていることは多くなってきました。</p>

<p>そういった場合のSEO、OGP生成エンジンとして、比較的一般的なディレクトリ構成がなされているNuxt.jsを採用する、Nuxt.jsへと移行するというということは選択肢として十分現実的なものです。</p>

<ul>
<li><a href="https://mobile.twitter.com/" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">https://mobile.twitter.com/</a></li>
<li><a href="https://service.scouter.co.jp/" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">https://service.scouter.co.jp/</a></li>
</ul>

<h3>技術系ドキュメントの運営</h3>

<p>技術ドキュメントの運用にも有効活用が可能です。</p>

<p>Nuxt.jsには、独自の機能として<code>nuxt generate</code>が存在しており、このコマンドを利用すると、Nuxt.jsで作られたものを全て静的サイトとして、ルーティングをそのままに書き出すことが可能となります。</p>

<p>Markdownで原稿は管理を行い、Vue.jsの強力なコンポーネントシステムのもと、デザインを効率的に管理する。ということが可能です。Nuxt.jsの公式ドキュメントは、この手法にて管理されています。</p>

<ul>
<li><a href="https://nuxtjs.org/" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">https://nuxtjs.org/</a></li>
</ul>

<h3>いわゆる一般的なホームページ制作</h3>

<p>驚くかもしれませんが、一般的なホームページ制作においてもNuxt.jsは大きく貢献してくれます。</p>

<p>Vue.jsのコンポーネントでは<pre class="crayon-plain-tag">Scoped CSS</pre>を利用することが可能となっており、CSSの影響範囲についての考慮を最小限できるためコーディングのスピード化に貢献するほか、ライブリロードなどの効率的な開発基盤が既に整っているからです。</p>

<p>また、本稿では詳しくは紹介しませんが、Nuxt.jsはプログラムから呼び出すことも可能であるため、お問い合わせだけをExpress.jsで受けるということも実現可能です。</p>

<p>実際にPush7というサービスのWebサイトはi18n化をmiddlewareで、メール受け付けをExpressで実装しました。</p>

<ul>
<li><a href="https://push7.jp/" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">https://push7.jp/</a></li>
</ul>

<h2>Nuxt.jsをはじめる</h2>

<p>それではいよいよNuxt.jsを利用して実際にアプリケーションを作成してみましょう。</p>

<p>まずはサンプルプロジェクトを作成した後、実際にAPIと連携するWebサイトを構築してみます。</p>

<h3>プロジェクトのセットアップと実行</h3>

<p>プロジェクトの初期化にはvue-cliを利用しましょう。ターミナル上で以下を実行してください。</p>

<p></p><pre class="crayon-plain-tag">$ npm install -g vue-cli # 既に vue-cli を導入されているかたについては不要です
$ vue init nuxt-community/starter-template nuxt_sample</pre><p></p>

<p>これを行うことで実行したディレクトリに新たにnuxt_sampleという名前でプロジェクトが作成されます。</p>

<p>これで一通りのファイルはセットアップされていますので、そのまま依存関係をインストールしてサーバーを立ち上げてみます。</p>

<p>パッケージ管理については、Nuxt.js自体がYarnで管理されているため、個人的にはYarnを用いることを推奨します。</p>

<p></p><pre class="crayon-plain-tag">$ cd nuxt_sample
$ yarn
$ yarn dev</pre><p></p>

<p>実行した段階でプリコンパイルが実行され、完了次第 <a href="http://localhost:3000/" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">http://localhost:3000/</a> にてアクセスが可能であることが確認できるようになっています。実際にアクセスしてみます。</p>

<p><img src="/wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-21.07.09.png" alt="Nuxt Starter 初期ページ" class="alignnone size-medium wp-image-24393" srcset="/wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-21.07.09.png 640w, /wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-21.07.09-300x231.png 300w, /wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-21.07.09-207x159.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>このように表示された時点で成功です。</p>

<p><img src="/wp-content/uploads/2017/10/Screen-Shot-2017-10-10-at-0.20.57.png" alt="Nuxt Starter 初期ページ ソースコード" class="alignnone size-medium wp-image-24394" srcset="/wp-content/uploads/2017/10/Screen-Shot-2017-10-10-at-0.20.57.png 640w, /wp-content/uploads/2017/10/Screen-Shot-2017-10-10-at-0.20.57-300x231.png 300w, /wp-content/uploads/2017/10/Screen-Shot-2017-10-10-at-0.20.57-207x159.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>ページのソースコードを見ると、きちんとSSRされて結果が出力されていることがわかります。</p>

<h2>APIからデータを取得してSSRするページを作成する</h2>

<p>基本的なサーバーの起動はここまでで完了したので、ここからはルーティングの追加と非同期データの取得を行っていきます。</p>

<p>ここでは誰でも利用できるPublicなAPIとして、GitHubのユーザー情報を参照する API を利用し、ユーザー情報を表示してみます。要件としては、以下を満たすものの開発とします。</p>

<ul>
<li><a href="https://developer.github.com/v3/" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">https://developer.github.com/v3/</a> を利用したデータ取得を行う</li>
<li><pre class="crayon-plain-tag">/users/:id</pre>  形式でそれぞれのユーザーにアクセスする</li>
<li>ユーザー情報からIDと名前を取得し、アイコン画像と共に表示する</li>
</ul>

<h3>ルーティングを追加する</h3>

<p>まずはルーティングを追加してみます。</p>

<p>Nuxt.jsにはファイルに応じたルーティングの自動生成機能がありますので、これを有効活用して作成します。</p>

<p>今作ったnuxt_sampleのプロジェクトルート内の<pre class="crayon-plain-tag">pages/</pre>ディレクトリ内にusersディレクトリを作成し、さらにその中に _id.vueファイルを作成します。</p>

<p>内容については、index.vueの中身をコピーしておくと良いでしょう。</p>

<p><img src="/wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-21.47.57.png" alt="ディレクトリ構成" class="alignnone size-medium wp-image-24395" srcset="/wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-21.47.57.png 640w, /wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-21.47.57-300x211.png 300w, /wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-21.47.57-207x146.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>完成したディレクトリ構成はこのようになります。</p>

<p>このようにファイルを配置することで、Nuxt.jsがルーティングを解釈し、<pre class="crayon-plain-tag">/users/:id</pre>のリクエストについては全て_id.vue を参照するようになります。</p>

<p>さらに、アクセス時にURLパラメータのオブジェクト内にidというキー名で格納されます。</p>

<p>これを例えば_nickname.vueなどとした場合は、idの代わりにnicknameというキーで保存されます。</p>

<p>これでひとまずルーティングの作成は完了です。</p>

<h3>ページ内でHTTPリクエストを行い、結果を取得する</h3>

<p>次は_id.vueの中でGitHubからデータをフェッチしてみます。</p>

<p>まずはHTTPリクエストのためにaxiosをインストールします。</p>

<p></p><pre class="crayon-plain-tag">$ yarn add axios</pre><p></p>

<p>その上で、_id.vueを以下のように記述します。</p>

<p></p><pre class="crayon-plain-tag">&lt;template&gt;
  &lt;section class="container"&gt;
    &lt;img :src="`https://github.com/${user.login}.png`" :alt="user.name"&gt;
    &lt;h1&gt;{{user.name}}&lt;/h1&gt;
  &lt;/section&gt;
&lt;/template&gt;

&lt;script&gt;
import axios from 'axios'

export default {
  async asyncData ({ params }) {
    const { data: user } = await axios.get(`https://api.github.com/users/${params.id}`)
    return {
      user
    }
  }
}
&lt;/script&gt;

&lt;style&gt;
.container {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
  flex-direction: column;
}

.container img{
  margin-bottom: 20px;
  border-radius: 50%;
  overflow: hidden;
}
&lt;/style&gt;</pre><p></p>

<p>ここでポイントとなるのはasyncDataの記述です。</p>

<p>通常のVue.jsでは、データの保持について、 <pre class="crayon-plain-tag">data(){}</pre>形式で関数を定義し、その戻り値をデータとして利用しますが、これを <pre class="crayon-plain-tag">asyncData(){}</pre>に置き換えることで、SSR時に非同期のデータを取得した上で、SSRに流し込むことが可能となります。</p>

<p>また、Nuxt.jsではデフォルトでasync/awaitの変換用のbabel-presetも導入されていますので、モダンな記法でこのように取得することが可能となっております。</p>

<h3>実際に表示をみてみる</h3>

<p>ここまで完了した段階で、実際に表示を見てみましょう。</p>

<p>現在サーバーが立ち上がっているなら自動で読み込まれているためそのまま<pre class="crayon-plain-tag">/users/potato4d</pre>を。</p>

<p>もし一度落としているなら、再度<pre class="crayon-plain-tag">yarn dev</pre>を行った上で<br />
<pre class="crayon-plain-tag">/users/potato4d</pre> 
 にアクセスしてみましょう。</p>

<p><img src="/wp-content/uploads/2017/10/Screen-Shot-2017-10-10-at-1.21.19.png" alt="SSR 結果サンプル" class="alignnone size-medium wp-image-24396" srcset="/wp-content/uploads/2017/10/Screen-Shot-2017-10-10-at-1.21.19.png 640w, /wp-content/uploads/2017/10/Screen-Shot-2017-10-10-at-1.21.19-300x231.png 300w, /wp-content/uploads/2017/10/Screen-Shot-2017-10-10-at-1.21.19-207x159.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>このように表示されると成功です。</p>

<p><img src="/wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-23.51.17.png" alt="SSR 結果サンプルソースコード" class="alignnone size-medium wp-image-24397" srcset="/wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-23.51.17.png 640w, /wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-23.51.17-300x89.png 300w, /wp-content/uploads/2017/10/Screen-Shot-2017-10-09-at-23.51.17-207x61.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>ソースコードを見ると、正しくSSRされた結果が返ってきていることがわかります。</p>

<p>このように、asyncDataと、axiosなどのHTTPライブラリを組み合わせることによって、Web APIからの取得結果をSSRに流すことが可能となります。</p>

<p>これを用いることにより、例えばサービス内の投稿について、ツイートされたときにコンテンツを表示する。Twitter CardやOGPなどを正しく表示する。ということが可能となります。</p>

<p>最後に、このサンプルについては私のGitHub上に掲載しておりますので、お手元にすぐNuxt.jsを試す環境がない場合は適宜ご参照ください。</p>

<ul>
<li><a href="https://github.com/potato4d/nuxt_html5expertsjp" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">https://github.com/potato4d/nuxt_html5expertsjp</a></li>
</ul>

<h2>おわりに</h2>

<p>ここまででNuxt.jsの基本とできること・活躍しやすいシーンをご紹介した後に、簡単なサンプルアプリケーションを作るところまでを行ってみました。</p>

<p>実案件で投入する際は、新規でないとディレクトリやビルドシステムの移行コストがそれなりに存在しますが、新規においては効率的な開発にも大きく貢献し、将来的なSSR要望にも先んじて対応を行うことができます。</p>

<p>基本的にSPAの後からのSSR対応というものは非常にコストがかかるものでもありますので、これからのSPA開発においては、Nuxt.jsの存在は、開発効率化ツールとしても、また、SSRだけではない統合開発フレームワークとしても無視できないものになってくると考えております。</p>

<p>Nuxt.js単体がフロントエンド開発のフレームワークとして一定以上の存在意義をもつ未来や、ほかのNode.js製のフレームワークと組み合わせてのレンダリング用フレームワークとして利用される未来も十分にあるでしょう。</p>

<p>近々1.0のリリースが行われることで、rcにて大量にあったBreaking Changesについてもひとまずは収まることが予想されますし、日本語ドキュメントの1.0追従も盛んに行われております。</p>

<p>もし活躍できるシチュエーションに遭遇した時は、Nuxt.jsを是非利用してみると良いでしょう。</p>

<h2>参考資料</h2>

<p>本稿の執筆にあたって参照した情報ソースとなります。</p>

<ul>
<li>Nuxt.js 公式ページ（英語）

<ul>
<li><a href="https://nuxtjs.org/" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">https://nuxtjs.org/</a></li>
</ul></li>
<li>v1.0 時代の機能一覧 日本語訳

<ul>
<li><a href="https://gitlocalize.com/repo/100/ja/en/guide/index.md" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">https://gitlocalize.com/repo/100/ja/en/guide/index.md</a></li>
</ul></li>
<li>本稿で使用したスターターテンプレート

<ul>
<li><a href="https://github.com/nuxt-community/starter-template" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">https://github.com/nuxt-community/starter-template</a></li>
</ul></li>
<li>本稿で使用したスキャフォールディングツール

<ul>
<li><a href="https://github.com/vuejs/vue-cli" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">https://github.com/vuejs/vue-cli</a></li>
</ul></li>
<li>Nuxt.js 上での開発における babel の対応文法のソース（設定プリセット）

<ul>
<li><a href="https://github.com/vuejs/babel-preset-vue-app" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">https://github.com/vuejs/babel-preset-vue-app</a></li>
</ul></li>
</ul>
]]></content:encoded>
			</item>
		<item>
		<title>JSエンジン「V8」はバージョン6で世代移行を終える ── Google I/O 2017レポート</title>
		<link>/furoshiki/23289/</link>
		<pubDate>Tue, 12 Sep 2017 01:00:47 +0000</pubDate>
		<dc:creator><![CDATA[川田寛]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[Google I/O 2017]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[V8]]></category>

		<guid isPermaLink="false">/?p=23289</guid>
		<description><![CDATA[連載： Google I/O 2017特集 (3)ChromeやNode.jsで利用されているJavaScriptエンジン「V8」に、8年の歴史の中でも大きな変化が訪れました。8月3日にリリースされたバージョン6.1で、...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/google-io-2017/" class="series-450" title="Google I/O 2017特集" data-wpel-link="internal">Google I/O 2017特集</a> (3)</div><p>ChromeやNode.jsで利用されているJavaScriptエンジン「V8」に、8年の歴史の中でも大きな変化が訪れました。8月3日にリリースされたバージョン6.1で、数年かけて進めてきたJavaScriptコンパイラーが世代交代を終えました。詳しい話は、<a href="https://v8project.blogspot.jp/2017/08/v8-release-61.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">V8のブログでも語られていますが</a>、ここでは大きなトピックであるコンパイラーの世代交代についてお話します。</p>

<p>なお、この動きについては、<a href="https://www.youtube.com/watch?v=r5OWCtuKiAk" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">昨年に開かれたカンファレンス「BlinkOn 6」でも語られており</a>、Google I/O 2017でも、Seth Thompsonによるセッション「<a href="https://events.google.com/io/schedule/?section=may-18&amp;sid=06ad955b-2387-45b8-9a5b-9ebd00a6f952&amp;gclid=CKuXh-a6g9QCFVR9vQodz50B6g" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">V8, Advanced JavaScript, &amp; the next performance frontier</a>」によって紹介されています。本記事では、これらの発表内容を補足してご紹介します。</p>

<p><img src="/wp-content/uploads/2017/05/top.png" alt="" width="640" height="439" class="alignnone size-full wp-image-23339" srcset="/wp-content/uploads/2017/05/top.png 640w, /wp-content/uploads/2017/05/top-300x206.png 300w, /wp-content/uploads/2017/05/top-207x142.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<h1>V8のミッションとは？</h1>

<p>Chromeで使われているJavaScriptエンジン「V8」ですが、そのミッションはとてもシンプルです。</p>

<p>「Speed up real-world performance for modern JavaScript, and enable developers to build a faster future web.(実世界での要求にあわせてモダンなJavaScriptのパフォーマンスを向上させること。そして、今後の変化していくWebに早く追従し、開発者がそれらをビルドできるようにすること)」</p>

<h1>V8のパフォーマンス改善につきまとう2つのトレードオフ</h1>

<p>V8とはなんでしょう？JIT(just-in-time compile)で動作させることができるJavaScriptのエンジンです。ブラウザがJavaScriptを受け取ると、ブラウザはそのコードをトランスレートして実行したり。また、コードを翻訳してコンピューターが理解できるネイティブコードにコンパイルしてから実行します。</p>

<p>ただ、そこにはいくつかのトレードオフが存在します。</p>

<ol>
<li>コンパイルして生成されたネイティブコードは、実行されるピーク時の速度が早い一方で、コードの量が多いほど、最初に実行されるまでに遅延が発生する。一方で、トランスレーターを使った場合は、実行されるまでの遅延は小さいけど、実行時の速度が遅い。</li>
<li>JavaScriptエンジンは、パフォーマンスを良くしようとするとメモリの消費量が多くなる。一方で、省メモリを進めようとするとパフォーマンスは悪化する。</li>
</ol>

<p>例えば、以下のような一行のfunctionを呼び出すコードについて考えてみましょう。</p>

<p><img src="/wp-content/uploads/2017/05/02-1.png" alt="" width="640" height="330" class="alignnone size-full wp-image-23350" srcset="/wp-content/uploads/2017/05/02-1.png 640w, /wp-content/uploads/2017/05/02-1-300x155.png 300w, /wp-content/uploads/2017/05/02-1-207x107.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>このコードでは、 <code>function foo()</code> は一度しか呼び出されていませんよね。このケースでは、実行されるまでの速さ（Fast Startup）を重視し、実行時のパフォーマンス（Peak Perf）は重要視しません。</p>

<p>しかし、以下のケース。</p>

<p><img src="/wp-content/uploads/2017/05/03-1.png" alt="" width="640" height="350" class="alignnone size-full wp-image-23352" srcset="/wp-content/uploads/2017/05/03-1.png 640w, /wp-content/uploads/2017/05/03-1-300x164.png 300w, /wp-content/uploads/2017/05/03-1-207x113.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>1万回も <code>function foo()</code> を呼び出しています。このケースでは、Fast Startupが遅れてでも、Peak Perfを重視する必要がでてきます。 <code>foo()</code> はネイティブコードにコンパイルされていなくてはいけません。そしてそれがデスクトップ型のコンピューターであれば、メモリも潤沢なので、大量のメモリ消費を犠牲にネイティブコードをさらに幾度に渡り最適化させます。</p>

<p>ただ、これはあくまでデスクトップ型コンピューターの場合。同じ1万回 <code>foo()</code> を呼び出すコードであっても、モバイルの場合は同じアプローチにはなりません。Androidデバイスはモバイルなので、デスクトップと同じようにメモリを扱うことはできません。</p>

<p><img src="/wp-content/uploads/2017/05/04.png" alt="" width="640" height="428" class="alignnone size-full wp-image-23356" srcset="/wp-content/uploads/2017/05/04.png 640w, /wp-content/uploads/2017/05/04-300x201.png 300w, /wp-content/uploads/2017/05/04-207x138.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>ネイティブのコードへコンパイルはされますが、メモリの消費量は抑えられるよう最適化は制限されます。</p>

<p>別のパターンについても考えてみましょう。それが以下のコード。</p>

<p><img src="/wp-content/uploads/2017/05/05.png" alt="" width="640" height="399" class="alignnone size-full wp-image-23358" srcset="/wp-content/uploads/2017/05/05.png 640w, /wp-content/uploads/2017/05/05-300x187.png 300w, /wp-content/uploads/2017/05/05-207x129.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>これはNode上で実行されているコードです。一度起動されたら、ずっと利用されるわけですから、当然、Fast Startupを犠牲にしてPeak Perfを改善しようとしますね。しかし…</p>

<p><img src="/wp-content/uploads/2017/05/06.png" alt="" width="640" height="397" class="alignnone size-full wp-image-23360" srcset="/wp-content/uploads/2017/05/06.png 640w, /wp-content/uploads/2017/05/06-300x186.png 300w, /wp-content/uploads/2017/05/06-207x128.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>IoTデバイス上で動作するとなると、同じ状況とは言えません。サーバー用マシンとは異なり、メモリ消費は抑えなくてはいけません。Peak Perfを上げるようにはしますが、それはメモリ消費が少なくて済むようなアプローチで進めます。</p>

<p>同じ一行のfunction呼び出しであっても、その最適化方法は無数にあり、コンテキストやデバイスの状況に強く依存するのです。そしてそれは、Fast Startupなのか、あるいはPeak Perfに最適化していくのか、メモリを富豪的に扱うのか、それとも小さくなるよう努力するのか、解決しなくてはいけません。</p>

<h1>8年前のリリース時点から全てが変わろうとしているV8</h1>

<p>V8エンジンは、ここまでに説明したあらゆる状況で最適化できるようにしたり、また新しいパターンのJavaScript（asm.js, WebAssembly等）に対応できるよう、2〜3年かけて実行パイプラインを作り変えました。</p>

<p>過去の変遷を見てみると。</p>

<p>2008年のリリース時点の段階では、シンプルなコードジェネレーターがあって、そこからやや最適化を行ったマシンコードが生成されるだけでした。あらゆるJavaScriptのコードは、この仕組を使って実行されます。</p>

<p>ただ、最適化には計算が必要なため、コードを実行できる状態にするまでに多くの時間を要します。大量のJavaScriptコードを扱う場合は、Startup Time短縮するために最適化の処理をスキップすることが求められます。</p>

<p><img src="/wp-content/uploads/2017/06/c01.png" alt="" width="640" height="295" class="alignnone size-full wp-image-23697" srcset="/wp-content/uploads/2017/06/c01.png 640w, /wp-content/uploads/2017/06/c01-300x138.png 300w, /wp-content/uploads/2017/06/c01-207x95.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>2010年にコンパイラ「Crankshaft」が追加されます。計算コストの高い最適化処理を分離し、Crankshaftにその責務が委譲されました。コードの生成だけであれば、Full-codegenは最小のコストでマシンコードを吐き出すため高速なため、Startup Timeが最適化されます。そして、CrankShaftを使ってコンパイルすれば、計算コストを犠牲にPeak Perfにとって最適なマシンコードが生成されます。</p>

<p>実行時に、CrankShaftが吐き出したコードを、Full-codegenが吐き出したコードへ置き換えることで最適化を図ります。</p>

<p><img src="/wp-content/uploads/2017/06/c03.png" alt="" width="640" height="328" class="alignnone size-full wp-image-23698" srcset="/wp-content/uploads/2017/06/c03.png 640w, /wp-content/uploads/2017/06/c03-300x154.png 300w, /wp-content/uploads/2017/06/c03-207x106.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>2015年。Crankshaftには限界が来ます。JavaScriptの仕様そのものが大きく変化する時代になりましたが、Crankshaftはその設計上、JavaScriptの機能をサポートしきれず、また新しいパターンのJavaScript（asm.js, WebAssembly等）にも十分に対応できませんでした。当時のフロントエンドエンジニアなら、V8のECMAScript標準への対応の遅れに苛立ちを感じたはずです。</p>

<p>V8開発チームは、それを改善しようと新たなコンパイラ「TurboFan」を追加します。</p>

<p><img src="/wp-content/uploads/2017/06/c04.png" alt="" width="640" height="326" class="alignnone size-full wp-image-23699" srcset="/wp-content/uploads/2017/06/c04.png 640w, /wp-content/uploads/2017/06/c04-300x153.png 300w, /wp-content/uploads/2017/06/c04-207x105.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>2016年。「Ignition」と呼ばれる仕組みを追加しました。Ignitionには、ソースコードをいきなりマシンコードにするのではなく、バイトコード(マシンコードほどハードウェアに依存しない「中間コード」と呼ばれるもの)を生成するコンパイラーと、それを実行するインタプリターが内包されています。</p>

<p>そして、TurboFanはバイトコードを扱う形へと作り変えられました。そして現在、最新のVersionである5.9では、この2つの仕組みは既に使われていません。内部にコードこそ存在していますが、バイトコードの生成と解釈するインタープリターIgnitionと、PeakPerfを改善するための処理をするコンパイラーTurboFanだけで動作しているという状況です。</p>

<p><img src="/wp-content/uploads/2017/06/c05.png" alt="" width="640" height="325" class="alignnone size-full wp-image-23701" srcset="/wp-content/uploads/2017/06/c05.png 640w, /wp-content/uploads/2017/06/c05-300x152.png 300w, /wp-content/uploads/2017/06/c05-207x105.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>そして、これからまもなくリリースされる6.0では、コードとして完全にV8から削除されます。</p>

<p><img src="/wp-content/uploads/2017/06/c06.png" alt="" width="640" height="312" class="alignnone size-full wp-image-23702" srcset="/wp-content/uploads/2017/06/c06.png 640w, /wp-content/uploads/2017/06/c06-300x146.png 300w, /wp-content/uploads/2017/06/c06-207x101.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<h3>「Ignition Interpreter」とは？</h3>

<p>中間コードを生成して実行するインタプリター。メモリ消費が小さく動く、Fast Startupも最適という特徴があります。</p>

<ul>
<li>モバイルなどのメモリの小さな環境で動かすのに最適。</li>
<li>Startup Timeに最適化すべきコードの実行に向いている。</li>
<li>TurboFanと組み合わせることで、実行速度を最適化できる。</li>
</ul>

<h3>「TurboFan」とは？</h3>

<p>主として、最適化を行うことを目的としたコンパイラー。</p>

<ul>
<li>使われ方としては、拡張的な感じ。ただ、あらゆる新しいJavaScript機能に対応していき、その場合も活用される。</li>
<li>WebAssemblyのバックエンドでもある。</li>
<li>最近はtry/catch/finallyとか、ES2015+の最適化が可能になった。</li>
</ul>

<h1>まとめ</h1>

<p>V8について、メモリ管理向けガーベジコレクター「Orinoco」など、さまざまな技術要素が進化し、語り尽くせないほどのトピックがあるのですが、それはまた別の機会にお話しましょう。TurboFanへの完全移行、実態としてすでにほとんど終わった状況といっても過言ではありませんが、8年前とは全く異なる、Web・JavaScriptの変化に追従する大きな変化です。今後も楽しみですね。</p>
]]></content:encoded>
		
		<series:name><![CDATA[Google I/O 2017特集]]></series:name>
	</item>
		<item>
		<title>Node.jsでSlack Command Botをつくってみよう</title>
		<link>/girlie_mac/22535/</link>
		<pubDate>Fri, 03 Mar 2017 00:00:22 +0000</pubDate>
		<dc:creator><![CDATA[Tomomi Imura]]></dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[ECMAScript]]></category>
		<category><![CDATA[ES6]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[Slack]]></category>
		<category><![CDATA[UX]]></category>
		<category><![CDATA[bot]]></category>
		<category><![CDATA[海外]]></category>

		<guid isPermaLink="false">/?p=22535</guid>
		<description><![CDATA[こんにちは。ごぶさたしています。以前の執筆から１年ちょっとになるのですが、その当時はInternet of Things(IoT)について書いたのですが、最近では市場がある程度まで到達したからでしょうか、それとも脆弱性の...]]></description>
				<content:encoded><![CDATA[<p>こんにちは。ごぶさたしています。以前の執筆から１年ちょっとになるのですが、その当時はInternet of Things(IoT)について書いたのですが、最近では市場がある程度まで到達したからでしょうか、それとも脆弱性の問題を問われることが多くなったせいでしょうか、話題は少し落ち着いてきたかに思われます。さて今ホットな話題は何でしょうか、ということで今回はChat Botsについて書いてみようと思います。</p>

<h3>E-Commerceから Conversational Commerceへ</h3>

<p>ここ最近話題になることが多いAIやBotsですが、私の周りではConversational interface、Conversational UXなどという言葉が去年からたびたび使われるようになっているようです。</p>

<p>これはAmazon Alexaなどのデバイスや、Facebook Messengerなどチャットアプリケーションなどの対話型テクノロジーをいかに活用しその使い勝手をよくするか、ということなのですが、必ずしもアプリケーションのUIデザインそのものを述べているわけではなく、既存のサービスを延長することを指していることも多いでしょう。例えば、今まではモバイル上のアプリケーションのみで車を呼べていたUberが、<a href="https://newsroom.uber.com/messengerlaunch/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Facebook Messenger のチャットからも車をを呼べるような機能</a>を加えたり、Slack上でTaco Bellからタコスをオーダーできる<a href="https://www.tacobell.com/feed/tacobot" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">TacoBot</a>、というのもが挙げられます。</p>

<h3>Slack Botを書いてみよう</h3>

<p>さて、というわけで何かBotを書いてみたいと思いませんか？ここはNode.jsでSlack botを作成する方法を紹介したいと思います。</p>

<p>このチュートリアルでは、ディベロッパー向けのHTTPステータスコードのルックアップができるスラッシュ・コマンドを作ってみます。ここでは私が５年ほど前に何気なく作って、Mashableなどで紹介され思わぬ反響を得てしまった<a href="http://http.cat/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">HTTP Status Cats</a>を使ってみます。具体的には、Slack上でユーザが、<code>/httpstatus [code]</code> （例えば <code>/httpstatus 404</code>）と入力すると、そのステータスコードの意味と猫が一緒に表示される、という簡単なbotです。</p>

<p>まず試してみたい方は、<a href="http://www.girliemac.com/slack-httpstatuscats/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">HTTP Status Cats command for Slack</a>を自分がアドミン権限のあるのチャットチームにインストールしてみてください。</p>

<p><img src="/wp-content/uploads/2017/02/slack-httpstatuscats.gif" alt="slack-httpstatuscats gif animation" width="640" height="437" class="aligncenter size-full wp-image-22558" /></p>

<p>さて、このチュートリアルは２つのパートに分けられます。</p>

<ol>
<li>スラッシュ・コマンドを書いて、自分のSlackチームにインストールする
<li>OAuthを使ってボットを<a href="https://slack.com/apps" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Slack&#8217;s App Directory</a>などで誰もがインストールできるようにする</ol>

<p></ol></p>

<p>とりあえず動くbotを書いてみたい、と思う方は１だけ試してみてで十分ですが、botをみんなにシェアしたい方は２も読んでみてください。</p>

<p><a href="https://github.com/girliemac/slack-httpstatuscats" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ソースコード</a>と実際のボットのインストールボタンは両方GitHubにあります。では始めましょう！</p>

<h2>1 プライベートなスラッシュコマンドボットの作成</h2>

<p>ここで作るのは、Slackの公式な用語でいうところの<a href="https://api.slack.com/custom-integrations" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Custom Integrations</a>というもので、自分のチャットグループ専用のプライベートなbot、もしくはいわゆるAppとして発表する前にドライ・ランを行うことを指します。アカウントを持っていない方はまずサインアップしてから始めましょう。</p>

<h3>1.1 スラッシュコマンドの設定</h3>

<p>ログインして、<a href="https://my.slack.com/services/new/slash-commands" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">my.slack.com/services/new/slash-commands</a>でコマンドを選びます。ここでは<code>/httpstatus</code>と入力し<strong>Add Slash Command Integration</strong>ボタンをクリックして次のステップへ進みます。</p>

<p>Tokenなどの欄がありますが現時点では、(1) Command、 (2) URL、 (3) Method、の３つが必要になります。</p>

<p><img src="/wp-content/uploads/2017/02/slack-config-custom-integration.png" alt="slack-config-custom-integration" width="431" height="640" class="aligncenter size-full wp-image-22561" srcset="/wp-content/uploads/2017/02/slack-config-custom-integration.png 431w, /wp-content/uploads/2017/02/slack-config-custom-integration-202x300.png 202w, /wp-content/uploads/2017/02/slack-config-custom-integration-139x207.png 139w" sizes="(max-width: 431px) 100vw, 431px" /></p>

<p>(1)には、<code>/httpstatus</code>、(3)には、<code>POST</code>、そして(2)のURLは次のように設定してください。</p>

<p>開発中に使用するURLを取得するには<a href="https://ngrok.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ngrok</a>を使ってみましょう。いろいろなツールがあるのですが、これは自分のローカルホストをパブリックURLとしてトンネルできるというとても便利なツールなので私のイチオシです。開発途中にデプロイすることなく、Webhookが手軽に使えます。自分のローカルホスト、たとえば  <code>http://localhost:3000/</code> をつかったままOAuthのテストもできるのです。（注：よく聞かれるのですが、ngrokはあくまでも開発ツールですのでプロダクションには適していません。デプロイメントに関しては最後の章を読んでください）</p>

<p><a href="https://ngrok.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://ngrok.com/</a>から自分のマシンにngrokをインストールしたら、ターミナルで自分の使いたいポート番号（このチュートリアルでは 3000）を設定します。</p>

<p></p><pre class="crayon-plain-tag">$ ngrok http 3000</pre><p></p>

<p>すると下のスクリーンショットのように、Forwardingアドレスが取得できるので、そのURL（例えば<a href="https://71f03962.ngrok.io/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://71f03962.ngrok.io/</a>)をSlackセッティングの、上のスクリーンショットで示された(2)の欄で使います。</p>

<p><img src="/wp-content/uploads/2017/02/ngrok.png" alt="ngrok" width="640" height="349" class="aligncenter size-full wp-image-22538" srcset="/wp-content/uploads/2017/02/ngrok.png 640w, /wp-content/uploads/2017/02/ngrok-300x164.png 300w, /wp-content/uploads/2017/02/ngrok-207x113.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>すべての設定が終えたらSaveボタンを押します。&#8221;Your settings have been saved!&#8221;のメッセージが画面上部に現れるのを確認してください。</p>

<h3>1.2 Node.js を使ってレスポンスを書く</h3>

<p>基本的にbotは、ユーザがSlackインターフェイス上でコマンドを実行した際HTTP POST（または設定次第では GET)によって指定先のURLにメッセージが届け、プログラムでその応答をユーザに返す、という作業になります。</p>

<p>たとえばそのユーザが<code>/httpstatus 302</code>というコマンドを送信した場合、指定URLに送られるデータは次のようになります。</p>

<p></p><pre class="crayon-plain-tag">command=/httpstatus
text=302
response_url=https://hooks.slack.com/commands/1234/5678
…</pre><p></p>

<p>Botは、これに対する応答をユーザに返します。この場合はユーザが尋ねているステータス302の定義と<a href="https://http.cat/302" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">この猫</a>を返しましょう。</p>

<p>ではそのコードを書いてみましょう。</p>

<p>まず、<strong>Express.js</strong>と<strong>body-parser</strong>をインストールします。</p>

<p></p><pre class="crayon-plain-tag">$ npm install express body-parser --save</pre><p></p>

<p><strong>index.js</strong>で、<code>express</code>のインスタンスを作り、先ほどngrokで設定したポート番号、3000でサーバを始動します。</p>

<p></p><pre class="crayon-plain-tag">'use strict';
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

const server = app.listen(3000, () =&gt; { 
console.log('Express server listening on port %d in %s mode', server.address().port, app.settings.env);});</pre><p></p>

<p>次はHTTP POSTルートメソッドで、コマンドを扱います。</p>

<p></p><pre class="crayon-plain-tag">app.post('/', (req, res) =&gt; {
 let text = req.body.text;
 // ここでbotを書きます
});</pre><p></p>

<p>ここで<code>text</code>の値を取得します。HTTP Status botの場合、<code>/httpstatus</code> コマンドの値、例えば&#8221;404&#8243;が <code>text</code>の値になります。同時に、ユーザが数字以外を入力した際にエラーメッセージを送るなどのエラーチェックもしておきましょう。</p>

<p></p><pre class="crayon-plain-tag">if(! /^\d+$/.test(q.text)) { // not a digit
 res.send('Error: enter a valid status code, such as 200');   
 return;
}</pre><p></p>

<p>このエラーは、ユーザだけにプライベートに送信されるメッセージでチャットそのものには表示されません。</p>

<p>エラーがない場合は、コマンドに対する応答をJSONとしてレスポンスします。</p>

<p></p><pre class="crayon-plain-tag">let data = {
 response_type: 'in_channel', 
 text: '302: Found',
 attachments:[{
   image_url: 'https://http.cat/302.jpg'
 }]
};
res.json(data);</pre><p></p>

<p><code>response_type</code>を<code>in_channel</code>とすることで応答はチャットメンバー全員に見えるように送信されます。デフォルトはその逆の<code>ephemeral</code>で、コマンドを送ったユーザのみに表示されます。</p>

<p>このコマンドと応答は次のようになります。</p>

<p><img src="/wp-content/uploads/2017/02/slack-command.png" alt="slack-command" width="640" height="491" class="aligncenter size-full wp-image-22540" srcset="/wp-content/uploads/2017/02/slack-command.png 640w, /wp-content/uploads/2017/02/slack-command-300x230.png 300w, /wp-content/uploads/2017/02/slack-command-207x159.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>このサンプルコードでは、応答をわかりやすくハードコードで示してありますが、実際はストリングなどは別のファイルに定義しています。下のスクリーンショットのように存在しないHTTPステータスに対してのエラーメッセージも定義しましょう。実際のコードは<a href="https://github.com/girliemac/slack-httpstatuscats" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ソースコード</a>を参照してください。</p>

<p><img src="/wp-content/uploads/2017/02/slack-command-private.png" alt="slack-command-private" width="640" height="60" class="aligncenter size-full wp-image-22539" srcset="/wp-content/uploads/2017/02/slack-command-private.png 640w, /wp-content/uploads/2017/02/slack-command-private-300x28.png 300w, /wp-content/uploads/2017/02/slack-command-private-207x19.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>ディスプレイはボーダー色などのカスタマイズが可能です。詳しくはSlackドキュメンテーションの<a href="https://api.slack.com/docs/message-formatting" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Basic message formatting</a>を参照してください。</p>

<p>次のステップでは、このボットを自分のチャットグループ以外に配布するために必要な認証とコードのデプロイについてです。</p>

<h2>2. Slack Botのディストリビューション</h2>

<p>この「Custom Integration」をインストール可能な「App」にするには、コードのデプロイをして他のチャットにもインストールできるようにせねばならないのですが、そのためにはあといつくかのステップが必要になります。</p>

<h3>2.1 Appセットアップ</h3>

<p>まず、自分のAppを申請し、クライアントIDやシークレットなどのクレデンシャルを取得します。<a href="https://api.slack.com/apps" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://api.slack.com/apps</a>で<strong>Create an App</strong>ボタンをクリックしてください。</p>

<p><img src="/wp-content/uploads/2017/02/slack-create-app.png" alt="slack-create-app" width="614" height="640" class="aligncenter size-full wp-image-22542" srcset="/wp-content/uploads/2017/02/slack-create-app.png 614w, /wp-content/uploads/2017/02/slack-create-app-288x300.png 288w, /wp-content/uploads/2017/02/slack-create-app-199x207.png 199w" sizes="(max-width: 614px) 100vw, 614px" /></p>

<p>このフォームにはいくつもの欄があり少しわかりづらいのですが、スラッシュコマンドのbotには次の3つが最低必要になります。</p>

<ul>
<li><strong>Basic Information</strong> (at <a href="https://api.slack.com/apps/YOUR_APP_ID/general%29" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://api.slack.com/apps/YOUR_APP_ID/general)</a></li>
<li><strong>OAuth &amp; Permissions</strong> (at …/YOUR_APP_ID/oauth)</li>
<li><strong>Slash Commands</strong> (at …/YOUR_APP_ID/slash-commands)</li>
</ul>

<h3>2.1.1 API Keyを.envファイルに保管</h3>

<p>ここで取得した<code>Client ID</code>、<code>Client secret</code>、<code>Verification token</code>は <strong>.env</strong> ファイルに別に保管してbotのメインのコードから切り離すことを推奨します。gitを使う場合は、このファイルを <strong>.gitignore</strong> ファイルに付け加えるのを忘れずに。</p>

<p></p><pre class="crayon-plain-tag">SLACK_CLIENT_ID=12345XXXXX.09876XXXXX 
SLACK_CLIENT_SECRET=535d2f9....
SLACK_VERIFICATION_TOKEN=42P829U...</pre><p></p>

<h3>2.1.2 Foremanを使う</h3>

<p>他にも手段はありますが、<a href="https://heroku.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Heroku</a>にデプロイするために私は<a href="http://strongloop.github.io/node-foreman/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Node Foreman</a>を使っています。Foremanを使うには、npmを使ってglobalフラッグでインストールしてください。</p>

<p></p><pre class="crayon-plain-tag">$ npm install -g foreman</pre><p></p>

<p>アプリケーションの Root に <code>.procfile</code> を作成し、この一行を加えます。</p>

<p></p><pre class="crayon-plain-tag">web: node index.js</pre><p></p>

<p>index.jsを実行するには <code>node index.js</code>の代わりに次のコマンドを使います。</p>

<p></p><pre class="crayon-plain-tag">$ nf start</pre><p></p>

<h2>2.2 ユーザの認証</h2>

<p>Slackは認証には<a href="https://oauth.net/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">OAuth</a>を使っています。実際には自分でOAuthを実装しなくても、<a href="https://api.slack.com/docs/slack-button" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Slack ボタン</a>を使えば簡単に認証できるようになっています。</p>

<p>公式のドキュメンテーションのダイアグラムに手を加えて、流れをわかりやすくするためにGIFアニメーションにしてみました。</p>

<p><img src="/wp-content/uploads/2017/02/slack-oauth-1.gif" alt="slack-oauth gif animation" width="640" height="387" class="aligncenter size-full wp-image-22559" /></p>

<p>ここでの実際のフローは次のようになります。</p>

<ol>
<li>ウェブページを作成し、認証ボタンを置く。ユーザがボタンをクリックするとパラメータがSlackに送信される(ユーザは認証ページにリダイレクトされる)。
<li>Node appには、SlackからGETで10分だけ有効な仮のコードが送られる。
<li>アクセストークンを得るために <a href="https://api.slack.com/methods/oauth.access" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">oauth.access</a> API使い認証コードをPOSTする。Node app側から`200 OK`を受け取り次第、このプロセスが完了。
<li>オプションとして、このトークンを使ってSlackの他のAPIにもアクセス。例えば、認証後、ユーザをhttps://team-name.slack.comにリダイレクトするなど。/
</ol>

<h3>2.2.1 Slack ボタンの設定</h3>

<p>Slackボタンを使うには、まずウェブページを作成してください。私の場合はこのNode Appとは切り離した別のHTMLページを作成し、<a href="http://www.girliemac.com/slack-httpstatuscats/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">GitHub Pages</a>にホストしました。</p>

<p>次にボタンを設定しましょう。 <a href="https://api.slack.com/docs/slack-button" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://api.slack.com/docs/slack-button</a> に行き、<strong>Add the Slack button</strong> までスクロールして下さい。</p>

<p><img src="/wp-content/uploads/2017/02/slack-generate-button.png" alt="slack-generate-button" width="640" height="268" class="aligncenter size-full wp-image-22543" srcset="/wp-content/uploads/2017/02/slack-generate-button.png 640w, /wp-content/uploads/2017/02/slack-generate-button-300x126.png 300w, /wp-content/uploads/2017/02/slack-generate-button-207x87.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>このボタン作成ツールの<strong>Commends</strong>のチェックボックスをチェックします。</p>

<p>上で示したフローの４を実行したい場合は、このGETパラメータを下のように変更します。</p>

<p></p><pre class="crayon-plain-tag">&lt;a href="https://slack.com/oauth/authorize?scope=commands+team%3Aread&amp;client_id=your_client_id"&gt;</pre><p></p>

<p>ここで<code>scope</code>に着目してみてください。<code>commands</code>の他に<code>team:read</code>(コロンは<strong>%3A</strong>とエスケープ)が必要になります。詳しくは<a href="https://api.slack.com/docs/oauth-scopes" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">OAuth scopes on the Slack API docs</a>で。</p>

<p><img src="/wp-content/uploads/2017/02/slack-button.png" alt="slack-button" width="139" height="40" class="aligncenter size-full wp-image-22548" /></p>

<h3>2.2.2 トークンの発行</h3>

<p>さて、Nodeコードに戻りましょう。仮のコード(<code>req.query.code</code>)をGETで取得するためにまたExpress.jsを使います。</p>

<p>何でもよいのですがここでは<code>/slack</code> routeを使いましょう。この場合ngrokのURL は <code>http://71f03962.ngrok.io/slack</code> のようになります。Slack App設定ページ（https://api.slack.com/apps/YOUR_APP_ID/oauth）の、<strong>OAuth &amp; Permissions</strong> セクションにある、<em>Redirect URL</em>の欄にはこのURLを設定してください。</p>

<p>仮の<code>code</code>を取得されたら、それを自分のAPIクレデンシャルとともにPOSTで送って、トークンと交換します。POSTするためにここではNode.jsのHTTPリクエストクライアントである、<code>Request</code>を使いましょう。</p>

<p></p><pre class="crayon-plain-tag">$ npm install request --save</pre><p></p>

<p>仮の<code>code</code>を取得し、それを<code>token</code>と交換するコードが下になります。</p>

<p></p><pre class="crayon-plain-tag">const request = require('request');

app.get('/slack', function(req, res){
 let data = {form: {
   client_id: process.env.SLACK_CLIENT_ID,
   client_secret: process.env.SLACK_CLIENT_SECRET,
   code: req.query.code
 }};

 request.post('https://slack.com/api/oauth.access', data, function (error, response, body) {
   if (!error &amp;&amp; response.statusCode == 200) {
     // おしまい！
     // ここからはオプションでチーム情報を取得
     let token = JSON.parse(body).access_token; // Auth token
   } ...</pre><p></p>

<h3>2.2.3 オプショナル： ユーザをチームURLにダイレクトする</h3>

<p>認証が済んだらそこで終えてもよいのですが、この画面でユーザを置き去りにするのはあまりよいUXとはいえないので、チームページにリダイレクトしてみましょう。</p>

<p>リダイレクトURLのサブドメインとなるチーム名は<a href="https://api.slack.com/methods/team.info" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">team.info</a>APIで取得できます。</p>

<p>このAPIを使うにはトークンが必要なので前述のコードでの、トークンにアクセスする箇所に下のコードを追加します。</p>

<p></p><pre class="crayon-plain-tag">...
request.post('https://slack.com/api/team.info', {form: {token: token}}, function (error, response, body) {
 if (!error &amp;&amp; response.statusCode == 200) {
   let team = JSON.parse(body).team.domain;
   res.redirect('http://' +team+ '.slack.com');
 }
});</pre><p></p>

<p>これで API からチーム名(<code>team.domain</code>)が返されました。最終的にこれを使ってチームURLにリダイレクトしてできあがり！</p>

<p>このチュートリアルでは簡素化したコードを使いましたが、<a href="https://github.com/girliemac/slack-httpstatuscats" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">全ソースコードはGitHubで</a>見てみてください。</p>

<h2>2.3 サーバにデプロイする</h2>

<p>最後にデプロイしておしまいです。APIクレデンシャルの<strong>env vars</strong>設定を忘れないように！私はHerokuを使っているのですが、Herokuの場合、<code>heroku config</code>コマンドを使います。例えば、<code>heroku config:set API_KEY=123456</code>というふうに設定してください。</p>

<p>Slackの設定で画面で指定したngrok URLを、デプロイ先のURLに変更するのもお忘れなく。</p>

<p>さて、プロセスが少し面倒ですが、コード自体は簡単だったと思います。もし何か面白いボットを作った際にはぜひ教えてくださいね！</p>

<p><img src="/wp-content/uploads/2017/02/slack-worked.png" alt="slack-worked" width="200" height="200" class="aligncenter size-full wp-image-22546" srcset="/wp-content/uploads/2017/02/slack-worked.png 200w, /wp-content/uploads/2017/02/slack-worked-150x150.png 150w" sizes="(max-width: 200px) 100vw, 200px" /></p>
]]></content:encoded>
			</item>
		<item>
		<title>VR成功の鍵はWebVRにあり！？ ── HTML5 Conference 2016セッションレポート</title>
		<link>/edo_m18/21153/</link>
		<pubDate>Thu, 20 Oct 2016 00:00:07 +0000</pubDate>
		<dc:creator><![CDATA[比留間 和也]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[WebGL]]></category>
		<category><![CDATA[WebVR]]></category>

		<guid isPermaLink="false">/?p=21153</guid>
		<description><![CDATA[連載： HTML5 Conference 2016 特集 (3)セッション内容を講演者自らが解説するという「HTML5 Conference 2016特集」の第三弾。今回のテーマは「Webのグラフィックス後編: WebG...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/html5-conf2016/" class="series-403" title="HTML5 Conference 2016 特集" data-wpel-link="internal">HTML5 Conference 2016 特集</a> (3)</div><p>セッション内容を講演者自らが解説するという「<a href="https://html5experts.jp/series/html5-conf2016/" data-wpel-link="internal">HTML5 Conference 2016特集</a>」の第三弾。今回のテーマは「<a href="http://events.html5j.org/conference/2016/9/session/#session_id_b3" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Webのグラフィックス後編: WebGL2、そしてWebVR</a>」。<br />
すでに策定が始まっている次期バージョンWebGL2.0のお話や、WebでVRを実現する「WebVR API」を用いてVRコンテンツの実装の仕方を解説します。</p>

<p><img src="/wp-content/uploads/2016/10/DSC06585.jpg" alt="" width="600" height="388" class="aligncenter size-full wp-image-21443" srcset="/wp-content/uploads/2016/10/DSC06585.jpg 640w, /wp-content/uploads/2016/10/DSC06585-300x194.jpg 300w, /wp-content/uploads/2016/10/DSC06585-207x134.jpg 207w" sizes="(max-width: 600px) 100vw, 600px" /></p>

<h2>VRとは？</h2>

<p>今年、2016年はVR元年と言われ、様々なVRデバイス、VR関連ガジェット、VRコンテンツが世に生み出されています。  しかし、VR発祥は意外と古く、遡ること1960年代にVRの基礎となる理論、デバイスが発表されています。</p>

<p>ただ当時は個人で手が出るものではなく、体験自体はデパートのアトラクションとして登場するなど、体験は限定的でした。</p>

<p><img src="/wp-content/uploads/2016/10/352930-sensorama-1962-242x300.jpg" alt="352930-sensorama-1962" width="242" height="300" class="alignnone size-medium wp-image-21157" srcset="/wp-content/uploads/2016/10/352930-sensorama-1962-242x300.jpg 242w, /wp-content/uploads/2016/10/352930-sensorama-1962-167x207.jpg 167w, /wp-content/uploads/2016/10/352930-sensorama-1962.jpg 400w" sizes="(max-width: 242px) 100vw, 242px" /><br />
<a href="http://www.pcmag.com/slideshow/story/321996/12-vr-headsets-that-predate-oculus-don-t-tell-facebook/1" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">参考</a></p>

<p>時を戻して2016年。世界が動き出します。<br />
2016年6月時点のGoogle検索トレンドでは、検索回数が飛躍的に伸びているのが見てとれます。</p>

<p><img src="/wp-content/uploads/2016/10/unnamed-640x228.png" alt="unnamed" width="640" height="228" class="aligncenter size-large wp-image-21159" srcset="/wp-content/uploads/2016/10/unnamed.png 640w, /wp-content/uploads/2016/10/unnamed-300x107.png 300w, /wp-content/uploads/2016/10/unnamed-207x74.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>きっとこれを読まれている方も、周りで「VR」というワードを聞くことが増えてきたのではないでしょうか。そしてこの波に乗るように、VRについてもWebでの体験を可能にする技術が公開されています。</p>

<h2>WebVRは体験の話ではない</h2>

<p>WebでのVR技術、それが「WebVR」です。<br />
取りざたされているVRを手軽にWebで体験できるもの。それが「WebVR」。</p>

<p>…ではなく。<br />
あくまでWebVRはイチ仕様に過ぎません。<br />
つまり、WebVRに対応したからといって、即座にWeb上でVRコンテンツを提供できる、という類のものではないということです。</p>

<h2>WebVRはAPIの仕様</h2>

<p>誤解を恐れずに言えば、WebVRはセンサーからの情報を扱うためだけのAPIです。<br />
要は、HMD（ヘッドマウントディスプレイ）からの位置、回転、視野情報など様々な、ハードウェアの情報を取り扱うAPIということです。もっと言ってしまえば、モバイルで利用しているジャイロセンサーとなんら変わることはない、ということです。</p>

<p>事実、WebGLの仕様と比べると格段に少ない内容の仕様となっています。（<a href="https://w3c.github.io/webvr/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">仕様はこちら</a>）</p>

<h2>VRコンテンツの構築</h2>

<p>Webで手軽に体験できるVRコンテンツ、と書きましたが提供する側が同じく手軽であるとは限りません。<br />
（とはいえ、その他のネイティブなVRコンテンツと比較すると格段に手軽だと思いますが）</p>

<p>WebVRはただのAPIだと書きました。<br />
つまり、VRコンテンツ自体は別のAPI、具体的にはWebGLを利用して3Dコンテンツを制作する必要があります。事実、VRコンテンツの制作について既存の3Dコンテンツの制作と違いはほとんどありません。</p>

<p>WebGLコンテンツでは通常、requestAnimationFrameなどを利用して、一定時間置きに画面を更新しアニメーションやインタラクションを実現します。ジャイロセンサーを使ったコンテンツの制作を行ったことがある方であれば、どういったコンテンツが制作できるのかのイメージがわくでしょう。</p>

<p>そして上でも書いたように、ジャイロセンサーで行っていたような処理をWebVR APIに替えて画面を更新してやればいいのです。</p>

<p>ただし、（当然ではありますが）通常のWebGLコンテンツとWebVRコンテンツでは決定的に違うところがあります。それは「VR体験を作り上げる必要がある」という点です。</p>

<p>具体例を上げましょう。<br />
今までの3Dコンテンツはカメラの位置は製作者側で制御可能でした。<br />
ということはつまり、都合の悪い、カメラの後ろ側を映さないようにカメラを制御することができた、ということです。
しかし、VRコンテンツはそのカメラの操作はユーザーの視点という形で使われるため、当然、その後ろ側を見られる可能性があります。<br />
（というより、ほとんどの場合、ユーザーはあたりを見渡すでしょう）</p>

<p>このように、裏側が見られてしまうということは、悪く言えば手抜き、よく言えば無駄を省いた部分までもしっかりと作り込まないとならないということを意味しています。</p>

<h2>基本的なセットアップ方法</h2>

<p>さて、それではざっくりとですが、WebVR APIを使ったセットアップのコードを紹介しましょう。<br />
本コードは<a href="https://hacks.mozilla.org/2016/03/introducing-the-webvr-1-0-api-proposal/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">こちらのサイトのサンプル</a>を引用させていただいています。</p>

<p><strong>▼ HMDハードウェアの参照を取得する</strong></p>

<p><code>navigator.getVRDisplay().then(function (displays) {
    if (!displays.length) {
        return;
    }</p>

<pre><code>vrDisplay = displays.length[0];
</code></pre>

<p>}).catch(function (err) {
    console.error('Could not get VRDisplay', err.stack);
};</code></p>

<p><br /></p>

<p><strong>▼ 描画対象として必要なサイズを取得する</strong></p>

<p><code>var eyeParameter = vrDisplay.getEyeParameters('left');
var width = eyeParameter.renderWidth;
var height = eyeParameter.renderHeight;
</code></p>

<p><br /></p>

<p><strong>▼ WebGLのCanvasおよびVRモード移行のための処理を記述</strong>
<code>var webglCanvas = document.querySelector('#webglcanvas');
var enterVRBtn = document.querySelector('#entervr');</p>

<p>enterVRBtn.addEventListener('click', function () {
    vrDisplay.requestPresent({source:webglCanvas});
}, false);</p>

<p>vrDisplay.exitPresent();</code></p>

<p><br /></p>

<p><strong>▼ 画面のアニメーションループを処理する</strong>
<code>var id = vrDisplay.requestAnimationFrame(onAnimationFrame);</p>

<p>function onAnimationFrame() {
    id = vrDisplay.requestAnimationFrame(onAnimationFrame);
}</p>

<p>vrDisplay.cancelRequestAnimationFrame(id);</code></p>

<p><br /></p>

<p><strong>▼ HMDのセンサーからの値を取り出す</strong>
<code>var pose = vrDisplay.getPose();</p>

<p>var orientation = pose.orientation;</p>

<p>var position = pose.position;</code></p>

<p><br /></p>

<p><strong>▼ ハードウェアに設定された個々の設定を読み取る（瞳孔間距離など）</strong>
<code>var eyeParameters = vrDisplay.getEyeParameter('left');</p>

<p>var eyeOffset = eyeParameters.offset;</p>

<p>var eyeMatrix = makeProjectionMatrix(vrDisplay, eyeParameters);</code></p>

<p><br /></p>

<p><strong>▼ 取得した情報から、プロジェクション行列を生成する</strong>
<code>function fieldOfViewToProjectionMatrix (fov, zNear, zFar) {
    var upTan = Math.tan(fov.upDegrees * Math.PI / 180.0);
    var downTan = Math.tan(fov.downDegrees * Math.PI / 180.0);
    var leftTan = Math.tan(fov.leftDegrees * Math.PI / 180.0);
    var rightTan = Math.tan(fov.rightDegrees * Math.PI / 180.0);
    var xScale = 2.0 / (leftTan + rightTan);
    var yScale = 2.0 / (upTan + downTan);</p>

<pre><code>var out = new Float32Array(16);
out[0] = xScale;
out[1] = 0.0;
out[2] = 0.0;
out[3] = 0.0;
out[4] = 0.0;
out[5] = yScale;
out[6] = 0.0;
out[7] = 0.0;
out[8] = -((leftTan - rightTan) * xScale * 0.5);
out[9] = ((upTan - downTan) * yScale * 0.5);
out[10] = -(zNear + zFar) / (zFar - zNear);
out[11] = -1.0;
out[12] = 0.0;
out[13] = 0.0;
out[14] = -(2.0 * zFar * zNear) / (zFar - zNear);
out[15] = 0.0;

return out;
</code></pre>

<p>}</code></p>

<h2>Three.jsを使えばお手軽</h2>

<p>WebGLといえばThree.js、というくらいデファクトスタンダードなライブラリとなったThree.js。<br />
実はThree.jsのリポジトリにはWebVRに対応するためのプラグインがすでに存在しています。</p>

<p>それは VRControl.js と VREffect.js の2種類です。<br />
これはどちらもThree.jsでVRを実現するのを手助けしてくれるプラグインです。<br />
VRControl がHMDのセンサーの処理を、 VREffect.js がフルスクリーンモードへの移行や、VRモードの表示を手助けしてくれます。</p>

<p>基本的に、Three.jsを使った3Dコンテンツ制作の方法はVR化すると言っても大きな違いはありません。<br />
その証拠に、VR化するためのコード断片は以下のようにとても短いものとなります。</p>

<p><code>var controls = new THREE.VRControls(camera);
var effect = new THREE.VREffect(renderer);</p>

<p>// clickイベントなどのユーザ操作のタイミングで実行される関数
function toVRMode() {
    effect.requestPresent();
}</code></p>

<h2>対応ブラウザ</h2>

<p>対応ブラウザは、執筆時点（2016/09/28）ではまだ限定的にしか存在していません。<br />
安定版で動作するものは今のところないのが現状です。</p>

<p>対応状況は以下のサイトから確認することができます。<br />
<a href="https://iswebvrready.org/#webvr-enthusiasm" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Is WebVR Ready?</a></p>

<h2>VR成功の鍵を握るのはWebVR</h2>

<p>個人的な見解ですが、VR成功の鍵をにぎるのはWebVRにあると思っています。<br />
その理由はいくつかあります。</p>

<p>一つ目が、プラットフォーム（Oculus Rift、HTC Viveなど）に依存しないこと。<br />
つまり今までのWebアプリと同様に、モバイル、PCなどのプラットフォームに依存しないコンテンツ展開ができることです。</p>

<p>二つ目に、インストールが不要なこと。ネイティブアプリにしてしまうとどうしてもこの「インストール」という手順が必要になってしまいます。しかし、WebVRであればWebサイトに訪れたユーザが、VRモードの開始ボタンを押すだけでVR体験をすることが可能になります。</p>

<p>そして最後の三つ目として、「ちょっとだけVR」が使えること。<br />
例えばECサイトの商品をVRで見てみる、例えば不動産サイトの部屋の感じをVRで体験してみる、などなど、VRが活用できればユーザの利便性が上がることはたくさんあります。</p>

<p>しかし、例えばこれらを、アプリをインストールしたのちにしか行えないとしたら大部分の人はそれを倦厭するでしょう。</p>

<p>またコンテンツ制作側からしても、そんなちょっとしたVRアプリだけをプラットフォームに載せて配信する、というハードルの高さも出てくるでしょう。</p>

<p>こうしたように、今までの「Webならではの良さ」がそのままVRにも当てはめることができると考えています。そしてこれが結局、VRとユーザの接点となり、より多くの人にVRとはなにか、VRでどんなことができるかを広める機会になると考えています。</p>

<h2>まとめ</h2>

<p>まとめると、</p>

<ul>
<li>WebVRはAPIの名称</li>
<li>WebVR APIがやってくれるのはセンサーの値を取るなどの最低限の処理のみ</li>
<li>Three.jsを使えば手軽にVRコンテンツの制作が可能</li>
<li>とはいえまだサポートブラウザが（ほぼ）ない</li>
<li>しかし、Webでの活用はまだまだ（いい意味で）未知数</li>
</ul>

<p>ということです。<br />
詳細については<a href="http://www.slideshare.net/hirumakazuya/webvr-65665803" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">カンファレンスで使用したスライド</a>がアップされているので、そちらを参照ください。</p>

<p>当日の動画は下記で公開されていますので、こちらも参照してください。（編集部注：動画は3：26：10あたりから比留間さんの講演となります）</p>


<!-- iframe plugin v.4.3 wordpress.org/plugins/iframe/ -->
<iframe class="embedly-embed" src="//cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.slideshare.net%2Fslideshow%2Fembed_code%2Fkey%2Fj44z1KIgpvjxeF&amp;url=http%3A%2F%2Fwww.slideshare.net%2Fhirumakazuya%2Fwebvr-65665803&amp;image=http%3A%2F%2Fcdn.slidesharecdn.com%2Fss_thumbnails%2Fwebvr-160903231346-thumbnail-4.jpg%3Fcb%3D1472944881&amp;key=internal&amp;type=text%2Fhtml&amp;schema=slideshare" scrolling="no" frameborder="0" 0="allowfullscreen" width="100%" height="500"></iframe>



<!-- iframe plugin v.4.3 wordpress.org/plugins/iframe/ -->
<iframe src="https://www.youtube.com/embed/UQGmbabnUBY" frameborder="0" 0="allowfullscreen" width="100%" height="500" scrolling="yes" class="iframe-class"></iframe>

]]></content:encoded>
		
		<series:name><![CDATA[HTML5 Conference 2016 特集]]></series:name>
	</item>
		<item>
		<title>Webブラウザで高速な演算を可能にする低水準言語asm.jsと、WebAssembly詳解ーasm.jsの仕組みとコーディング例</title>
		<link>/chikoski/18980/</link>
		<pubDate>Mon, 25 Jul 2016 00:06:51 +0000</pubDate>
		<dc:creator><![CDATA[清水智公]]></dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[asm.js]]></category>

		<guid isPermaLink="false">/?p=18980</guid>
		<description><![CDATA[連載： 低水準言語asm.jsとWebAssembly詳解 (2)連載の第１回目は asm.jsの紹介と、asm.jsが導入された背景を概観しました。 Just in Timeコンパイルによって高速にJavaScript...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/asmjs/" class="series-384" title="低水準言語asm.jsとWebAssembly詳解" data-wpel-link="internal">低水準言語asm.jsとWebAssembly詳解</a> (2)</div><p>連載の<a href="https://html5experts.jp/chikoski/18964/" target="_blank" data-wpel-link="internal">第１回目</a>は asm.jsの紹介と、asm.jsが導入された背景を概観しました。</p>

<p>Just in Timeコンパイルによって高速にJavaScriptを実行できるようになりましたが、立ち上がりが遅い、やり直しが発生する、コンパイルによって一時的に負荷が向上する、といった問題が残されています。</p>

<p>これを解決するためにプログラムの実行を行うより前にネイティブコードへとコンパイルするAhead of Timeコンパイルを導入したいのですが、JavaScriptは柔軟すぎて効率の良いネイティブコードを出力することが難しい、という問題がありました。</p>

<p>asm.jsはこの問題に一定の解をあたえるものとなります。今回はそのasm.jsがどのようなものなのか、JavaScriptの関数を asm.js化しながら解説していきます。</p>

<h2>asm.jsがコンパイルされるまで</h2>

<p>前述したとおりasm.jsで記述されたプログラムは、実行以前にコンパイルされます。コンパイルは下図のような過程で行われます。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2016/05/aot.png" data-wpel-link="internal"><img src="/wp-content/uploads/2016/05/aot.png" alt="asm.jsがコンパイルされるまで。意味解析とリンク時のチェックが行われ、失敗すると通常のJSとして実行される。" class="aligncenter size-medium wp-image-18967" srcset="/wp-content/uploads/2016/05/aot.png 640w, /wp-content/uploads/2016/05/aot-300x75.png 300w, /wp-content/uploads/2016/05/aot-207x52.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p>ソースコードが字句解析、構文解析されてAST（Abstract Syntax Tree：抽象構文木）になるところまでは一緒ですが、その後意味解析が行われます。この意味解析でそれぞれの式や変数、関数の型がチェックされます。</p>

<p>意味解析が終了後、プログラムはコンパイルされネイティブコードが出力されます。このネイティブコードはメモリ上に展開されたあと、プログラム中で利用しているJavaScriptの関数やasm.jsに用意されている標準ライブラリとのリンクが行われます。</p>

<p>意味解析とリンク、この2つに失敗する場合もあります。プログラム中に型エラーが発見された場合は前者の失敗します。
後者はメソッドの呼び出しや、JSにエキスポートできない種類のデータを引数に指定した関数呼び出しを行った場合に失敗します。</p>

<p>このような場合、プログラムはasm.jsとして処理されるのではなく、通常のJSとして処理されます。asm.jsがJSのサブセットであることによって、このようなフォールバックも可能になっています。</p>

<h2>asm.jsモジュール</h2>

<p>asm.jsで書かれたプログラムとして事前コンパイルされる際の単位は、モジュールです。ファイル単位でコンパイルが行われるわけではないので、1つのJSファイルのうち高速化が必要な部分をasm.jsで書き、それ以外の部分は通常のJSとして書くといったことが可能です。</p>

<p>asm.jsのモジュールは、次のようにCやC++のソースコードと似た構造となっています。</p>

<p></p><pre class="crayon-plain-tag">function ModuleName(stdlib, ffi, heap){
"use asm";
 // (1) 外部からインポートするシンボルの宣言
 // (2) 関数宣言
 // (3) 関数表の宣言
 // (4) モジュールのエキスポート
}</pre><p></p>

<p>1の部分では利用する標準ライブラリや、JSの関数、定数などのシンボルを列挙します。ちょうどCのextern宣言と同じような役割です。</p>

<p>2の部分で、それぞれの処理を関数として定義します。asm.jsではオブジェクトやクラスの定義が許されていません。そのため処理はクラスやオブジェクトとしてではなく、あくまで関数として定義します。</p>

<p>3の部分では同じ型の関数をまとめた表を定義できます。ちょうどCでの関数ポインタの機能を代替するものです。関数を直接呼び出すのではなく、この表を参照する形で呼び出すことで、呼び出す関数の振る舞いを変えられるので、多態性を持った関数を定義したい場合に有用です。</p>

<p>とはいえ、いまいちイメージがつかめないかと思います。そこで足し算を行うモジュールをasm.js化しながら、構成を見てゆきましょう。変更するのは以下のようなモジュールです。</p>

<p></p><pre class="crayon-plain-tag">function AddFunctions(){
  function add1(value){
    var result;
    result = value + 1;
    return result;
  }
  return {
    add1: add1
  }
}</pre><p></p>

<p>このモジュールは次のように利用できます。</p>

<p></p><pre class="crayon-plain-tag">const module = AddFunctions();
const one = module.add1(0);    // 1
const two  = module.add1(one); // 2</pre><p></p>

<h3>asm.jsディレクティブ</h3>

<p>asm.js化の第一歩は、ディレクティブの追加です。&#8221;use strict&#8221; ディレクティブをつけると、その関数はstrict modeで解釈されるのと同様に、&#8221;use asm&#8221;ディレクティブをつけることで、処理系はその関数をasm.jsのモジュール定義として処理します。</p>

<p></p><pre class="crayon-plain-tag">function AddFunctions(){
  "use asm";
  function add1(value){
    var result;
    result = value + 1;
    return result;
  }
  return {
    add1: add1,
  }
}</pre><p></p>

<h2>　型アノテーション</h2>

<p>次にAOTを行うための型アノテーションを行います。型アノテーションは、TypeScriptなどのように型を直接記述する方法が一般的かと思いますが、JavaScriptとしても解釈できなくてはいけないasm.jsでは異なります。同値となるような式を追加することで、型情報を明示します。</p>

<p>明示的に型アノテーションを行う対象は次の3つです。</p>

<ul>
<li>関数の引数</li>
<li>変数</li>
<li>関数の返り値</li>
</ul>

<p>これらの情報を元に、関数の型や式の型が決定されます。</p>

<h4>引数に対する型アノテーション</h4>

<p>引数に対する型アノテーションは、関数本体の先頭で行います。次の例では、add1の引数valueの型はintであることを示す型アノテーションが加わっています。value = value | 0; が型アノテーションを行っている部分です。</p>

<p></p><pre class="crayon-plain-tag">function AddFunctions(){
  "use asm";
  function add1(value){
    value = value | 0;
    var result;
    result = value + 1;
    return result;
  }
  return {
    add1: add1
  }
}</pre><p></p>

<p>引数で利用できる型はint, doubleの2つです。それぞれの型はは次の表のようにアノテーションします。</p>

<table>
<thead>
<tr>
  <th>型</th>
  <th>型アノテーション</th>
</tr>
</thead>
<tbody>
<tr>
  <td>int</td>
  <td>value = value | 0</td>
</tr>
<tr>
  <td>doube</td>
  <td>value = +value</td>
</tr>
<tr>
  <td>float</td>
  <td>value = f(value)</td>
</tr>
</tbody>
</table>

<p>尚、外部で定義された関数呼び出しを行った場合は、floatとして解釈されます。</p>

<h3>変数宣言</h3>

<p>asm.jsでは、関数内で利用する変数に対しても型アノテーションを行います。これは宣言時に初期値として代入するを適切に選ぶ形で行います。整数値を代入すればintに、実数値の場合はdoubleとなります。</p>

<p>尚、1.0のような小数点以下の数字が0のものは実数値として扱われます。変数宣言に型アノテーションをつけると、先ほどまでのモジュールは以下のようになります。</p>

<p></p><pre class="crayon-plain-tag">function AddFunctions(){
  "use asm";
  function add1(value){
    value = value | 0;
    var result = 0; // intとして宣言
    result = value + 1;
    return result;
  }
  return {
    add1: add1
  }
}</pre><p></p>

<h3>返り値に対する型アノテーション</h3>

<p>返り値に対して型アノテーションを行います。この情報と引数の型情報とを組み合わせて、関数の型が決定されます。</p>

<p>返り値で利用できるのはdouble, signed, float, そしてvoidの4つの型です。それぞれのアノテーション方法は以下の表の通りです。また即値を書く場合は、アノテーションは必要ありません。</p>

<table>
<thead>
<tr>
  <th>型</th>
  <th>アノテーション例</th>
  <th>メモ</th>
</tr>
</thead>
<tbody>
<tr>
  <td>double</td>
  <td>return +result;</td>
  <td></td>
</tr>
<tr>
  <td>signed</td>
  <td>return result</td>
  <td>0|</td>
</tr>
<tr>
  <td>float</td>
  <td>return f(result)</td>
  <td>fは関数</td>
</tr>
<tr>
  <td>void</td>
  <td>return;</td>
  <td></td>
</tr>
</tbody>
</table>

<h3>asm.jsの型システム</h3>

<p>これまでintやdoubleといった型を利用してきましたが、asm.jsで利用できる型を列挙し、それぞれの継承関係を示すと次の図となります。
矢印の元にある型は先の型を継承しています。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2016/05/subtypes.png" data-wpel-link="internal"><img src="/wp-content/uploads/2016/05/subtypes.png" alt="asm.js の型システム" class="aligncenter size-medium wp-image-18970" srcset="/wp-content/uploads/2016/05/subtypes.png 640w, /wp-content/uploads/2016/05/subtypes-300x134.png 300w, /wp-content/uploads/2016/05/subtypes-207x93.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a>
<a href="http://asmjs.org/spec/latest" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">http://asmjs.org/spec/latest</a> より引用</p>

<p>継承するということは、何かの制約が厳しくなっていくということです。asm.jsの型システムではnullを許容するか、実行時に割り当てられるレジスタがdoubleかintか、といった点での制約が厳しくなっていきます。</p>

<p>また、JavaScriptで定義されている関数に渡せる型も決まっています。背景色が薄い灰色になっているfixnum / signed / extern / double型のデータのみが許可されています。</p>

<h3>型のキャスト</h3>

<p>先ほどから変更しているプログラムは、意味解析に失敗します。それは次の部分に原因があります。</p>

<p></p><pre class="crayon-plain-tag">result = value + 1;</pre><p></p>

<p>これはint+fixnumの計算を行い、その結果をint型の変数に代入しようとしています。型エラーの入り込む余地はなさそうに思えます。しかし、この加算の評価値の型はinterishとなっています。そのため、int型へinterish型の値を代入することになり、型エラーが起きるというわけです。</p>

<p>そこでキャストを行い、演算結果の型を明示します。この変更をおこないasm.jsの意味解析に成功するコードは次のようになります。</p>

<p></p><pre class="crayon-plain-tag">function AddFunctions(){
  "use asm";
  function add1(value){
    value = value | 0;
    var result = 0; // int として宣言
    result = (value + 1) | 0; // int へキャスト
    return result;
  }
  return {
    add1: add1
  }
}</pre><p></p>

<h2>JavaScriptとの組み込み</h2>

<p>以上で、AddFunctionsモジュールをasm.js化することができました。これをJavaScriptのプログラムに組み込みんでいきます。</p>

<p>ここでは 上記で作成したAddFunctionsモジュールをJavaScript側から利用する方法と、AddFunctionsモジュール内で JavaScriptの関数を利用する方法について説明します。</p>

<h3>JavaScriptからの利用</h3>

<p>asm.jsのモジュールとJavaScriptのモジュールは、JavaScriptからみると区別できません。下記のようにJSのモジュールを呼ぶように利用できます。</p>

<p></p><pre class="crayon-plain-tag">const module = AddFunctions();
var one = module.add1(0);
var two = module.add1(one);

function add2(n){
  return module.add1(module.add1(n));
}</pre><p></p>

<h3>JavaScriptの関数をasm.jsから呼ぶには</h3>

<p>まず、asm.jsの内部からJavaScriptで定義された関数を呼ぶことはできます。また、Mathオブジェクトの持っているいくつかのメソッドは、<a href="http://asmjs.org/spec/latest/#standard-library" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">標準ライブラリ中の関数</a>として提供されています。</p>

<p>これら関数への参照はモジュールを定義する関数の引数として与えます。例えば、AsmModuleにasm.jsモジュールが定義されている場合、次のように呼び出すことでJavaScriptの関数をasm.js内から呼び出せます。</p>

<p></p><pre class="crayon-plain-tag">const ffi = {
  put: n =&gt; console.log(n)
};

const module = AsmModule(window, ffi);</pre><p></p>

<p>asm.jsで定義される関数はオブジェクトの解決ができません。そのため利用する関数はあらかじめ外部からインポートするシンボルとして宣言しておきます。</p>

<p>次の例では、標準ライブラリ中のMath.expとMath.log、そして自作関数であるputを外部からインポートするシンボルとして宣言しています。</p>

<p></p><pre class="crayon-plain-tag">function AsmModule(stdlib, ffi, heap){
  "use asm";
  var exp = std.lib.Math.exp;
  var log = std.lib.Math.log;

  var put = ffi.put;</pre><p></p>

<p>これらの関数は、関数定義内でasm.js内部で定義された関数と同様に呼び出せます。ただ1点注意しなくてはならないのは、引数に渡すデータの型です。標準ライブラリ以外の外部関数に渡せるのはfixnum、signed、extern、doubleのいずれかです。
それ以外の値を渡すとリンクエラーとなり、通常のJSとして実行されます。演算の結果を適切にアノテーションすることで、リンクエラーを避けられます。</p>

<p></p><pre class="crayon-plain-tag">var value = 1;
put(value + 1); // リンクエラー
put((value + 1) | 0); // OK</pre><p></p>

<h2>ヒープの利用</h2>

<p>asm.jsで定義される関数は、数値演算しかできません。また、オブジェクトの解決もできません。つまり、次のような関数は定義できないことになります。</p>

<p></p><pre class="crayon-plain-tag">function caesar(string, key){
  var result = "";
  for(let i = 0; i &lt; string.length; i++){
    result += String.fromCharCode(a.charCodeAt(0)+key);
  }
  return result;
}</pre><p></p>

<p>ところでC言語では文字列を数値の配列として扱います。この考えを応用すれば、asm.jsでも文字列を数値演算の範囲で扱えるようになります。</p>

<p>上記の関数をasm.jsに書き直すと以下のようになります。</p>

<p></p><pre class="crayon-plain-tag">function Caesar(stdlib, ffi, heap){
  "use asm";
  var HEAP = new stdlib.Int8Array(heap);

  function encrypt(key){
    key = key | 0;
    var i = 0;
    for(;(HEAP[i &lt;&lt; 0 &gt;&gt; 0] | 0) != 0; i = i + 1 | 0){
      buffer[i &lt;&lt; 0 &gt;&gt; 0] = ((buffer[i &lt;&lt; 0 &gt;&gt; 0] | 0) + key) | 0;
    }
    return;
  }</pre><p></p>

<p>文字列はHEAPというArrayBufferに格納されています。このArrayBufferはモジュールの定義時に引数として与えられます。
ArrayBufferのビューは標準ライブラリとして提供されているため、上記のようにモジュール内のHEAPを大域変数として宣言する際にビューもあわせて定義します。</p>

<p>HEAPの添字は、ビューの各要素の大きさに合わせてシフトする必要があります。シフトするビット数は、2を底として要素のバイトサイズのlogをとると求まります。</p>

<p>上記の例で利用しているInt8Arrayの場合、各要素の大きさは1バイトのため、0ビットシフトしています。ビューとシフトするビット数の対応は次の表を参照してください。</p>

<table>
<thead>
<tr>
  <th>ビュー</th>
  <th>要素のサイズ（バイト）</th>
  <th>シフトするビット数</th>
  <th>ロード時の型</th>
  <th>保存時の型</th>
</tr>
</thead>
<tbody>
<tr>
  <td>Uint8Array</td>
  <td>1</td>
  <td>0</td>
  <td>intish</td>
  <td>intish</td>
</tr>
<tr>
  <td>Int8Array</td>
  <td>1</td>
  <td>0</td>
  <td>intish</td>
  <td>intish</td>
</tr>
<tr>
  <td>Uint16Array</td>
  <td>2</td>
  <td>1</td>
  <td>intish</td>
  <td>intish</td>
</tr>
<tr>
  <td>Int16Array</td>
  <td>2</td>
  <td>1</td>
  <td>intish</td>
  <td>intish</td>
</tr>
<tr>
  <td>Uint32Array</td>
  <td>4</td>
  <td>2</td>
  <td>intish</td>
  <td>intish</td>
</tr>
<tr>
  <td>Int32Array</td>
  <td>4</td>
  <td>2</td>
  <td>intish</td>
  <td>intish</td>
</tr>
<tr>
  <td>Float32Array</td>
  <td>4</td>
  <td>2</td>
  <td>float?</td>
  <td>floatish, double?</td>
</tr>
<tr>
  <td>Float64Array</td>
  <td>8</td>
  <td>3</td>
  <td>double?</td>
  <td>float?, double?</td>
</tr>
</tbody>
</table>

<p>ArrayBufferを与えてモジュールの作成と関数の呼び出しを行うと、次のようなコードとなります。</p>

<p>気をつけなければならいのは、TypedArrayの大きさです。2<sup>12</sup> 以上、2<sup>24</sup>バイト未満の大きさになるようにするか、2<sup>24</sup>バイトの整数倍の大きさになるようにしてください。そうしなければ、リンクに失敗してします。</p>

<p>これが原因でリンクに失敗した場合は、コンソールに適切なサイズが表示されます。それを参考に大きさを際設定すればようでしょう。</p>

<p></p><pre class="crayon-plain-tag">const heap = new Int8Array(0x10000)
const caesar = Caesar(window, {}, heap);
heap[0] = 72; heap[1] = 65; heap[2] = 76; // HALと設定
caesar.encrypt(1); // HALが1文字ずつシフトされる</pre><p></p>

<h2>まとめ</h2>

<p>以上のように、JavaScriptと比べてasm.jsは随分と書きづらく、できることも限られています。ArrayBufferを駆使すればベクトルの計算も可能ですが、オブジェクトと平坦なArrayBufferとの相互変換を自分で実装しなくてはならず、なかなか骨が折れる作業であることは否めません。</p>

<p>その代わり得られる効果は絶大です。JITによって処理が重たくなることもなく、高速な実行が可能となります。またコンパイルされた結果はキャッシュされるため、2回目以降は高速に起動できるようになります。</p>

<p>とはいえ、手で書くのは骨が折れます。</p>

<p>「人間のやることではない」</p>

<p>「高級言語で実装したい」</p>

<p>そう思う方も多いでしょう。そのために用意されているツールがEmscriptenです。次回はEmscriptenを利用したC言語やC++で実装されたコードのasm.jsへの変換について解説します。</p>
]]></content:encoded>
		
		<series:name><![CDATA[低水準言語asm.jsとWebAssembly詳解]]></series:name>
	</item>
		<item>
		<title>カメラを使ってみよう ーWebRTC入門2016</title>
		<link>/mganeko/19728/</link>
		<pubDate>Fri, 24 Jun 2016 00:00:28 +0000</pubDate>
		<dc:creator><![CDATA[がねこまさし]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[WebRTC]]></category>
		<category><![CDATA[カメラ]]></category>

		<guid isPermaLink="false">/?p=19728</guid>
		<description><![CDATA[連載： WebRTC入門2016 (1)こんにちは！ がねこまさしです。2014年に連載した「WebRTCを使ってみよう！」シリーズですが、内容がすっかり古くなってしまいました。そこで2016年6月の最新情報に基づき、内...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/webrtc2016/" class="series-380" title="WebRTC入門2016" data-wpel-link="internal">WebRTC入門2016</a> (1)</div><p>こんにちは！ がねこまさしです。2014年に連載した<a href="https://html5experts.jp/series/webrtc-beginner/" target="_blank" data-wpel-link="internal">「WebRTCを使ってみよう！」シリーズ</a>ですが、内容がすっかり古くなってしまいました。そこで2016年6月の最新情報に基づき、内容をアップデートして改めてお届けしたいと思います。</p>

<h2>WebRTCとは？</h2>

<p>WebRTCとは”Web Real-Time Communication”の略で、Webブラウザ上でビデオ/オーディオの通信や、データ通信を行うための規格です。HTML5で新しく策定されたもので、複数の技術の連携で成り立っています。 ちなみに策定には複数の団体が絡んでいています。</p>

<ul>
<li>API → <a href="https://www.w3.org/TR/webrtc/" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">W3C</a></li>
<li>ビデオ/オーディオのコーデック → <a href="http://tools.ietf.org/wg/rtcweb/" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">IETF</a></li>
</ul>

<p>APIの策定作業はWebRTC 1.0に向けて大詰めに入っています。またより詳細な低レベルのAPIを定義している<a href="http://ortc.org/wp-content/uploads/2016/05/ortc.html" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">ORTC</a>も登場し、将来の統合に向けた動きも始まっています。</p>

<p>コーデックの選定では、ブラウザがサポートしなければならないビデオコーデックに、既にデファクトスタンダードともいえるH.264が加わりました。また、Googleが開発しているオープンソースのビデオコーデック「VP9」をサポートするブラウザも増えています。</p>

<h2>WebRTCで何ができるの？</h2>

<p>WebRTCは厳密に言うとビデオ/オーディオ/データ通信を行うための仕組みですが、他にも関連が深い技術があります。この連載では3つをまとめてWebRTC（とその仲間たち）ということで扱います。</p>

<ul>
<li>カメラ、マイクといったデバイスへのアクセスする &#8230; <a href="https://www.w3.org/TR/mediacapture-streams/" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">Media Capture and Streams</a></li>
<li>ビデオ/オーディオ/データ通信を行う &#8230; <a href="https://www.w3.org/TR/webrtc/" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">WebRTC 1.0: Real-time Communication Between Browsers</a></li>
<li>ビデオ/オーディオの録画/録音を行う &#8230; <a href="https://www.w3.org/TR/mediastream-recording/" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">MediaStream Recording</a></li>
</ul>

<p>この3兄弟に、HTML5の様々な要素を組み合わせて活用することができます。</p>

<ul>
<li>JavaScript（大前提）</li>
<li>videoタグ、audioタグ</li>
<li>CSS3</li>
<li>Canvas</li>
<li>WebGL</li>
<li>Web Audio API</li>
<li>WebSocket</li>
</ul>

<h2>新しいAPIでカメラを使ってみよう</h2>

<p>カメラやマイクと言ったデバイスにアクセスするには、従来は<code>navigator.getUserMedia()</code>というAPIを使いました。2016年6月現在では、これに代わる新しいAPIが登場しています。</p>

<ul>
<li><code>navigator.mediaDevices.getUserMedia()</code> になった</li>
<li>ベンダープレフィックスが取れた</li>
<li>コールバックではなく<code>Promise</code>ベースになった</li>
</ul>

<p>またデスクトップブラウザの場合は次のブラウザで利用することができます。</p>

<ul>
<li>Firefox 47 &#8230; 利用可能</li>
<li>Chrome 51 &#8230; 利用する場合にはフラグ設定が必要

<ul>
<li>chrome://flagsというURLを開く</li>
<li>「試験運用版のウェブ プラットフォームの機能 #enable-experimental-web-platform-features」を有効に</li>
<li>Chromeを再起動</li>
</ul></li>
<li>Edge 25 &#8230; Windows 10 のEdgeでも利用可能</li>
</ul>

<h3>サンプルコード</h3>

<p>それではカメラから映像を取得してみましょう。サンプルコードはこちらです。
</p><pre class="crayon-plain-tag">&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
 &lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
 &lt;title&gt;Camera with mediaDevice&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;button onclick="startVideo()"&gt;Start&lt;/button&gt;
  &lt;br /&gt;
  &lt;video id="local_video" autoplay style="width: 320px; height: 240px; border: 1px solid black;"&gt;&lt;/video&gt;
&lt;/body&gt;
&lt;script type="text/javascript"&gt;
  let localVideo = document.getElementById('local_video');
  let localStream;
  
  // start local video
  function startVideo() {
    navigator.mediaDevices.getUserMedia({video: true, audio: false})
    .then(function (stream) { // success
      localStream = stream;
      localVideo.src = window.URL.createObjectURL(localStream);
    }).catch(function (error) { // error
      console.error('mediaDevice.getUserMedia() error:', error);
      return;
    });
  }
&lt;/script&gt;
&lt;/html&gt;</pre><p></p>

<p>このHTMLファイルに、（Webサーバ経由で）ブラウザからアクセスしてみてください。GitHub Pagesでも公開していますので、すぐに試すことができます。</p>

<ul>
<li>GitHub Pages で試す <a target="_blank" href="https://mganeko.github.io/webrtcexpjp/basic2016/camera_new.html" data-wpel-link="external" rel="follow external noopener noreferrer">camera_new.html</a>（※Chromeの場合は、上記のフラグ設定が必要です）</li>
<li>GitHub でソースを見る <a target="_blank" href="https://github.com/mganeko/webrtcexpjp/blob/master/basic2016/camera_new.html" data-wpel-link="external" rel="follow external noopener noreferrer">camera_new.html</a></li>
</ul>

<p>ブラウザで[Start]ボタンをクリックすると、カメラへのアクセスの許可を求めるダイアログが表示されますので、許可してください。<br />
<strong>Firefoxの場合</strong>
<a href="https://html5experts.jp/wp-content/uploads/2016/06/getusermedia_ff.png" data-wpel-link="internal"><img src="/wp-content/uploads/2016/06/getusermedia_ff-300x144.png" alt="getusermedia_ff" width="300" height="144" class="alignnone size-medium wp-image-19758" srcset="/wp-content/uploads/2016/06/getusermedia_ff-300x144.png 300w, /wp-content/uploads/2016/06/getusermedia_ff-207x100.png 207w, /wp-content/uploads/2016/06/getusermedia_ff.png 322w" sizes="(max-width: 300px) 100vw, 300px" /></a><br /></p>

<p><strong>Chromeの場合</strong>
<a href="https://html5experts.jp/wp-content/uploads/2016/06/getusermedia_chrome.png" data-wpel-link="internal"><img src="/wp-content/uploads/2016/06/getusermedia_chrome-300x112.png" alt="getusermedia_chrome" width="300" height="112" class="alignnone size-medium wp-image-19759" srcset="/wp-content/uploads/2016/06/getusermedia_chrome-300x112.png 300w, /wp-content/uploads/2016/06/getusermedia_chrome-207x77.png 207w, /wp-content/uploads/2016/06/getusermedia_chrome.png 354w" sizes="(max-width: 300px) 100vw, 300px" /></a><br /></p>

<p><strong>Edgeの場合</strong><br />
<a href="https://html5experts.jp/wp-content/uploads/2016/06/getusermedia_edge.png" data-wpel-link="internal"><img src="/wp-content/uploads/2016/06/getusermedia_edge-300x45.png" alt="getusermedia_edge" width="300" height="45" class="alignnone size-medium wp-image-19789" srcset="/wp-content/uploads/2016/06/getusermedia_edge-300x45.png 300w, /wp-content/uploads/2016/06/getusermedia_edge.png 640w, /wp-content/uploads/2016/06/getusermedia_edge-207x31.png 207w" sizes="(max-width: 300px) 100vw, 300px" /></a><br />
ウィンドウの下の部分にこのように表示されます。他のブラウザと違うので、ちょっと気が付きにくいかもしれません。</p>

<p>すると、このようにカメラの映像が表示されるはずです。
<a href="https://html5experts.jp/wp-content/uploads/2016/06/camera_ff.png" data-wpel-link="internal"><img src="/wp-content/uploads/2016/06/camera_ff-300x247.png" alt="camera_ff" width="300" height="247" class="alignnone size-medium wp-image-19768" srcset="/wp-content/uploads/2016/06/camera_ff-300x247.png 300w, /wp-content/uploads/2016/06/camera_ff-207x171.png 207w, /wp-content/uploads/2016/06/camera_ff.png 428w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>

<h3>HTMLファイルの置き場所</h3>

<p>カメラやマイクにアクセスするには、サンプルのHTMLファイルをWebサーバーに配置する必要がありますが、実はブラウザによって条件が異なります。</p>

<ul>
<li>Chromeの場合 &#8230; 原則 https://～/ のみ。例外として http://localhost/～ でも利用可能</li>
<li>Firefoxの場合 &#8230; https://～/ および http://～/ の両方で利用可能。さらに file://～ でも利用可能</li>
<li>Edgeの場合 &#8230; https://～/ および http://～/ の両方で利用可能。さらに file://～ でも利用可能</li>
</ul>

<p>FirefoxやEdgeの場合は、ローカルのHTMLファイルを直接読み込んでも、利用可能です。</p>

<h3>トラブルシューティング</h3>

<p>カメラのアクセスの許可を求められた際に「常に拒否」すると、そのサイトからはカメラの映像を取得することができなくなります。その場合は明示的に再許可してあげる必要があります。</p>

<p><strong>Firefoxの場合</strong><a href="https://html5experts.jp/wp-content/uploads/2016/06/getusermedia_ff_ng.png" data-wpel-link="internal"><img src="/wp-content/uploads/2016/06/getusermedia_ff_ng-300x204.png" alt="getusermedia_ff_ng" width="300" height="204" class="alignnone size-medium wp-image-19761" srcset="/wp-content/uploads/2016/06/getusermedia_ff_ng-300x204.png 300w, /wp-content/uploads/2016/06/getusermedia_ff_ng-207x141.png 207w, /wp-content/uploads/2016/06/getusermedia_ff_ng.png 403w" sizes="(max-width: 300px) 100vw, 300px" /></a>で「許可」または「毎回確認する」を選択</p>

<p><strong>Chromeの場合</strong><a href="https://html5experts.jp/wp-content/uploads/2016/06/getusermedia_chrome_ng.png" data-wpel-link="internal"><img src="/wp-content/uploads/2016/06/getusermedia_chrome_ng-300x151.png" alt="getusermedia_chrome_ng" width="300" height="151" class="alignnone size-medium wp-image-19762" srcset="/wp-content/uploads/2016/06/getusermedia_chrome_ng-300x151.png 300w, /wp-content/uploads/2016/06/getusermedia_chrome_ng-207x104.png 207w, /wp-content/uploads/2016/06/getusermedia_chrome_ng.png 471w" sizes="(max-width: 300px) 100vw, 300px" /></a>「常に許可する」を選択</p>

<p><strong>Edgeの場合</strong><br />
※いまのところ「常に拒否」することはできないようなので、このケースは発生しません。</p>

<h2>新旧 getUserMedia() をラップしてみると</h2>

<p>新しいAPIである navigator.mediaDevices.getUserMedia()は、まだChromeではデフォルトの状態では使えません。これは、引数で渡すオプションの指定方法が、まだ新しい書き方に沿っていないことが原因です。
</p><pre class="crayon-plain-tag">let deviceID = getSelectedIDsomehow(); // デバイスIDを指定する

// Firefoxの場合
let constraints = {
  audio: false,
  video: { 
   deviceId: {exact: deviceID}
  }
};

// Chromeの場合
let constraintsForChrome = {
  audio: false,
  video: {
    optional: [{sourceId: deviceID}]
  }
};</pre><p></p>

<p>そのため、Chromeではしばらく新しいAPIはデフォルトでは使えない状態が続くと思われます。そこで古いAPIをPromise型にラップする例を用意してみました。（オプション指定の違いは吸収できていません）
</p><pre class="crayon-plain-tag">// --- prefix -----
  navigator.getUserMedia  = navigator.getUserMedia    || navigator.webkitGetUserMedia ||
                            navigator.mozGetUserMedia || navigator.msGetUserMedia;

  // ---- 新旧APIをPromiseでラップする ----
  function getDeviceStream(option) {
    if ('getUserMedia' in navigator.mediaDevices) {
      console.log('navigator.mediaDevices.getUserMadia');
      return navigator.mediaDevices.getUserMedia(option);
    }
    else {
      console.log('wrap navigator.getUserMadia with Promise');
      return new Promise(function(resolve, reject){    
        navigator.getUserMedia(option,
          resolve,
          reject
        );
      });      
    }
  }

  // 利用例
  function startVideo() {
    getDeviceStream({video: true, audio: false})
    .then(function (stream) { // success
      localStream = stream;
      localVideo.src = window.URL.createObjectURL(localStream);
    }).catch(function (error) { // error
      console.error('getUserMedia error:', error);
      return;
    });
  }</pre><p> 
これを使ってカメラ映像を取得する例もご用意しました。Chrome 51でもデフォルトのままで利用できます。</p>

<ul>
<li>GitHub Pages で試す <a target="_blank" href="https://mganeko.github.io/webrtcexpjp/basic2016/camera_old_new.html" data-wpel-link="external" rel="follow external noopener noreferrer">camera_old_new.html</a></li>
<li>GitHub でソースを見る <a target="_blank" href="https://github.com/mganeko/webrtcexpjp/blob/master/basic2016/camera_old_new.html" data-wpel-link="external" rel="follow external noopener noreferrer">camera_old_new.html</a></li>
</ul>

<p>様々なWebRTC関連のブラウザの違いを吸収する <code>adapter.js</code> が <a href="https://github.com/webrtc/adapter" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">本家のGitHub</a>で公開されています。より便利に使いたい場合は、<a href="http://webrtc.github.io/adapter/adapter-latest.js" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">そちらを</a>ご利用ください。</p>

<h2>CSS3と組み合わせてみよう</h2>

<p>WebRTCは他の要素と組み合わせて使うことができると書きました。実際にCSS3と組み合わせてみましょう。</p>

<p></p><pre class="crayon-plain-tag">&lt;!-- 通常 --&gt;
  &lt;video id="local_video" autoplay style="width: 320px; height: 240px; border: 1px solid black;"&gt;&lt;/video&gt;

  &lt;!-- 左右反転 --&gt;
  &lt;video id="flip_video" autoplay style="transform: scaleX(-1); width: 320px; height: 240px; border: 1px solid black;"&gt;&lt;/video&gt;

  &lt;!-- 角丸 --&gt;
  &lt;video id="round_video" autoplay style="border-radius: 80px 80px 80px 80px; width: 320px; height: 240px; border: 1px solid black;"&gt;&lt;/video&gt;

  &lt;!-- セピア --&gt;
  &lt;video id="filter_video" autoplay style="filter: sepia(100%); -webkit-filter: sepia(100%); width: 320px; height: 240px; border: 1px solid black;"&gt;&lt;/video&gt;</pre><p> 
ほかにも様々なバリエーションが考えられます。ぜひ自分でもいろいろ試してみてください。</p>

<p>また、CSS3アニメーションを使うこともできます。例えばこんな感じです。
</p><pre class="crayon-plain-tag">&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
 &lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;
 &lt;title&gt;Camera with mediaDevice&lt;/title&gt;
 &lt;style type="text/css"&gt;
   #rotate_video
   {
    animation-duration:4s;
    animation-iteration-count:infinite;
    animation-timing-function:linear;
    animation-name:rotate360;     
   }

   #shake_video
   {
    animation-duration:0.5s;
    animation-iteration-count:infinite;
    animation-timing-function:ease-in-out;
    animation-name:shake;     
   }
   
   @keyframes rotate360
   {
    0%{transform:rotate(0deg);}
    100%{transform:rotate(360deg);}
   }

   @keyframes shake
   {
    0%{transform:rotate(-20deg);}
    50%{transform:rotate(20deg);}
    100%{transform:rotate(-20deg);}
   }
  &lt;/style&gt; 
&lt;/head&gt;
&lt;body&gt;
  Camera with mediaDevice.getUserMedia()&lt;br /&gt;
  &lt;button onclick="startVideo()"&gt;Start&lt;/button&gt;
  &lt;br /&gt;
  &lt;!-- 通常 --&gt;
  &lt;video id="local_video" autoplay style="width: 320px; height: 240px; border: 1px solid black;"&gt;&lt;/video&gt;
  &lt;br /&gt;

  &lt;!-- 回転アニメーション --&gt;
  &lt;video id="rotate_video" autoplay style="width: 320px; height: 240px; border: 1px solid black;"&gt;&lt;/video&gt;

  &lt;!-- 振動アニメーション --&gt;
  &lt;video id="shake_video" autoplay style="width: 320px; height: 240px; border: 1px solid black;"&gt;&lt;/video&gt;
  
&lt;/body&gt;
&lt;script type="text/javascript"&gt;
  // --- prefix -----
  navigator.getUserMedia  = navigator.getUserMedia    || navigator.webkitGetUserMedia ||
                            navigator.mozGetUserMedia || navigator.msGetUserMedia;

  let localVideo = document.getElementById('local_video');
  let localStream;
  
  // start local video
  function startVideo() {
    getDeviceStream({video: true, audio: false})
    .then(function (stream) { // success
      localStream = stream;
      localVideo.src = window.URL.createObjectURL(localStream);
	  
      document.getElementById('rotate_video').src = localVideo.src;
      document.getElementById('shake_video').src = localVideo.src;
    }).catch(function (error) { // error
      console.error('mediaDevice.getUserMedia() error:', error);
      return;
    });
  }

  // ---- 新旧APIをPromiseでラップする ----
  function getDeviceStream(option) {
    if ('getUserMedia' in navigator.mediaDevices) {
      console.log('navigator.mediaDevices.getUserMadia');
      return navigator.mediaDevices.getUserMedia(option);
    }
    else {
      console.log('wrap navigator.getUserMadia with Promise');
      return new Promise(function(resolve, reject){    
        navigator.getUserMedia(option,
          resolve,
          reject
        );
      });      
    }
  }
&lt;/script&gt;
&lt;/html&gt;</pre><p> 
<a href="https://html5experts.jp/wp-content/uploads/2016/06/camera_css_animation.png" data-wpel-link="internal"><img src="/wp-content/uploads/2016/06/camera_css_animation-300x123.png" alt="camera_css_animation" width="300" height="123" class="alignnone size-medium wp-image-19778" srcset="/wp-content/uploads/2016/06/camera_css_animation-300x123.png 300w, /wp-content/uploads/2016/06/camera_css_animation.png 640w, /wp-content/uploads/2016/06/camera_css_animation-207x85.png 207w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>

<p>CSS3と組み合わせたサンプルも、GitHub Pagesでも公開していますので、試してみてください。（ラップ関数を使っているので、デフォルトのChrome 51でも利用できます）</p>

<ul>
<li>GitHub Pages で試す <a target="_blank" href="https://mganeko.github.io/webrtcexpjp/basic2016/camera_css_wrap.html" data-wpel-link="external" rel="follow external noopener noreferrer">camera_css_wrap.html</a></li>
<li>GitHub でソースを見る <a target="_blank" href="https://github.com/mganeko/webrtcexpjp/blob/master/basic2016/camera_css_wrap.html" data-wpel-link="external" rel="follow external noopener noreferrer">camera_css_wrap.html</a></li>
</ul>

<h2>次回は</h2>

<p>今回は新しいAPIを使って、カメラの映像を取得してみました。次回はWebRTCによる通信を手動で接続してみます。</p>
]]></content:encoded>
		
		<series:name><![CDATA[WebRTC入門2016]]></series:name>
	</item>
		<item>
		<title>Angular2を書くためのAngularJSの書き方</title>
		<link>/teyosh/18806/</link>
		<pubDate>Fri, 27 May 2016 06:00:05 +0000</pubDate>
		<dc:creator><![CDATA[吉田 徹生]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[Angular2]]></category>
		<category><![CDATA[AngularJS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[ng-japan]]></category>

		<guid isPermaLink="false">/?p=18806</guid>
		<description><![CDATA[Angular2のリリースが刻一刻と近づいてきました。しかし世の中のプロダクトは、まだまだ大半がAngular1.xで開発されています。Angular2はコンポーネント指向が徹底されていたり、TypeScriptが推奨の...]]></description>
				<content:encoded><![CDATA[<p>Angular2のリリースが刻一刻と近づいてきました。しかし世の中のプロダクトは、まだまだ大半がAngular1.xで開発されています。Angular2はコンポーネント指向が徹底されていたり、TypeScriptが推奨の開発言語であるなど、Angular1から大きく変わっており、一見すると移行は容易ではありません。</p>

<p>しかしAngular1.xの最新バージョンである1.5では、Angular1から2への移行をスムーズに行うために、Angular2を見据えたコーディングが行えるようになっています。この記事ではAngular2への移行をスムーズにするための、Angular1の書き方を紹介していきます。</p>

<p><img src="/wp-content/uploads/2016/05/DSC02661.jpg" alt="" width="500" height="319" class="aligncenter size-full wp-image-19230" srcset="/wp-content/uploads/2016/05/DSC02661.jpg 500w, /wp-content/uploads/2016/05/DSC02661-300x191.jpg 300w, /wp-content/uploads/2016/05/DSC02661-207x132.jpg 207w" sizes="(max-width: 500px) 100vw, 500px" /></p>

<p><strong>【編集部注】</strong><br>
<span style="font-size: 90%">※この記事は、2016年3月21日に開催された「ng-japan 2016」のセッション「Angular2を書くためのAngularJSの書き方」についての、講演者自身によるレポートです。講演内容に加えて、講演者自身による解説や追記によって、よりわかりやすく詳細な記事に仕上げていただきました。<br>※本記事では、AngularJSをAngular1、 AngularJSの2系をAngularと表記しています。</span></p>

<p>セッションの講演資料と動画はこちらになります。</p>

<h3>講演資料</h3>


<!-- iframe plugin v.4.3 wordpress.org/plugins/iframe/ -->
<iframe class="embedly-embed" src="//cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fspeakerdeck.com%2Fplayer%2Ff7f27043b8884f71822b4fe709864990&amp;url=https%3A%2F%2Fspeakerdeck.com%2Fteyosh%2Fangular2woshu-kutamefalseangularjsfalseshu-kifang&amp;image=https%3A%2F%2Fspeakerd.s3.amazonaws.com%2Fpresentations%2Ff7f27043b8884f71822b4fe709864990%2Fslide_0.jpg&amp;key=internal&amp;type=text%2Fhtml&amp;schema=speakerdeck" width="500" height="344" scrolling="no" frameborder="0" 0="allowfullscreen"></iframe>


<h3>講演動画（2:03:46付近から始まります）</h3>


<!-- iframe plugin v.4.3 wordpress.org/plugins/iframe/ -->
<iframe width="560" height="315" src="https://www.youtube.com/embed/yQX1Y3MAIWQ" frameborder="0" 0="allowfullscreen" scrolling="yes" class="iframe-class"></iframe>


<h2>Angular1の歴史と背景</h2>

<p>Angular1は、今から4年前の2012年6月に、バージョン1.0.0がリリースされました。この4年間に、Windowsなら8-&gt;10、Macで10.8-&gt;10.11、Androidで4-&gt;6、iOSで6-&gt;9という変化がありました。バージョンアップが比較的遅いとされるOSでも、4年の間にこれほど大きなバージョンアップが行われているのです。</p>

<p>現在のIT業界では、4年とはこれほど長い期間です。また4年前のWebを振り返ってみますと、当時はBackbone.jsなどのMVCフレームワークが全盛期でした。Angularはリリースされてから大きな人気を博し、世界中の数多くのプロジェクトで採用されました。</p>

<p>しかし月日は流れ、2014年にReactが発表されてからは、Angular1の人気にも陰りが訪れます。コンポーネント指向を採用したReactの優れた設計が広く支持されたこと、Angular1はパフォーマンスがあまりよくないということもあり、Reactを採用するプロジェクトも増えてきました。</p>

<p>そこでパフォーマンスを大きく改善し、アーキテクチャが刷新されたAngular2が今年中にリリースが予定されています。しかしAngular2は変更点が多く、普及には時間がかかることが予想されます。そのため、Angular1.xは当分サポートされることが決定しています。</p>

<h2>Angular1とAngular2の違い</h2>

<p>Angular1とAngular2の違いは多岐にわたります。その中でも代表的な違いを以下に挙げます。</p>

<ul>
<li>主な開発言語がJavaScriptからTypeScriptへ</li>
<li>Two-wayデータバインディングを廃し、One-wayデータバインディングへ</li>
<li>従来のスコープに代わり、コンポーネントがUIの状態を保持する（コンポーネント指向）</li>
<li>テンプレートの文法が変更</li>
<li>従来のng-routerからコンポーネントルーターに</li>
<li>従来の文字列ベースのDI (Dependency Injection)から、型によるDIに</li>
</ul>

<h2>対象ブラウザに関して</h2>

<p>Angular1.5は、残念ながらIE8以前では動作しません。IE8以前を対象とする場合は、Angular1.2を利用する必要があります。もしIE8を対象にしなくてよいのであれば、Angular1.5へのアップデートが強く推奨されます。</p>

<h2>JavaScriptからTypeScriptへ</h2>

<p>Angular2では、メインの開発言語がTypeScriptに変更されました。</p>

<p>簡単に経緯を説明しますと、もともとAngular2を開発する際、JavaScriptのスーパーセットであるAtScriptという言語を同時に開発していました。</p>

<p>AtScriptの実体は、アノテーション付きのTypeScriptと言ってよいものでしたが、開発は難航。2015年3月にTypeScriptが（アノテーションに近い機能である）デコレーターの実装を表明すると、Angular2はTypeScriptへと移行したという流れがあります。</p>

<p>実際には、Angular2にとってTypeScriptは必須ではなく、JavaScriptやDartでも開発は可能です。しかしTypeScriptを利用すると多くのメリットがあるので、TypeScriptの使用が推奨されています。</p>

<p>ちなみに、TypeScriptというのは以下のような特徴を持った言語です。</p>

<h3>TypeScriptの特徴</h3>

<ul>
<li>型がある</li>
<li>インターフェースがある</li>
<li>モジュールインポートがある</li>
<li>仕様がしっかりしている</li>
<li>JavaScriptのスーパーセットである</li>
<li>TypeScriptはそのままではブラウザでは利用できないのでコンパイル（JavaScriptへの変換）が必要</li>
</ul>

<h2>BrowserifyやWebpackを使おう</h2>

<p>皆さん、GruntやGulpと言ったタスクランナーを既に使われている方は多いと思います。Angular1.5 / 2の開発では、TypeScriptのimport文を使用してモジュール間の依存性を記述していくため、こうした依存関係を解決して実行可能なプログラムを生成できるツールが必要です。</p>

<p>そうしたツールにはBrowserifyやWebpack、System.jsなどがあり、import文やCommonJSのrequire()関数などを解釈し、依存関係を解決した上で、ファイルを一つにまとめる機能を持ちます。</p>

<p>TypeScriptからのコンパイルなどもプラグインとして提供されており、今後のAngular開発には必須のツールとなっています。</p>

<h2>Angular1.5のコードを眺める</h2>

<p>Angular2とAngular1の違いや開発に必要な情報が一通り揃ったところで、実際にAngular1.5のコードを眺めてみましょう。
以下は、画面に「Hello」と表示するだけのプログラムです。</p>

<p></p><pre class="crayon-plain-tag">import * as angular from 'angular';

angular.module('app')
.component('app', {
  template: `&lt;div&gt;Hello {{ $ctrl.text }}&lt;/div&gt;`,
  controller: class App {
    public text: string;
    constructor() {}
  },
  bindings: {
    text: '@'
  }
});</pre><p></p>

<p></p><pre class="crayon-plain-tag">&lt;!doctype html&gt;
&lt;html&gt;
&lt;body&gt;
  &lt;app text="ng-japan"&gt;
    Loading...
  &lt;/app&gt;
  &lt;script src="./bundle.js"&gt;&lt;/script&gt;
  &lt;script&gt;
    angular.bootstrap(document, ['app']);
  &lt;/script&gt;
&lt;body&gt;
&lt;/html&gt;</pre><p></p>

<p>Angular1のコードには違いないように見えますが、これまでとは何かが違いますね。</p>

<p>実際上のコードはTypeScriptで書かれており、<code>import</code>や<code>class</code>、<code>public</code>などのアクセス指定子など、素のJavaScriptでは使えない文法が多く使われています。</p>

<h2>DirectiveからComponentへ</h2>

<p>Angular2から、コンポーネントという概念が登場します。それに合わせて、Angular1.5でもコンポーネントが利用できるようになりました。Angular1のディレクティブに比べて、簡単に作ることができます。</p>

<h1>DirectiveとComponentでの設定値の違い</h1>

<p>Directiveには先述したComponentと呼ばれるDOMの生成と他にAttributeに設定する処理ng-repeatやng-showなども同じ方法で作成しています。</p>

<p>そのため、Componentを作るには設定が過多気味であり、Angular2へ移行する場合に必要なものと不必要なものをより分けた作成メソッドを新たに追加されました。</p>

<p>以下の表が元々のDirectiveメソッドと追加されたComponentメソッドとの設定の違いとなります。</p>

<table>
<thead>
<tr>
  <th align="left"></th>
  <th align="right">Directive</th>
  <th align="center">Component</th>
</tr>
</thead>
<tbody>
<tr>
  <td align="left">bindings</td>
  <td align="right">No</td>
  <td align="center">Yes (binds to controller)</td>
</tr>
<tr>
  <td align="left">bindToController</td>
  <td align="right">Yes (default: false)</td>
  <td align="center">No (use bindings instead)</td>
</tr>
<tr>
  <td align="left">compile function</td>
  <td align="right">Yes</td>
  <td align="center">No</td>
</tr>
<tr>
  <td align="left">controller</td>
  <td align="right">Yes</td>
  <td align="center">Yes (default function() {})</td>
</tr>
<tr>
  <td align="left">controllerAs</td>
  <td align="right">Yes (default: false)</td>
  <td align="center">Yes (default: $ctrl)</td>
</tr>
<tr>
  <td align="left">link functions</td>
  <td align="right">Yes</td>
  <td align="center">No</td>
</tr>
<tr>
  <td align="left">multiElement</td>
  <td align="right">Yes</td>
  <td align="center">No</td>
</tr>
<tr>
  <td align="left">priority</td>
  <td align="right">Yes</td>
  <td align="center">No</td>
</tr>
<tr>
  <td align="left">require</td>
  <td align="right">Yes</td>
  <td align="center">Yes</td>
</tr>
<tr>
  <td align="left">restrict</td>
  <td align="right">Yes</td>
  <td align="center">No (restricted to elements only)</td>
</tr>
<tr>
  <td align="left">scope</td>
  <td align="right">Yes (default: false)</td>
  <td align="center">No (scope is always isolate)</td>
</tr>
<tr>
  <td align="left">template</td>
  <td align="right">Yes</td>
  <td align="center">Yes, injectable</td>
</tr>
<tr>
  <td align="left">templateNamespace</td>
  <td align="right">Yes</td>
  <td align="center">No</td>
</tr>
<tr>
  <td align="left">templateUrl</td>
  <td align="right">Yes</td>
  <td align="center">Yes, injectable</td>
</tr>
<tr>
  <td align="left">terminal</td>
  <td align="right">Yes</td>
  <td align="center">No</td>
</tr>
<tr>
  <td align="left">transclude</td>
  <td align="right">Yes (default: false)</td>
  <td align="center">Yes (default: false)</td>
</tr>
</tbody>
</table>

<p>引用：<a href="https://docs.angularjs.org/guide/component" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">https://docs.angularjs.org/guide/component</a></p>

<h2>Angular1のパフォーマンス問題</h2>

<p>Angular1のパフォーマンスが良くない理由ですが、その原因を挙げてみましょう。</p>

<ul>
<li>Two-wayデータバインディングが重い</li>
<li>状態の監視に伴うオーバーヘッド</li>
<li>dirty check</li>
<li>$digest loop</li>
</ul>

<p>では、どうしたらよいのでしょうか？以下の様なアーキテクチャが推奨されていますが、Fluxアーキテクチャによく似ています。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2016/05/one-way.png" data-wpel-link="internal"><img src="/wp-content/uploads/2016/05/one-way-300x275.png" alt="one-way" width="300" height="275" class="alignnone size-medium wp-image-18871" srcset="/wp-content/uploads/2016/05/one-way-300x275.png 300w, /wp-content/uploads/2016/05/one-way.png 640w, /wp-content/uploads/2016/05/one-way-207x190.png 207w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>

<p>では、このアーキテクチャに従ったコードのサンプルを紹介します。</p>

<p>まずはアプリケーションのエントリーポイントとなるHTML（<code>index.html</code>）です。これは、<code>angular.bootstrap()</code>を呼び出しているだけで、特に変わったことはしていません。ただし、<code>list-cmp</code>というタグを使用していることは覚えておいてください。</p>

<p></p><pre class="crayon-plain-tag">&lt;!doctype html&gt;
&lt;html&gt;
&lt;body&gt;
  &lt;list-cmp&gt;
    Loading...
  &lt;/list-cmp&gt;
  &lt;script src="./bundle.js"&gt;&lt;/script&gt;
  &lt;script&gt;
    angular.bootstrap(document, ['app']);
  &lt;/script&gt;
&lt;/body&gt;</pre><p></p>

<p>以下がサービスのコードです。このサービスは、アプリケーションのデータを保持しており、データの操作を行うことが可能です。</p>

<p></p><pre class="crayon-plain-tag">import * as angular from 'angular';

angular.module('app')
.service('StoreService', class Store{
  private datas: Array&lt;string&gt; = [];
  constructor(){
    this.datas = ['angular', 'javascript', 'typescript', 'angular2'];
  }
  getList() {
    return this.datas;
  }
  addData(data:string) {
    this.datas.push(data);
  }
  changeData(index:number, data:string){
    this.datas[index] = data;
  }
  deleteData(index:number){
    this.datas.splice(index, 1);
  }
})</pre><p></p>

<p>以下は、<code>index.html</code>で使用されていた<code>list-cmp</code>タグ（コンポーネント）の実装です。内部で、さらに<code>lang-cmp</code>というタグ（コンポーネント）を使用しています。</p>

<p>また、Angular1で多用されていた<code>$scope</code>はもう使われておらず、代わりにコンポーネントのコントローラーの参照である<code>$ctrl</code>が使用されています。基本的には、$scopeはもう使用してはならないものとして考えましょう。</p>

<p></p><pre class="crayon-plain-tag">import * as angular from 'angular';

angular.module('app')
.component('listCmp', {
  template: `&lt;ul&gt;&lt;li ng-repeat="data in $ctrl.datas"&gt;
    &lt;lang-cmp index="$index" lang-data="data"
     lang-change="$ctrl.change(index, data)"
     lang-delete="$ctrl.delete($index)"&gt;&lt;/lang-cmp&gt;
  &lt;/li&gt;&lt;/ul&gt;`,
  controller: class List {
    private store;
    private datas: Array&lt;string&gt; = [];
    constructor(StoreService) {
      this.store = StoreService;
      this.datas = StoreService.getList();
    }
    change(index: number, data: string) {
      this.store.changeData(index, data);
    }
    delete(index: number){
      this.store.deleteData(index);
    }
  }
});</pre><p></p>

<p>最後に、<code>lang-cmp</code>タグの実装です。上のコードで指定されていた<code>lang-change</code>や<code>lang-delete</code>と言った属性が、<code>langChange</code>や<code>langDelete</code>といったプロパティに対応しています。</p>

<p></p><pre class="crayon-plain-tag">import * as angular from 'angular';

angular.module('app')
.component('langCmp', {
  template: `&lt;input ng-model='$ctrl.langData'&gt;
  &lt;button ng-click="$ctrl.change()"&gt;変更&lt;/button&gt;
  &lt;button ng-click="$ctrl.delete()"&gt;削除&lt;/button&gt;`,
  controller: class Data {
    private langData:string;
    private index:number;
    private langChange;
    private langDelete;
    constructor() {}
    change() {
      console.log(this.index, this.langData);
      console.log(this.langChange);
      this.langChange({index: this.index, data: this.langData});
    }
    delete() {
      this.langDelete({index: this.index});
    }
  },
  bindings: {
    'langData': '&lt;',
    'index': '&lt;',
    'langChange': '&amp;',
    'langDelete': '&amp;'
  }
})</pre><p></p>

<h2>コンポーネント指向のディレクトリ構造</h2>

<p>コンポーネント指向になったことから、コンポーネント単位にまとめると見通しがよくなります。</p>

<p></p><pre class="crayon-plain-tag">├─about
│  └─components
│          about.component.e2e.ts
│          about.component.html
│          about.component.scss
│          about.component.spec.ts
│          about.component.ts
│
├─app
│  └─components
│          app.component.e2e.ts
│          app.component.html
│          app.component.spec.ts
│          app.component.ts
│          navbar.component.html
│          navbar.component.scss
│          navbar.component.ts
│          toolbar.component.html
│          toolbar.component.scss
│          toolbar.component.ts
│
├─assets
│  │  main.scss
│  │  _colors.scss
│  │  _variables.scss
│  │
│  └─svg
│          more.svg
│
├─home
│  └─components
│          home.component.e2e.ts
│          home.component.html
│          home.component.scss
│          home.component.spec.ts
│          home.component.ts
│
└─shared
    └─services
            name-list.service.spec.ts
            name-list.service.ts</pre><p></p>

<h2>テストについて</h2>

<p>Angular2ではテストの基本セットがJasmineとなっていますので、Jasmineだと学習コストは少なくなります。</p>

<h2>ルーティング</h2>

<p>Angular1ではngRouteよりもui-routerがよく使われていると思いますが、Angular2では性能と管理が簡単なComponentRouterが登場します。
Angular1.5用のComponent Routerが用意されています。</p>

<h2>まとめ</h2>

<p>このセッションで学んだことを最後にまとめます。</p>

<ul>
<li>Angular1のプロジェクトでもTypeScriptを使おう</li>
<li>タスクランナーを利用しましょう</li>
<li>Webpackやbrowserifyを利用しましょう</li>
<li>DirectiveからComponentに変更しよう</li>
<li>controllerの廃止</li>
<li>Scopeは原則利用しないように</li>
<li>Two-way data-bindingよりOne-way data-binding</li>
<li>コンポーネント単位でファイルを整理しよう</li>
</ul>
]]></content:encoded>
			</item>
		<item>
		<title>Angular1から2への移行プロセス、詳しく語ります</title>
		<link>/frontainer/18780/</link>
		<pubDate>Thu, 28 Apr 2016 03:05:16 +0000</pubDate>
		<dc:creator><![CDATA[林 優一]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[システム開発]]></category>
		<category><![CDATA[Angular]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[TypeScript]]></category>

		<guid isPermaLink="false">/?p=18780</guid>
		<description><![CDATA[Angular2のリリースが近づいてきている今、Angular1で開発された資産を、どうやってAngular2に移行していけばよいのでしょうか？ この記事では、実際に移行を行う上でのプロセスを具体的に示していきます。 編...]]></description>
				<content:encoded><![CDATA[<p>Angular2のリリースが近づいてきている今、Angular1で開発された資産を、どうやってAngular2に移行していけばよいのでしょうか？</p>

<p>この記事では、実際に移行を行う上でのプロセスを具体的に示していきます。</p>

<p><em>編集部注: この記事は、2016年3月21日に開催された「<a href="http://ngjapan.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ng-japan 2016</a>」のセッション「Angular1.4で作られた自社マイクロサービスを2へマイグレーション」についての、講演者自身によるレポートです。講演内容に加えて、講演者自身による解説や追記によって、よりわかりやすく詳細な記事に仕上げていただきました。</em></p>

<p><img src="/wp-content/uploads/2016/04/DSC027921.jpg" alt="" width="550" height="382" class="aligncenter size-full wp-image-18853" srcset="/wp-content/uploads/2016/04/DSC027921.jpg 550w, /wp-content/uploads/2016/04/DSC027921-300x208.jpg 300w, /wp-content/uploads/2016/04/DSC027921-207x144.jpg 207w" sizes="(max-width: 550px) 100vw, 550px" /></p>

<p>セッションの講演資料と動画はこちらになります。</p>

<h3>講演資料</h3>

<iframe class="embedly-embed" src="//cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.slideshare.net%2Fslideshow%2Fembed_code%2Fkey%2FMVkoVxeu8i10TT&#038;url=http%3A%2F%2Fwww.slideshare.net%2Ffrontainer%2Fangular142&#038;image=http%3A%2F%2Fcdn.slidesharecdn.com%2Fss_thumbnails%2Fng-japan2016-160321133747-thumbnail-4.jpg%3Fcb%3D1458569152&#038;key=internal&#038;type=text%2Fhtml&#038;schema=slideshare" width="500" height="417" scrolling="no" frameborder="0" allowfullscreen></iframe>

<h3>講演動画（4:19:52付近から始まります）</h3>

<iframe width="560" height="315" src="https://www.youtube.com/embed/4QVMhM75XK8" frameborder="0" allowfullscreen></iframe>

<h2>Angular1から2へ移行する前に</h2>

<p>Angular2への移行を始める前に、Angular1の構成やソースコードを整理する必要があります。公式サイトに「<a href="https://angular.io/docs/ts/latest/guide/upgrade.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">UPGRADING FROM 1.X</a>」という1からアップグレードする手順の解説があります。その手順に加え、実際のアプリケーションの構成を考慮すると以下のような流れになります。</p>

<ul>
<li>事前準備</li>
<li>ng-upgrade</li>
<li>コンポーネント(ディレクティブ)の移植</li>
<li>サービスの移植</li>
<li>ページコンポーネントの移植</li>
<li>フィルターの移植</li>
<li>ルーターの移植</li>
<li>ng1ライブラリの置き換え</li>
<li>ng-upgradeの除去</li>
</ul>

<p>※ セッションでは上記の「サービスの移植」までの前段のみを取り上げています。</p>

<h2>事前準備</h2>

<p>Angular2では1とは異なる点が多く、そのままではすぐにアップグレードすることはできません。そこでまずは1で近い構成にする事前準備が必要になります。</p>

<h3>AngularJS Style Guideに従った構成になっていること</h3>

<p><a href="https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">johnpapa/angular-styleguide Angular 1 Style Guide</a></p>

<p>上記スタイルガイドの<a href="https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#rule-of-1" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Rule of 1</a>及び<a href="https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#folders-by-feature-structure" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Folders-by-Feature Structure</a>、<a href="https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md#modularity" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Modularity</a>の３点には最低限合わせておきましょう。</p>

<p>Angular2ではコンポーネントが中心になり、ファイルの構成もこのスタイルガイドと近い構成になっていきます。あらかじめコンポーネントごとにファイルを分けて置くことで、基本的な設計もコンポーネント指向に近づけておきます。</p>

<p>「<a href="http://qiita.com/laco0416/items/edfa917583af4593ad6c" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">その使い方はもう古いかも？AngularJS老化チェック</a>」という記事の内容が現在のコードに当てはまらないかどうかをチェックしておきましょう。当てはまったものはスタイルガイドに沿ってリファクタリングを行いましょう。</p>

<h3>モジュールローダー（モジュールバンドラー）（Browserify/Webpackなど）を使っていること</h3>

<p>Angular2は必要なスクリプトを読み込んでいって作ることもできますが、モジュールローダー（モジュールバンドラー）前提で話が進んでいくことがあり、導入されていないと理解が難しい状況になります。何も導入していなければBrowserifyかWebpackをおすすめします。公式サイトではSystemJSを用いていますが、Browserify/Webpackを使う場合、必ずしもSystemJSを使う必要はありません。</p>

<ul>
<li><a href="http://browserify.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Browserify</a></li>
<li><a href="https://webpack.github.io/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Webpack</a></li>
<li><a href="https://github.com/systemjs/systemjs" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">SystemJS</a></li>
</ul>

<h3>TypeScriptへ移行</h3>

<p>Angular2入門のページではBabelやTypeScriptなどの利用を、とありますが、マイグレーション時においては<a href="https://www.typescriptlang.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">TypeScript</a>への移行を先にすることを強くお勧めします。</p>

<p>例えば先ほどの「UPGRADING FROM 1.X」のページですが、JavaScript用のドキュメントは準備中となっています（2016年4月現在）。</p>

<p>このような状況からみて、今後の新しい機能についてもTypeScript優先で情報提供されることがあることでしょう。また、既にAngular2に取り組んでいる先人たちのノウハウ（StackOverflowなど）もTypeScriptをベースにしているものが多いので、これを機にTypeScriptを使うと良いでしょう。型などを用いることで移行時の不具合を見つける手助けにもなります。</p>

<h3>コンポーネントディレクティブの使用</h3>

<p>Angular1.5からコンポーネント機能が提供されました。Angular2の基本はコンポーネントで構成されます。そのため、既存のアプリケーションをコンポーネント化していくことで移行がスムーズになります。対応ブラウザに問題がなければまずはAngular1.5にアップグレードし、ディレクティブや共通部分をコンポーネント化しましょう。</p>

<p><a href="https://docs.angularjs.org/guide/component" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Angular Developer Guide / Component</a></p>

<p>ここまでを一通り行い、Angular2への移行の準備が整います。</p>

<p>この時点で難しいと思われる方もいるかもしれません。しかしながら、Angular2でも準備と同様の環境が求められます。Angular2はパフォーマンス改善やコンポーネント指向など魅力的な変更があるのでぜひとも移行していきたいところなのです。いずれにしても、今後も大きなフロントエンド開発においてはこのようなモダン構成が求められることでしょうから、そうした練習としてAngular2を採用するのも良いでしょう。</p>

<h2>Angular2の導入</h2>

<p>Angular2の方へ入っていきたいと思います。最低限必要なものとして以下のものが必要になります。（2016/4/24時点）</p>

<ul>
<li>angular2@2.0.0-beta.15</li>
<li>systemjs@0.19.26</li>
<li>refrect-metadata@0.1.2</li>
<li>rxjs@5.0.0-beta.2</li>
<li>zone.js@0.6.10</li>
<li>es6-shim@0.35.0</li>
</ul>

<p><code>npm install</code>でまとめて導入できます。</p>

<p></p><pre class="crayon-plain-tag">npm install angular2@2.0.0-beta.15 systemjs@0.19.26 refrect-metadata@0.1.2 rxjs@5.0.0-beta.2 zone.js@0.6.10 es6-shim@0.35.0</pre><p></p>

<p>まずAngularの起動方法を変更します。</p>

<p></p><pre class="crayon-plain-tag">&lt;body ng-app="app"&gt;...&lt;/body&gt;</pre><p></p>

<p>これは以下のように<code>angular.bootstrap</code>関数を用いて定義するようにします。この際HTMLに<code>ng-app</code>は不要です。</p>

<p></p><pre class="crayon-plain-tag">angular.bootstrap(document.body,['app'],{strictDi:true});</pre><p></p>

<p>さらにこの部分を<strong>ng-upgrade</strong>と呼ばれているangular2/upgradeの<code>UpgradeAdapter</code>というものを用いてAngularを起動していきます。</p>

<p></p><pre class="crayon-plain-tag">import {UpgradeAdapter} from 'angular2/upgrade';
export const Adapter = new UpgradeAdapter();</pre><p></p>

<p></p><pre class="crayon-plain-tag">import {Adapter} from './adapter.ts';
Adapter.bootstrap(document.body,['app'],{strictDi:true});</pre><p></p>

<p>このようにupgradeの中にある<code>UpgradeAdapter</code>を経由して実行をします。今後1と2を混在させた状態でアプリケーションを動かすためのハブのような役割をこのAdapterが行ってくれます。今後いろいろな場面でAdapterを呼び出して使うことになるので、あらかじめ別のファイルにしておいて外部から参照できるようにしておきましょう。</p>

<p>続いて<code>angular2-polyfill.js</code>を読み込みます。後々<code>Observable</code>を使う時に必要になるので、忘れないように入れておきましょう。</p>

<p></p><pre class="crayon-plain-tag">import 'angular2/bundles/angular2-polyfills';

// for old browsers
import 'es6-shim/es6-shim.min.js';
import 'angular2/es6/dev/src/testing/shims_for_IE';</pre><p></p>

<p>ここでユニットテストなどで<code>PhantomJS</code>などで実行しているとエラーが出ます。<code>es6-shim</code>を入れることで回避することができます。</p>

<p><a href="https://github.com/radify/karma-es6-shim" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">karma-es6-shim</a></p>

<p>TypeScriptにもes6の型定義ファイルが必要になるので、<code>es6-shim</code>の型定義ファイルを入れておきましょう。</p>

<p></p><pre class="crayon-plain-tag">typings install es6-shim --save --ambient</pre><p></p>

<p>以上で移行の前段はできました。ここからはAngular1で作ったものを徐々に2へと置き換えて行く作業になります。</p>

<h2>コンポーネントを置き換え</h2>

<p>まずは他にあまり依存しない、Directiveのrestrict:&#8217;E&#8217;で実装されていたものをAngular2へ移行していきます。大きなところからやりたくなりますが、<strong>移行は末端から順番にやるようにしましょう</strong>。</p>

<p>以下はAngular1のコンポーネントを使って書かれたローディングの例です。</p>

<p></p><pre class="crayon-plain-tag">const template = require('./loading.html');
class LoadingCtrl {
    constructor(private LoadingService) {}
}
angular.module(‘app')
    .component('globalLoading',{
        controller: LoadingCtrl,
        transclude: true,
        template: template
    });
export default LoadingCtrl;</pre><p></p>

<p></p><pre class="crayon-plain-tag">class LoadingService {
    count:number = 0;
    loading:boolean = false;
    constructor() {}
    start() {
        ++this.count;
        this.loading = true;
    }
    stop() {
        --this.count;
        if (this.count === 0) {
            this.loading = false;
        }
    }
}
angular.module(‘app')
    .service('LoadingService',LoadingService);</pre><p></p>

<p></p><pre class="crayon-plain-tag">&lt;div ng-show="LoadingService.loading" class="loading"&gt;
    &lt;div class="loading-text" ng-transclude&gt;&lt;/div&gt;
&lt;/div&gt;</pre><p></p>

<p>このローディングコンポーネントをAngular2に置き換えていきます。
まずはコンポーネント部分を置き換えていきましょう。</p>

<p></p><pre class="crayon-plain-tag">import {Adapter} from '../../core/adapter';
import {Component} from 'angular2/core';
import {LoadingService} from './LoadingService';
const template = require('./loading.html');

@Component({
    selector: 'global-loading',
    template: template
})
export class LoadingCtrl {
    constructor(private LoadingService:LoadingService) {}
}
angular.module('app').directive('globalLoading',&lt;angular.IDirectiveFactory&gt;Adapter.downgradeNg2Component(LoadingCtrl));</pre><p></p>

<p>Angular2の基本はコンポーネントになっているので、出来る限りコンポーネントに置き換えておきましょう。</p>

<p>Angular2で書かれたコンポーネントは1環境では呼び出すことができません。そこでディレクティブに<code>Adapter.downgradeNg2Component()</code>を用いて登録することで、Angular1環境下においても使うことができるようになります。</p>

<p>続いて、サービス部分の移植です。</p>

<p></p><pre class="crayon-plain-tag">import {Adapter} from '../../core/adapter';
import {Injectable} from 'angular2/core';

@Injectable()
export class LoadingService {
    count:number = 0;
    loading:boolean = false;
    constructor() {}
    start() {
        ++this.count;
        this.loading = true;
    }
    stop() {
        --this.count;
        if (this.count === 0) {
            this.loading = false;
        }
    }
}
angular.module('app').factory('LoadingService',Adapter.downgradeNg2Provider(LoadingService));
Adapter.addProvider(LoadingService);</pre><p></p>

<p><code>@Injectable()</code>をつけてInject(DI)可能であることを示します。
コンポーネント同様に、Angular2記法のServiceをAngular1からもDIできるように<code>Adapter.downgradeNg2Provider()</code>を使ってダウングレードして登録しておきます。</p>

<p>加えて、<code>Adapter.addProvider()</code>で作ったサービスを<code>Provider</code>に登録する必要があります。これは<code>UpgradeAdapter</code>を使っている場合で、Angular2のコンポーネントからDIさせるために必要になります。</p>

<p>これを行わないと以下のようなエラーとなります。</p>

<p><code>
EXCEPTION: Error: [$injector:unpr] Unknown provider: LoadingServiceProvider &lt;- LoadingService &lt;- LoadingInterceptor &lt;- $http &lt;- $templateFactory &lt;- $view &lt;- $state</code></p>

<p>同様にHTMLもAngular2記法に置き換えを行います。</p>

<p>ディレクティブでは<code>ng-transclude</code>を使っていましたが、Angular2では<code>ng-content</code>になっているのは注意が必要です。</p>

<p>また、細かいところですが、<code>angular.constants</code>もなくなっているので、<code>const</code>でオブジェクトを作っておき、それを<code>import</code>して使うように置き換えましょう。</p>

<h3>ServiceのAngular2移行</h3>

<p>さて次に、ServiceをAngular2化していきます。
基本はLoadingのときと同じですが、通信周りには変更があります。</p>

<p>Ajax通信を行う際は<code>$http</code>を使って通信を行っていました。Angular2では<code>Http</code>でAjax通信を行うことができます。<code>$http</code>は<code>Promise</code>を返していましたが、<code>Http</code>は<code>Observable</code>を返すという違いがあります。</p>

<p>以下はAngular2記法に置き換えたいわゆるモデルです。作りは先程のローディングの場合と殆ど変わりませんが、<code>Http</code>は<code>Observable</code>を返すので、処理の変更箇所を減らすために<code>Promise</code>で返すようにしています。</p>

<p></p><pre class="crayon-plain-tag">import {Adapter} from '../../core/adapter';
import {Injectable} from 'angular2/core';
import {CONSTANTS} from '../../core/constants';
import {Http, Response} from 'angular2/http';
@Injectable()
export class AccountModel {
    constructor(protected http:Http) {}
    get() {
        return this.http.get(`${CONSTANTS.API_PATH}account`).toPromise();
    }    
}
angular.module('app').factory('AccountModel', Adapter.downgradeNg2Provider(AccountModel));
Adapter.addProvider(AccountModel);</pre><p></p>

<p><code>Http</code>の返す<code>Observable</code>については<a href="https://github.com/ReactiveX/rxjs" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">RxJSのドキュメント</a>を参照してください。</p>

<p><a href="https://github.com/Reactive-Extensions/RxJS" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Reactive-Extensions/RxJS</a></p>

<p>最後にあらかじめコンポーネントにしておいたページでフォームの部分を移植してみます。
まずテンプレートをAngular2記法に置き換えます。</p>

<p>テンプレートの記法は以下の参考リンクを上から順番に見ていくと良いでしょう。</p>

<ul>
<li>*ngIfのようなシンタックスについて &#8211; <a href="https://angular.io/docs/ts/latest/guide/template-syntax.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">TemplateSyntax</a></li>
<li>Angular1ではこう書いてたけど2だとどうなるの？というとき &#8211; <a href="https://angular.io/docs/ts/latest/cookbook/a1-a2-quick-reference.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ANGULAR 1 TO 2 QUICK REFERENCE</a></li>
<li>慣れてきて一覧でみたい時 &#8211; <a href="https://angular.io/docs/ts/latest/guide/cheatsheet.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ANGULAR CHEAT SHEET</a></li>
</ul>

<h3>formの移植</h3>

<p>続いてformの制御部分を移植します。メールアドレスの入力フォームで、バリデーションが通らないと更新ボタンが押せない（disabled）になるというよくあるものです。</p>

<p></p><pre class="crayon-plain-tag">&lt;form ng-submit="$ctrl.save()"&gt;
    &lt;label class="layout-block"&gt;メールアドレス変更&lt;/label&gt;     &lt;div class="form-item"&gt;
        &lt;div class="form-input form-fill"&gt;
            &lt;input ng-model="$ctrl.newEmail" type=“email" name="email" placeholder="新しいメールアドレス" required&gt;
            &lt;span class="form-error"&gt;
                &lt;span ng-if="!form.email.$error.email"&gt;メールアドレスを正しく入力してください&lt;/span&gt;
                &lt;span ng-if="!form.email.$error.required"&gt;必ず入力してください&lt;/span&gt;
            &lt;/span&gt;
        &lt;/div&gt;
    &lt;/div&gt;
    &lt;button ng-disabled="!emailform.$valid" class="btn btn-default btn-revert"&gt;メールアドレスを変更する&lt;/button&gt;
&lt;/form&gt;</pre><p></p>

<p>formの制御のために<code>[ngFormModel]="name"</code>を使います。（これ以外にも複数方法があります）また、inputタグには<code>ngControl="name"</code>を使って名前を付けます。</p>

<p>下記のように書きかえます。</p>

<p></p><pre class="crayon-plain-tag">&lt;form [ngFormModel]="form" (submit)="save();"&gt;
	&lt;div class="form-input"&gt;
		&lt;input [(ngModel)]="user['lastname-phonetic']" ngControl="lastphonetic" type="text" value="" placeholder="セイ"&gt;
		&lt;span class="form-error" *ngIf="form.controls.lastphonetic.errors"&gt;
			&lt;span class="form-error-message"&gt;
				&lt;div [hidden]="!form.controls.lastphonetic.errors.required"&gt;セイは必須項目です&lt;/div&gt;
				&lt;div [hidden]="form.controls.lastphonetic.errors.required &amp;&amp; form.controls.lastphonetic.errors.invalidPhonetic"&gt;全角カタカナで入力してください&lt;/div&gt;
			&lt;/span&gt;
		&lt;/span&gt;
	&lt;/div&gt;
	&lt;button [disabled]="!form.valid" class="btn btn-default btn-revert"&gt;更新&lt;/button&gt;
&lt;/form&gt;</pre><p></p>

<p>フォームのエラー状況によって振り分けしたい部分は[ngFormModel]でつけた名前.controls.inputにつけたngCotrol名.errors.エラー名でエラーが発生しているかどうかを確認することができるようになりますが、スクリプトも修正が必要です。</p>

<p></p><pre class="crayon-plain-tag">import {FORM_DIRECTIVES,Control,ControlGroup,Validators} from 'angular2/common';

@Component({
    selector: 'profile-form',
    templateUrl: 'webroot/components/profile/profile.html',
    directives: [FORM_DIRECTIVES]
})

this.form = new ControlGroup({
	lastphonetic: new Control('',Validators.compose([
		Validators.required,
		ValidateService.phonetic
	]))
});</pre><p></p>

<p>コンポーネント内でform関連のディレクティブを使うときには@Componentのdirectivesに配列で使うディレクティブを指定します。</p>

<p>先ほどngModelFormにつけた名前と同じ名称にnew ControlGroup()します。
そしてngControlにつけた名前と同じ名称でnew Control()します。
第一引数がデフォルトの値、第二引数にバリデーション関数を指定します。
複数指定する場合はValidators.componse([])を１つの場合はValidators.requiredなどを指定します。</p>

<p>Validatorsにはあらかじめ定義されているバリデーターがあります。</p>

<p></p><pre class="crayon-plain-tag">static required(control: modelModule.Control): {
	[key: string]: boolean;
};
static minLength(minLength: number): Function;
static maxLength(maxLength: number): Function;
static pattern(pattern: string): Function;
static nullValidator(c: any): {
	[key: string]: boolean;
};</pre><p></p>

<p>Angular1ではtype=&#8221;email&#8221;でメールアドレスのチェックが行われていましたが、Angular2では上記のチェック以外は行われない点は注意してください。</p>

<p>今回はメールアドレスなので、カスタムバリデータを作成します。</p>

<p></p><pre class="crayon-plain-tag">export const ValidateService = {
	email(control:Control) {
		if (!/^[a-z0-9!#$%&amp;'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i.test(control.value)) {
			return {email: true};
		}
	}
}</pre><p></p>

<p>returnする名称はエラーが発生した時に form.controls.lastphonetic.errors.emailで取得することができる値です。</p>

<p>バリデーションの正規表現についてはAngular1で使用されていたものと同じです。</p>

<p><a href="https://github.com/angular/angular.js/blob/g3_v1_5/src/ng/directive/input.js#L27" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Angular directive/input.js</a></p>

<p>セッションでは時間の関係で移行手順の途中までしかお話できませんでした。
移行作業は作られたアプリケーションによって異なりますが、公式サイトの手順だけではハマりどころも発生することでしょう。</p>

<p>今後移行手順に関してはさらに整理され情報も出てくると思いますので、事前準備をしっかりと行い、ng-upgradeを用いて少しずつ移行を進めていきましょう。</p>
]]></content:encoded>
			</item>
		<item>
		<title>TypeScriptで今すぐ使える実践的『ECMAScript 2015』</title>
		<link>/vvakame/18057/</link>
		<pubDate>Fri, 15 Jan 2016 00:00:34 +0000</pubDate>
		<dc:creator><![CDATA[わかめまさひろ]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[TypeScript]]></category>

		<guid isPermaLink="false">/?p=18057</guid>
		<description><![CDATA[連載： TypeScriptでECMAScript 2015時代のJavaScriptを先取りしよう！ (3)TypeScriptを使ってECMAScript 2015時代のコードを書く 3 第一回は、「なぜTypeSc...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/ts-es2015/" class="series-312" title="TypeScriptでECMAScript 2015時代のJavaScriptを先取りしよう！" data-wpel-link="internal">TypeScriptでECMAScript 2015時代のJavaScriptを先取りしよう！</a> (3)</div><h1>TypeScriptを使ってECMAScript 2015時代のコードを書く 3</h1>

<p><a href="https://html5experts.jp/vvakame/16241/" data-wpel-link="internal">第一回</a>は、「なぜTypeScriptか？」という話を書きました。<a href="https://html5experts.jp/vvakame/17004/" data-wpel-link="internal">前回</a>はTypeScriptで開発する際の環境についてがテーマでした。今回は、最後の締めくくりとしてECMAScript 2015において積極的に利用するべき構文を紹介していきます。</p>

<p>まず、TypeScriptの近況をお伝えしておきます。TypeScriptの現在のバージョンは1.7.5で、この後もまだまだ<a href="https://github.com/Microsoft/TypeScript/wiki/Roadmap" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">アップデート予定</a>は詰まっています。アップデートの予定はたくさんありますが、これは必ずしも機能が十分に揃っていないということを意味しません。</p>

<p>第一回で触れたとおり、TypeScriptはECMAScript 2015のsuperset+型のための構文が導入された言語です。TypeScriptの今後のアップデートはTypeScript自体の使い勝手や、型の柔軟性を改善するためのものが大部分。その証左として、1.5.3より後の1.6.2、1.7.5のアップデートではECMAScript 2015の構文の追加はGeneratorsくらいのものです。つまり、TypeScriptはすでにECMAScript 2015による記述を行うためには十分成熟している、といえます。</p>

<p>次に挙げる機能を使う場合、多くのブラウザで動作させるために何らかの後処理が必要になります。</p>

<ul>
<li>Modules

<ul>
<li>ECMAScript 2015としてのmoduleの仕様は決まりましたが、ブラウザ上で動かせる状態にはありません。そのため、<a href="http://requirejs.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">require.js</a>や<a href="http://browserify.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">browserify</a>、<a href="https://github.com/systemjs/systemjs" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">SystemJS</a>などのツールが必要。</li>
<li>なお、Node.js上で動作させる場合はCommonJSスタイルのJavaScriptとして出力できるためTypeScriptコンパイラによる変換だけで利用可能。</li>
</ul></li>
<li>Generators

<ul>
<li><code>--target es6</code>でのみ利用可である（es5で動く形式に変換できない）ため、利用したい場合は<a href="https://babeljs.io/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">babel</a>による変換が必要。</li>
</ul></li>
</ul>

<p>また、仕組み上es5で動く形に変換ができない（つまり、全くの新機能である）ものもいくつかあります。ブラウザなどの進歩を待ちましょう。</p>

<p>本稿では、すべてのサンプルコードは現代的に、つまりECMAScript 2015的に書くことにします。古くからのJavaScriptユーザとしては見慣れないかもしれない、そして別の言語に慣れている人には、比較的読みやすい記法でしょう。</p>

<p>これから紹介するTypeScript独自の記法ではないものは正式にJavaScriptの仕様になったものであるため、今後数年以内に徐々にすべてのJavaScriptコードが本稿で紹介されるような記法へと移行されていく…といいなぁ。</p>

<p>また、本稿に出てくるサンプルコードは<a href="http://www.typescriptlang.org/Playground" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">TypeScript playground</a>ですぐに試せるリンクをなるべく添えています。Playground上で、変数名などにマウスカーソルをホバーさせるとどういう型として解釈されているか確認できるのでいろいろ試してみてください。Playgroundはmodule周りのサポートがすっぽり抜け落ちているので、その辺りは割愛しています。<a href="https://html5experts.jp/vvakame/17004/" data-wpel-link="internal">前回</a>の記事を参考に、自分で環境を整え、試してみてください。</p>

<h2>TypeScript独自の構文</h2>

<p>まずは、TypeScript独自の構文について述べておきます。独自の構文といっても、型に関する部分についてなのでプログラムの動作には影響しません。プログラムの堅牢さ、分かりやすさ、保守しやすさによい影響があります。</p>

<p>詳しく知りたい場合は、<a href="http://typescript.ninja/typescript-in-definitelyland/types-basic.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">筆者の書いた別の解説</a>や<a href="http://qiita.com/vvakame/items" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">TypeScriptの更新差分解説</a>を参照してください。</p>

<h3>型注釈の基本</h3>

<p>TypeScript最大の特徴として、型の存在とそれを利用した静的なチェックがあります。</p>

<p>JavaScriptにももちろん型は存在しています。string, number, Date, RegExpなどなど多岐に渡りますがJavaScriptでは変数と型を結びつけるということをしませんでした。</p>

<p>TypeScriptでは変数に型を明示的に指定（注釈を与える）ことにより、静的なチェックやIDEによる支援を受けることができます。</p>

<p>変数や引数について型の指定ができる箇所は多くありますが、基本的に次の箇所だけマークしておけば多くの局面に対応できます。</p>

<ul>
<li>初期化なしの変数宣言</li>
<li>関数の仮引数</li>
<li>関数の戻り値の型</li>
<li>型パラメータ</li>
</ul>

<p>TypeScriptでは、変数や仮引数などの後に<code>: 型名</code>という形式で記述します。number, boolean, string, void, anyなど、組み込みの型と、DateやRegExpなど、見知ったJavaScriptのオブジェクトも存在しています。</p>

<p></p><pre class="crayon-plain-tag">"use strict";

// 関数の仮引数と戻り値の型
function concat(a: string, b: string): string {
    return a + b;
}

// 変数の型
let obj1: RegExp;
// 初期化子がある場合、わざわざ型注釈を明記しなくとも自動的に推論される
let obj2 = /^Hi!$/;

let array1: Array;
// array1 と全く同じ意味合い
let array2: boolean[];</pre><p></p>

<p><a href="http://goo.gl/TJ3p76" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Playgroundで試す</a></p>

<p>簡単ですね。型パラメータの考え方は、JavaやC#を知っている人であれば、馴染みのある記法でしょう。TypeScriptは配列だけは特別扱いをしており、<code>Array</code>などの記法の他に、<code>boolean[]</code>という記法をも許しています。これも、JavaやC#を知る人であれば、見たことがある記法かもしれません。TypeScriptでは、配列については<code>boolean[]</code>の記法を使うほうが一般的です。</p>

<h3>Interfaces</h3>

<p>インタフェースは、あるオブジェクトについての性質を記述し、それに名前をつけることができます。JavaやC#ではあるクラスに特定の実装を強制するものとして使いますが、TypeScriptではその範囲にとどまりません。</p>

<p>クラス化するほどでもない、サーバから受け取るデータについて名前をちょいちょいと与える場合などに使われる場合が多いです。</p>

<p></p><pre class="crayon-plain-tag">"use strict";

interface Sample {
    str: string;
    func: (n: string) =&gt; number;
    methodA(): void;
}

let obj: Sample;
obj.str;
obj.func("test");
obj.methodA();</pre><p></p>

<p><a href="http://goo.gl/HH4hLd" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Playgroundで試す</a></p>

<h2>ECMAScript 2015</h2>

<p>さて、それではECMAScript 2015の構文の説明に入っていきます。筆者が育てている4つの個人リポジトリのソースコードを見て、実際に使っているもののみを抜粋してきました。</p>

<p>つまり、ここで紹介している構文は使い勝手がよく、ECMAScript 2015以前よりも改善されている構文である！といえます。</p>

<h3>use strict</h3>

<p>まずは、 &#8220;use strict&#8221;; について紹介しておきます。これはECMAScript 5のときからあるディレクティブです。</p>

<p></p><pre class="crayon-plain-tag">"use strict";

// getterのみあり setterなし
let obj = {
    get str() {
        return "Hi!";
    }
};

// エラーにしてくれる！
// Uncaught TypeError: Cannot set property str of # which has only a getter
// "use strict"; がないと、単に無視されるので値がセットされない謎のバグになり苦しみのたうつ
obj.str = "setterは存在していない";</pre><p></p>

<p><a href="http://goo.gl/BDx6bd" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Playgroundで試す</a></p>

<p>多くの効能があるため、ここでは詳細には解説しません。ここで解説した理由は、<a href="http://www.ecma-international.org/ecma-262/6.0/#sec-strict-mode-code" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ECMAScript 2015の仕様</a>上、後述のクラスやモジュールの内部は暗黙的にstrict modeになるためです。TypeScriptで書いたコードをコンパイルするとクラスやモジュールの構文も変換されてしまい、暗黙的にstrict modeではなくなってしまいます。</p>

<p>そのため、後々ECMAScript 2015が無変換で動く時代になった時に困らぬよう、今のうちからすべてのファイルの先頭に<code>"use strict";</code>を書いておき、挙動を揃えておきます。これはトイレに行った後に手を洗うというレベルのエチケットなので、<a href="https://github.com/palantir/tslint" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">tslint</a>などを活用して忘れないように気をつけましょう。</p>

<h3>let, const</h3>

<p>let, constを紹介します。JavaScriptでは<code>var</code>というキーワードを使って変数定義をしていました。let, constではvarに対して次の違いがあります。</p>

<ul>
<li>ブロックスコープである</li>
<li>同じ変数名を複数回定義しようとするとエラーになる</li>
<li>変数の巻き上げは行われるが宣言前にアクセスするとエラーになる</li>
</ul>

<p>constの場合、さらに追加があります。</p>

<ul>
<li>宣言時に初期化必須</li>
<li>値の置き換え不可</li>
</ul>

<p>便利ですね。varの不思議な挙動について理解しておかねばならない時代も過去のものとなりそうです。多くの場合で単純にvarをletに置き換えできるし、そうしたほうがよいでしょう。varをletに置き換えて動かなくなるようなコードは、JavaScriptの不快な仕様を利用した悪いコードだと考え、リファクタリングするべきです。</p>

<p></p><pre class="crayon-plain-tag">"use strict";

let objA = "Aだよ！";
// ブロックスコープだ！ varはブロックスコープではない
{
    let objA = "Aだけど2番目だよ！";
    // Aだけど2番目だよ！ と表示される
    console.log(objA);
}
// Aだよ！ と表示される
console.log(objA);

// 2重に宣言してもエラーにならない
var objB: any;
var objB: any;

// 2重に宣言するとちゃんとエラーになる（TypeScript上でもプログラム実行時でも）
let objC: any;
let objC: any;

// 定数として宣言すると値の書き換えはエラーになる（TypeScript上でもプログラム実行時でも）
const objD = "Hi!";
objD = "Bye!";

// ちなみに値のさらに中身を書き換えるのは問題ない
const objE = {
    str: "Hi!"
};
objE.str = "Bye!";
// 対策（実行時エラーになる）
const objF = Object.freeze({
    str: "Hi!"
});
objF.str = "Bye!";</pre><p></p>

<p><a href="http://goo.gl/wG8Aqq" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Playgroundで試す</a></p>

<p>なお、TypeScriptで<code>--target es5</code>などでコンパイルした時はletがvarに変換されるため、実行時エラーは発生しなくなってしまいます。実用上はコンパイル時にそれと分かればとりあえずは問題ないでしょう。</p>

<h3>Classes</h3>

<p>オブジェクト指向な言語であればだいたい存在するクラスです。JavaScriptではECMAScript 2015から導入されました。ECMAScript 5までは、prototypeという仕組みを使ってオブジェクト指向なコードを書いていました。</p>

<p>prototypeにも良いところがあり、悪いモノでもないのですが、広く知られているという分かりやすさ、関連する記述がひとところにまとまっているという利点を考えると、やはりclassが使えるというのはありがたいものです。</p>

<p>今後、prototypeの出番は大きく減るでしょう。とはいえ、classの裏側はprototypeであるため、今まで使えたハックも利用可能ではあります。</p>

<p></p><pre class="crayon-plain-tag">"use strict";

class Sample {
    name: string;

    constructor(name: string, public extention = "!") {
        this.name = name;
    }

    hi(): string {
        return `Hi, ${this.name}${this.extention}`;
    }
}

let obj = new Sample("TypeScript");
// Hi, TypeScript! と表示される
console.log(obj.hi());</pre><p></p>

<p><a href="http://goo.gl/xC81cv" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Playgroundで試す</a></p>

<p>JavaやC#を見慣れているユーザであれば、大変親しみやすいコードになったと思います。ぜひ、PlaygroundでどういうES5なコードに変換されるかを確認してみてください。これを手書きで書くのは、チーム内の人数が多くなれば多くなるほど辛く感じるでしょう。</p>

<p>また、クラスが使えるようになりましたが、だからといってなんでもかんでもクラスにしなければならないわけではありません。今までどおり、関数や普通のオブジェクトを使うのが適していると思った場合はどんどん使って構いません。無理にクラスを使おうとするほうが、意図のわかりづらい、よくないコードになってしまうでしょう。</p>

<p>TypeScriptのみの独自仕様として、constructorで<code>public extention = "!"</code>のように、アクセス修飾子付きで仮引数を宣言すると、自動的に自分のプロパティとしてセットされます。ECMAScript 2015の仕様に準拠したコードを書きたい場合は、<code>name</code>プロパティのように、フィールドの宣言をしてから<code>this.name = name;</code>のように自分で代入しましょう。</p>

<p>気になる場合は、tscでのコンパイル時に<code>--target es6</code>を指定してコンパイルし、どのようなpure ECMAScript 2015コードが生成されるかをチェックしてみるとよいでしょう。</p>

<h3>Modules</h3>

<p>モジュールです。ECMAScript 2015では、ついにモジュールという概念が、JavaScriptの仕様として盛り込まれました。今までのJavaScriptにはモジュールの仕様が正式にはなく、AMDやCommonJSなど、それを埋めるための（ECMAScriptではない）仕様が複数考えだされ、実装されてきました。Node.jsではCommonJSのモジュールに仕様に近いものが採用されています。</p>

<p>ECMAScript 2015でのモジュールの仕様は、ざっくりいうと 1ファイル=1モジュール という仕様です。1ファイル毎に名前空間が分割されていて、どの識別子を外部に公開するかを選択していきます。</p>

<p>モジュールの仕様は、静的に（つまり実行することなく）ソースコード間の依存関係が解決できるようになっています。そのため、今までのJavaScriptのコードとはかけ離れた、全く新しい構文をもっています。</p>

<p>コード例を見ていきましょう。utilA.ts, utilB.ts, main.ts という3つのコードを利用します。3ファイルあるので、モジュールが3つあることになります。</p>

<p></p><pre class="crayon-plain-tag">"use strict";

export default function() {
    return "Hi! from utilA";
}</pre><p></p>

<p></p><pre class="crayon-plain-tag">"use strict";

export function hi() {
    return "Hi! from utilB";
}</pre><p></p>

<p></p><pre class="crayon-plain-tag">"use strict";
// es6 moduleを使うと自動的に use strict した事になる。
// しかし、TypeScriptでコンパイルするとそうではなくなってしまうので明示的に指定しておく。

import utilA from "./utilA";
import {hi} from "./utilB";
import * as utilB from "./utilB";

// Hi! from utilA と表示される
console.log(utilA());
// Hi! from utilB と表示される
console.log(hi());
// Hi! from utilB と表示される
console.log(utilB.hi());</pre><p></p>

<p>残念ながら、Playgroundで試すことができないので、お手元に環境を作って試してみてください。</p>

<p>exportして、importするだけの仕様ではありますが、慣れるまでは正しい記法がわかりづらく戸惑いを覚えるでしょう。TypeScriptの利点として、動作しない書き方をした場合きっちりコンパイルエラーにしてくれるので試行錯誤する手間が省けます。</p>

<h3>Arrow functions</h3>

<p>Arrow functions（アロー関数）です。ECMAScript 5までのJavaScriptの関数は、thisの値が他言語ユーザの期待とだいぶかけ離れた動作をしていて辛かったです。アロー関数では期待する挙動と実際の挙動の齟齬がだいぶ軽減されています。</p>

<p></p><pre class="crayon-plain-tag">"use strict";

// 引数なしの場合 括弧は必要
let funcA = () =&gt; {
    console.log("Hi!");
};
// Hi! と表示される
funcA();

// 引数1個の場合、括弧をつけることもできる
let funcB = (name: string) =&gt; {
    console.log(`Hi! ${name}`);
};
// Hi! TypeScript と表示される
funcB("TypeScript");

// 引数が1個の場合、括弧を省略して仮引数名のみを書くことができる
// ただし、括弧を省略する場合仮引数の型を指定することはできない
// このため、ここではfuncC変数に型を指定している
let funcC: (name: string) =&gt; void = name =&gt; {
    console.log(`Hi! ${name}`);
};
// Hi! TypeScript と表示される
funcC("TypeScript");
// 既に型がついている場合そのまま省略できる
funcC = name =&gt; {
    console.log(`Hi! ${name}`);
};
// Hi! TypeScript と表示される
funcC("TypeScript");

let funcD = (name: string, ...rest: string[]) =&gt; {
    console.log(`Hi! ${name} and ${rest.join(", ")}`);
};
// Hi! TypeScript and ECMAScript 2015, ECMAScript 2016 と表示される
funcD("TypeScript", "ECMAScript 2015", "ECMAScript 2016");</pre><p></p>

<p><a href="http://goo.gl/9UY2O3" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Playgroundで試す</a></p>

<p>この使い方では、EMCAScript 5の関数と大差ありませんね。タイプする文字数が減って嬉しいですが、まあ、その程度です。名前付きアロー関数は作ることができませんので、素直に変数に代入しましょう。</p>

<p>次の例を見てみましょう。</p>

<p></p><pre class="crayon-plain-tag">"use strict";

class Sample {
    constructor(public name: string) {
    }

    toString(): string {
        return `${this.name}!`;
    }

    method() {
        // ここはmethodのトップレベルです

        let funcA = () =&gt; {
            // arguments にアクセスできない
            // thisの値はmethodのトップレベルと変わらない
            console.log(`Hi, ${this}`);
        };
        let funcB = function() {
            // arguments にアクセスできる
            // thisの値は undefined
            console.log(`Hi, ${this}`);
        };

        // Hi, TypeScript! と表示される
        funcA();
        // Hi, undefined と表示される
        funcB();
    }
}

let obj = new Sample("TypeScript");
obj.method();</pre><p></p>

<p><a href="http://goo.gl/dOSfsx" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Playgroundで試す</a></p>

<p>アロー関数の特徴が顕著に出ていますね。</p>

<p>理由が明確に説明できない限り、今後はfunctionと記述する関数ではなく、アロー関数を使うべきでしょう。具体的に、今までのfunctionを使うのは名前付き関数を作りたい場合や、thisの値を変更するタイプのAPIをもつライブラリを使う場合などです。</p>

<h3>Default parameters, Rest parameters, Spread operators</h3>

<p>Default parameters（デフォルト値付き引数）、rest parameters（可変長引数）、Spread operators（展開演算子）について取り上げます。これらもECMAScript 2015からの導入になりますが、特にお世話になるのはデフォルト値付き引数でしょう。</p>

<p></p><pre class="crayon-plain-tag">"use strict";

// デフォルト値付き引数
// 当てはまる引数が渡されない場合、指定された値がデフォルト値として利用される
function hi(name = "TypeScript") {
    return `Hi! ${name}`;
}
// Hi! TypeScript と表示される
console.log(hi());
// Hi! ECMAScript 2015 と表示される
console.log(hi("ECMAScript 2015"));

// 可変長引数
function bye(...names: string[]) {
    if (names.length === 0) {
        return `Bye, JavaScript`;
    }
    return `Bye, ${names.join(", ")}`;
}
// Bye, JavaScript と表示される
console.log(bye());
// Bye, JavaScript, ECMAScript 3 と表示される
console.log(bye("JavaScript", "ECMAScript 3"));

function goodOldDays() {
    return ["JavaScript", "ECMAScript 3", "ECMAScript 5"];
}

let array = goodOldDays();
// spread（展開）される
// Bye, JavaScript, ECMAScript 3, ECMAScript 5 と表示される
console.log(bye(...array));
// 同上
console.log(bye(array[0], array[1], array[2]));</pre><p></p>

<p><a href="http://goo.gl/8mjHsl" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Playgroundで試す</a></p>

<p>ECMAScript 5までは、<code>p = p || "TypeScript";</code>のような、JavaScriptユーザ以外にはわかりにくいイディオムを取る必要がありましたがだいぶわかりやすくなりましたね。</p>

<h3>Template string</h3>

<p>Template stringは文字列の生成が今までより簡単にできるようになりました。これにより、文字列を結合してメッセージなどを生成するのが格段に読みやすくなります。Gruntfile.jsやgulpfile.jsでできると、設定ファイルも大変見やすく保守も簡単になります。</p>

<p></p><pre class="crayon-plain-tag">"use strict";

let name = "TypeScript";
// Hi! TypeScript と表示される
console.log(`Hi! ${name}`);

name = "ECMAScript 2015"
// Hi! ECMAScript 2015 と表示される
console.log(`Hi! ${name}`);

// Hi! ECMAScript 2015 と表示される
console.log("Hi! " + name);</pre><p></p>

<p><a href="http://goo.gl/tFF05r" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Playgroundで試す</a></p>

<p>まさにテンプレートですね。</p>

<p>Tagged template stringという機能もあるのですが、あまり有効な使いみちがないのと、活用した有名なライブラリなども登場してきていないので入門レベルでは気にする必要はないでしょう。</p>

<h3>Promises</h3>

<p>ECMAScript 2015から、非同期処理における標準のAPIが定義されました。それがPromiseです。Promiseは「約束する」の名の示すとおり、将来的に処理結果を返すことを約束し、その予約表を先に払い出すイメージです。Promiseの結果は成功か失敗の2状態で表されます。</p>

<p></p><pre class="crayon-plain-tag">"use strict";

let p1 = Promise.resolve(true);
p1.then(value =&gt; {
    // true と表示される
    console.log(value);
});

let p2 = Promise.reject("何かのエラー！");
p2.then(value =&gt; {
    // rejectの場合はここに到達しない
    console.log(value);
}, err =&gt; {
    // 何かのエラー！ と表示される
    console.log(err);
});

let p3 = Promise.reject("何かのエラー！");
p3.catch(err =&gt; {
    // 何かのエラー！ と表示される
    console.log(err);
});

let p4 = new Promise((resolve, reject) =&gt; {
    let xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
            if (xhr.status == 200) {
                resolve(xhr.responseText);
            } else {
                reject(xhr);
            }
        }
    }
    xhr.open("GET", "http://www.typescriptlang.org/");
    xhr.send();
});
p4
    .then(text =&gt; {
        // 通信が成功していたらHTMLがどばー！と表示される
        console.log(text);
    })
    .catch((xhr: XMLHttpRequest) =&gt; {
        // 通信に失敗していたらステータスコードが表示される
        console.log(xhr.status);
    });</pre><p></p>

<p><a href="http://goo.gl/l5KCJN" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Playgroundで試す</a></p>

<p>Playgroundは<code>--target es5</code>で動作しているため、Promiseの型定義が存在していません。コンパイルエラーが出ていてもRunすることはできますが、できれば手元で試してみるのがよいでしょう。</p>

<p>Promiseは今後さまざまな標準APIの一部として使われることになります。ブラウザ上で動くコードを書いている場合でも、ServiceWorkerやfetch APIなどを使うようになると、まず間違いなく触らなければいけなくなるため、今のうちに確実にマスターしておくことをお勧めします。azuさんの<a href="http://azu.github.io/promises-book/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Promise本</a>が大変わかりやすいので熟読すると得るものが大きいと思います。</p>

<h2>まとめ</h2>

<p>いかがでしょうか。わかりやすく使いやすい変更が多いので、今すぐにでも使い始められると思います。まずは、既存コードなしの100% TypeScriptなコードから書き始め、徐々に適用範囲を広げていってみてください。</p>

<p>CoffeeScriptやECMAScript 5なコードからは遅かれ早かれ移行しなければならないと思いますので、本記事を参考に徐々に実践を始めてみてください！それでは良いTypeScript &amp; ECMAScript 2015ライフを！</p>
]]></content:encoded>
		
		<series:name><![CDATA[TypeScriptでECMAScript 2015時代のJavaScriptを先取りしよう！]]></series:name>
	</item>
		<item>
		<title>ポエム駆動開発がエッジすぎる！白石俊平がピクシブの開発環境について、聞いてみた！</title>
		<link>/miyuki-baba/17613/</link>
		<pubDate>Wed, 02 Dec 2015 00:00:03 +0000</pubDate>
		<dc:creator><![CDATA[馬場 美由紀]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[Assault]]></category>
		<category><![CDATA[ES6]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[React]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[esa]]></category>
		<category><![CDATA[idobata]]></category>
		<category><![CDATA[ピクシブ]]></category>

		<guid isPermaLink="false">/?p=17613</guid>
		<description><![CDATA[次々と登場する開発ツールや言語のバージョンアップ。開発スピードがどんどん早くなるWeb業界ですが、実際に企業の開発現場ではどのように開発環境やツール・体制などを構築しているのか──。 HTML5 Experts.jp白石...]]></description>
				<content:encoded><![CDATA[<p>次々と登場する開発ツールや言語のバージョンアップ。開発スピードがどんどん早くなるWeb業界ですが、実際に企業の開発現場ではどのように開発環境やツール・体制などを構築しているのか──。</p>

<p>HTML5 Experts.jp白石俊平編集長が、根ほり葉ほり聞いちゃうシリーズ・第一弾は、ピクシブを訪問！HTML5 Experts.jpのエキスパートでもある川田寛<a href="https://twitter.com/_furoshiki" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">@_furoshiki</a>さんと片倉<a href="https://twitter.com/geta6" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">@geta6</a>さんにお話を聞いてきました。</p>

<p><img src="/wp-content/uploads/2015/11/pixiv-1.jpg" alt="" width="640" height="469" class="aligncenter size-full wp-image-17614" srcset="/wp-content/uploads/2015/11/pixiv-1.jpg 640w, /wp-content/uploads/2015/11/pixiv-1-300x220.jpg 300w, /wp-content/uploads/2015/11/pixiv-1-207x152.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<h2>クリエイターがやんちゃして遊べる基地ピクシブ</h2>

<p><strong>白石：</strong>まずはピクシブのサービスや、川田さんが今どんな業務を担当しているのか聞かせてください。</p>

<p><strong>川田：</strong>ピクシブでは「創作活動をもっと楽しくする」という理念を持って、いろんなサービスを提供しています。イラスト・漫画・小説が投稿できる「<a href="http://www.pixiv.net/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">pixiv</a>」以外にも、ネットショップサービス「<a href="https://booth.pm/ja" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">BOOTH</a>」やグッズ制作サービス「<a href="https://factory.pixiv.net/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">pixivFACTORY</a>」といったECサービス、お絵かきアプリ「<a href="https://sketch.pixiv.net/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">pixiv Sketch</a>」とか、いろいろな創作活動向けのサービスを提供しています。</p>

<p><img src="/wp-content/uploads/2015/11/DSC08801.jpg" alt="" width="640" height="441" class="aligncenter size-full wp-image-17638" srcset="/wp-content/uploads/2015/11/DSC08801.jpg 640w, /wp-content/uploads/2015/11/DSC08801-300x207.jpg 300w, /wp-content/uploads/2015/11/DSC08801-207x143.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /><span style="font-size: 80%"><strong>▲ピクシブ株式会社　エンジニア　川田寛さん</strong></span></p>

<p>私がメインとして担当しているのは　CtoCのECサービスです。同人イベントなどであつかわれる創作物の頒布を、どうやったらネットの力で便利に変えられるのかって、いつも考えてますね。主に「BOOTH」と「pixivFACTORY」を担当しています。</p>

<p><strong>白石：</strong>グッズ化したり、販売できたりするサービスですよね。ピクシブならではの強みってあります？</p>

<p><strong>川田：</strong>「創作活動をしている人」にフォーカスしているところでしょうね。そういう人たちに愛されるサービスにできていると思っているし、社内の空気としても、クリエーターに対する尊敬があって、彼らをどう幸せにできるのかを考えていたりして。</p>

<p>たとえばBOOTHだと、普通のECサービスじゃ採算があわないという理由で蔑ろにされてもおかしくないような作品を作っている人も、ちゃんと大切にできる。例えば、マニアックすぎて日の目を見ない人たちも気軽に参加できるし、投資できるような仕組みも作っています。普通なら500円くらいでしか売れない作品でも、その価値を認めた人は1000円とか1万円というように、購入者側の評価価格で購入できるような仕組みを作ったりとか。</p>

<h2>朝思いついたことをすぐコードで書くスピード感</h2>

<p><strong>白石：</strong>川田さんは入社したばかりですけど、前職との違いをどう感じてますか？</p>

<p><strong>川田：</strong>前は100年以上歴史があったりとか、受託をメインとしている企業だったので、ピクシブとは何もかもが真逆ですね。社員の年代も若いし、サービスもまだできて7年くらい。開発言語一つとっても、今まではJavaがメインだったのが、RubyやPHP、Scala、Goなど、前の会社だったら絶対に手を出さなかったような言語もガンガン使っています。</p>

<p>開発するものについても、大規模な受託案件で、1年以上先にリリースされるようなウォーターフォール型が多かったのですが、ピクシブは自社開発で、それこそ朝に思いついた良いアイデアはその日のうちにコードを書いて形にしてリリースしたりすることもあります。ユーザーに価値を提供していく上で、とにかくスピード感が命なので、そのために多くの権限を現場に委ねているというかんじがしています。</p>

<p><strong>白石：</strong>全然違うんですね。コードを書くってことは、川田さんはプログラマ寄りの仕事なんですか？</p>

<p><strong>川田：</strong>UIまわりが多く、フロントエンドエンジニアをやってます。サーバーサイドも書くときは書きます。うちの会社はフロントエンジニアが3人いますが、みんな特にフロントエンドだけをやっているという感じではありませんね。iOSとかAndroidを作るアプリエンジニアもいますが、あまり境目がなくて何でもやっているというかんじがします。前職はお客様対応みたいなのが絡むので、SEという言葉がぴったりハマるような仕事だったのですが、今は完全にエンジニアです。コードを書くことで、ユーザーへの価値を発揮しています。</p>

<p><strong>白石：</strong>そうなると、仕様策定は誰がやるんでしょうか。</p>

<p><strong>川田：</strong>大きな機能追加とかロードマップは、ディレクターがまとめたり経営層を巻き込んだりしていますが、そうでないものは現場で考えてスピーディーにやってしまいます。</p>

<p><img src="/wp-content/uploads/2015/11/DSC08879.jpg" alt="" width="640" height="425" class="aligncenter size-full wp-image-17661" srcset="/wp-content/uploads/2015/11/DSC08879.jpg 640w, /wp-content/uploads/2015/11/DSC08879-300x199.jpg 300w, /wp-content/uploads/2015/11/DSC08879-207x137.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /><span style="font-size: 80%">　▲ピクシブ株式会社のオフィスには、いたるところに絵師さんのイラストが描かれている。</span></p>

<h2>ポエムはesa、意見交換・情報共有はidobataで</h2>

<p><strong>川田：</strong>うちの会社にはポエム駆動開発というのがあるんです。コードがかけるだけじゃなくて、創作をする人に対して想いが強い人が入社してくる。エンジニアにも想いが強い人がいっぱいいるので、ポエムを通じて刺激されて作る。</p>

<p><strong>白石：</strong>へえ。川田さんはどんなポエムを書いたんですか？</p>

<p><strong>川田：</strong>新サービスとかユーザーの声とかいろんな話が絡んでてあまりまだ公表できない話も多いのですが。作品を扱っているサービスとしては、やはり、それを求めているユーザーとうまく繋いであげないことには、出展しているクリエーターやアーティストさんにとっても良くないわけで。そこをどう改善していけばいいのか、というお話をしていました。</p>

<p>社内では<a href="https://esa.io/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">esa</a>というツールを使ってポエムを語るんです。このサービスはこうやったら成功するんじゃないかって書くと、みんなが反応を示していく。そうやってどんどんプロダクトを改善したり、新しく作り出したりしていますね。</p>

<p><img src="/wp-content/uploads/2015/11/DSC08785.jpg" alt="" width="640" height="425" class="aligncenter size-full wp-image-17659" srcset="/wp-content/uploads/2015/11/DSC08785.jpg 640w, /wp-content/uploads/2015/11/DSC08785-300x199.jpg 300w, /wp-content/uploads/2015/11/DSC08785-207x137.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><strong>白石：</strong>現場から上がってくるボトムアップなかんじがいいですね。</p>

<p><strong>川田：</strong>何を作るのかとか、どう改善するかは現場から上げていけますね。経営層も「お前らでドラスティックに変えていってくれ」って言ってくれて。</p>

<p><strong>白石：</strong>チーム体制は何人くらいでやってるんですか？</p>

<p><strong>川田：</strong>うちのチームだと、BOOTHとpixivFactoryであわせて10名弱くらい。両方ともRailsなど同じ道具を使って作っているので、エンジニアはどちらもみている感じですね。</p>

<p><strong>白石：</strong>アジャイルで開発しているんでしたっけ。</p>

<p><strong>川田：</strong>うちのチームではアジャイルと呼べるほど、そこまできっちりしていません。どちらかといえばDevOpsが自然に機能しているという印象。大きな機能リリースに向けた開発はしているけれど、それだけをメインとしてやってはいられない。いま動いているものに問題があれば、そこで対応もしなくてはいけないので。サポートチームのフィードバックであったり、エゴサーチして問題を探って、<a href="https://idobata.io/ja/home" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">idobata</a>で即座に共有されたり。</p>

<p><strong>白石：</strong>エゴサーチを開発チームがしているのはすごい。社内のコミュニケーションツールは<a href="https://slack.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Slack</a>じゃないんですね。idobataって、Slackと比べてどうなんですか？使いやすいとか。</p>

<p><strong>川田：</strong>Slackとidobataを使ってはいますが、うちのチームだとidobataの方がメインになりましたね。自分たちの使っている範囲で、機能面にそこまでの違いは感じてはいません。Slackはチームごとで導入してしまっているからか、会社全体として導入しているidobataのほうがオープンに議論が交わされてて。他のチームのスレをみて気軽に意見を言ったり、挙句にプルリクを作って後方支援することもあったり。プロダクトやチームを超えて議論がされていますね。</p>

<h2>タスク管理はカンバン。具体的なタスクはGitHub</h2>

<p><strong>白石：</strong>タスク管理は何を使ってます？</p>

<p><strong>川田：</strong>うちのチームだと、タスク管理はカンバン。ToDoリストとしてざっくりタスクをポストイットで並べてます。トラブルがあったらそっちを優先したり、技術的な問題で遅れることもあります。タスクも今まで見てきた中ではわりと独立性が高いとおもってて、エンジニアやデザイナー、ディレクターやサポート担当者など、全員にビルド/デプロイ権限があって、自分たちが主体になってデプロイにまでもっていく。とはいえ、リーダーが責任をとるとか、デプロイした人が責任をとるとかそういうものもなく、リスクはチーム全体でうまく運用方法を改善しながらカバーしていきます。</p>

<p><img src="/wp-content/uploads/2015/11/DSC08778.jpg" alt="" width="640" height="440" class="aligncenter size-full wp-image-17653" srcset="/wp-content/uploads/2015/11/DSC08778.jpg 640w, /wp-content/uploads/2015/11/DSC08778-300x206.jpg 300w, /wp-content/uploads/2015/11/DSC08778-207x142.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>細かい機能とかコードレベルの話はGitHubです。プライベートのリポジトリ上に、Issue立てたり、PullRequest作ってMergeして、みたいなかんじです。よくあるGitHubの普通な運用方法になるとおもいます。</p>

<p>想いとか、こうやったほうがいいというポエムは<a href="https://esa.io/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">esa</a>、具体的なのはGitHubです。全体像はカンバンで、普段のコミュニケーションはidobataがメインです。</p>

<p><img src="/wp-content/uploads/2015/11/DSC08779.jpg" alt="" width="640" height="429" class="aligncenter size-full wp-image-17654" srcset="/wp-content/uploads/2015/11/DSC08779.jpg 640w, /wp-content/uploads/2015/11/DSC08779-300x201.jpg 300w, /wp-content/uploads/2015/11/DSC08779-207x139.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><strong>白石：</strong>ほかに開発体制で面白いトピックはありますか？</p>

<p><strong>川田：</strong>開発体制とは違うかもしれないんですけど、前の会社ではコミュニケーション手段がほぼメールと電話だけだったんです。それがこの会社に来てからは、メールと電話は一切使ったことがない。一度もです。ツールをしっかり固めて、コミュニケーションコストを下げると、得られる情報量が大きくなって、結果としてチームを超えていろんな情報にアクセスできるんです。ツールひとつで、ここまで組織がフラットになれるものなんですね。</p>

<p>ただ一方で、まずいと思うところもあって。メールや電話といったツールは、一般的なビジネスでは必須のコミュニケーションツールですよね。オーバーヘッドはとてつもなく大きいのですが、使わなくなるとそれはそれで、マナーやルールがわからなくなって社会から取り残されていく不安も感じるんです。両方のバランスが重要と感じています。</p>

<p><strong>白石：</strong>社員同士のやりとりは何を使ってるんですか？</p>

<p><strong>川田：</strong>一部はSkypeですが、基本はidobataでオープンにしてます。idobataのタイムライン上には、社員同士のやりとりだけじゃなく、自動的にデプロイの情報が流れてきたり、サポートの状況とかが流れてきたりで、社員同士のやりとりが発生しやすいというかんじがしています。</p>

<h2>インフラはコンシューマ向きの超安いサーバー？</h2>

<p><strong>白石：</strong>開発環境はどうですか？</p>

<p><strong>川田：</strong>開発環境の話だと、うちにはちょっとした特殊なインフラがありまして。初期のpixivは社長が借金をして買ってきた大量のサーバーがあるのですが。コンシューマー向けの安いマザーボードを、ラックにくくりつけて使ってるんですよ。ほんとうにむき出しのままなんです(笑)。</p>

<p><img src="/wp-content/uploads/2015/11/DSC08793.jpg" alt="" width="640" height="412" class="aligncenter size-full wp-image-17658" srcset="/wp-content/uploads/2015/11/DSC08793.jpg 640w, /wp-content/uploads/2015/11/DSC08793-300x193.jpg 300w, /wp-content/uploads/2015/11/DSC08793-207x133.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>さすがに今は本番環境をデータセンターに預けるようにしていますが、開発環境には未だにそのマザーボードむき出しのサーバーをインフラとして使ってるんです。インフラチームの図画工作スキルは、いまだに高いようですね(笑)。</p>

<p>インフラの話をもう少し突っ込んですると、pixivの場合はサービスの特性上、クラウドよりオンプレのほうが向いていてそっちが中心ですね。とはいえ、ところどころにクラウドは使われていて、新しいプロジェクトだとAWSみたいなクラウドも使われています。</p>

<p>データベースは、基本的にはMySQL使ってます。OSはLinux。新しいプロジェクトはRails使うことが多いんですが、「Rails最強!! Railsじゃないとダメだ！」みたいな人はいなくて、ツールとして使っているという印象です。</p>

<h2>サービスはリリースした時の最新技術で</h2>

<p><strong>白石：</strong>HTML5 Experts.jpはフロントエンド開発者が主な読者なので、フロントエンド開発の話も聞かせてもらえますか？</p>

<p><strong>川田：</strong>私が関わるBOOTHだと、マークアップはSlim、CSSはSASSやCoffeeScriptとか。Ruby書いている人にやりやすい環境で整っています。また、開発したのが2013年なので、CoffeeScript、Backbone.js、Marionette.jsなどを使ってます。いまだとReactあたりがもっと上手く問題を解決してくれたりするんでしょうし、SPA（Single page application）ももっといいやり方があるのでしょうが、当時の技術を使っているので…。</p>

<p>とはいえ、2007年に作られたpixivでも、CoffeeScriptが使われていたりはします。部分的に入れ替えも進んでいます。今年の6月にリリースしたお絵かきアプリ「pixiv Sketch」は、React.jsやBabelが使われています。もろ時代の影響を受けていますね。</p>

<p><strong>白石：</strong>それだけフロントエンドの流れが早いってことですね。</p>

<p>フロントエンドだと、そこそこエッジな事例がきけそうな、pixiv Sketchのエンジニアを呼んでみますね。</p>

<h2>ReactとFluxでサーバーサイドレンダリング</h2>

<p>──ということで、geta6さんにご登場いただきました。</p>

<p><strong>geta6：</strong>片倉@geta6です。「pixiv Sketch」の担当エンジニアをしています。</p>

<p><strong>白石：</strong>ぜひ、フレームワーク周りで面白い話を聞かせてください。</p>

<p><strong>geta6：</strong>ブラウザ版のpixiv Sketchは、Node.js上で動かしています。</p>

<p><img src="/wp-content/uploads/2015/11/DSC08807.jpg" alt="" width="640" height="438" class="aligncenter size-full wp-image-17737" srcset="/wp-content/uploads/2015/11/DSC08807.jpg 640w, /wp-content/uploads/2015/11/DSC08807-300x205.jpg 300w, /wp-content/uploads/2015/11/DSC08807-207x142.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /><span style="font-size: 80%"><strong>　　▲ピクシブ株式会社　エンジニア　片倉弘貴さん</strong><br></span></p>

<p><strong>白石：</strong>Node.jsってことは、サーバーサイドから全然違うかんじなんでしょうか。</p>

<p><strong>geta6：</strong>サーバーサイドは、RailsによるAPIサーバーと、Node.jsによるレンダリングサーバーで構成されていて。前者はgrapeを使用していてviewを持たずJSONしか吐かない仕様になっていて、後者はサーバーサイドでAPIを叩いてDOMを構築するReactサーバーになっています。</p>

<p><strong>白石：</strong>なるほど。最近、Universal JavaScriptととも言われているIsomorphic Javascriptですね。それでサーバーサイドレンダリングしてるって、まさに最新ですね。</p>

<p><strong>geta6：</strong>フレームワークは、Yahooさんが作ったfluxibleというのを使っています。サーバーとクライアントが同じコードで動くので、キツイ面もありますけど。</p>

<p><strong>白石：</strong>fluxibleって、結構ヘビーだって聞きますね。</p>

<p><strong>geta6：</strong>fluxibleは一人でさくっと開発する場合とか、SPA（シングルページアプリケーション）とかには向いてないかもしれません。ただ、pixiv Sketchみたいに複数人数で開発する場合は、ある程度がっつりしたコードを書けるし、メンテナビリティがあるので魅力的です。</p>

<p>良いところは、二重実装をしなくていいことですね。テンプレートをslim側で書いて、Backbone.jsからもってきて、Javascriptテンプレート内にテキストテンプレートをもう一個書いて…とか面倒なことはしなくていい。同じコードベースでAPIのリクエストとかすべてのことができるので、そこが便利です。</p>

<p><strong>白石：</strong>サーバーとクライアントが同じコードで動くのがキツイと言ってましたが、具体的にはどんなところが大変なんですか？</p>

<p><strong>geta6：</strong>Reactは、クライアント側の世界とサーバー側の世界で、呼ばれるメソッドが違うところがあるんです。componentDidMountっていうメソッドなんですが、それはクライアント側にしか呼ばれないので、その中ではCanvasの操作やDOMの操作が書けるんです。それがわかっていればそんなにつらくないけど、React始めたばかりだと、その辺がわからないのでつらいのかもしれないです。</p>

<p><strong>白石：</strong>getaさんの勉強量は相当すごそうですね。</p>

<p><strong>geta6：</strong>いつもはそんなに勉強はしてないんですけど、pixiv Sketch始めるときに、Reactが流行ってるって聞いて、どうしてもやりたいって言ったら採用されたんです。React全然知らなかったのに、採用されたので一から徹底的に勉強しました(笑)。</p>

<p><img src="/wp-content/uploads/2015/11/DSC08863.jpg" alt="" width="640" height="406" class="aligncenter size-full wp-image-17744" srcset="/wp-content/uploads/2015/11/DSC08863.jpg 640w, /wp-content/uploads/2015/11/DSC08863-300x190.jpg 300w, /wp-content/uploads/2015/11/DSC08863-207x131.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<h2>課題はパフォーマンス改善。野望はES6への乗り換え</h2>

<p><strong>白石：</strong>お二人が、今課題だと思ってることってありますか。</p>

<p><strong>川田：</strong>まだ入社したばかりなので、あまり深く掴めていませんが。自分の関わっているサービスのパフォーマンスが悪いことが気になっていますね。RailsとかJavaScriptとか、いろんなところに悪さするのが潜んでいますね。</p>

<p>もう一つは闇のコードたち。締め切り間際で、アドホックに作りこんじゃったコードとかがたくさんありまして。たとえば、BOOTHは「<a href="https://booth.pm/apollo/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">APOLLO(アポロ)</a>」という同人音楽をネット上で頒布する即売会イベントを開いていて、そういうイベント対応のために作りこまれて、めったに呼ばれないメンテされにくい闇のコードが眠っているんです。ある日とつぜん爆発しそうなので、なんとか阻止したいです。すでに若干、爆発しかけていますが…</p>

<p>こういう、サービス固有の問題みたいなのは山程ありますが、それ以外はとくに不安を感じてはいません。テストコードも書かれているし、最新のバージョンに上げていきましょうというモチベーションもある。機能追加や改善ばかりな企画屋さんがいるチームは世の中にいっぱいいるけど、うちはコードヘルスがサービスのライフサイクルやセキュリティにどんな影響を与えるのか理解されているし、バージョンアップしておかないと大変という感覚とか、エンジニアならわかる勘所を大事にしてくれています。上手くやれている感じがしています。</p>

<p><strong>白石：</strong>今後チャレンジしたいことはどうでしょう。</p>

<p><strong>川田：</strong>やっぱり、早くES6にしたいです。CoffeeScriptやめたい(笑)。</p>

<p><strong>白石：</strong>でも、CoffeeScriptのほうが言語的な機能は上じゃないですか？</p>

<p><strong>geta6：</strong>CoffeeScriptって1週間前に書いた自分のコードが読めなくなるんですよ。言語機能が強すぎて。特殊な記法が必要だし。ES6では普通に読めるから、メンテナンス性は高いですよね。</p>

<p><strong>川田：</strong>CoffeeScriptって、少し大きくなってくると、ビルドした結果を想像しながら書かなきゃいけなくなることがある。Devツールで、ちょっとこの値どうなってるんだろうとかコンソールを叩き始めると、今までCoffeeScriptのコードを読んでたはずなのに、完全にJavaScriptに戻ってたり。</p>

<p><strong>geta6：</strong>CoffeeScript書いてるより、JavaScript書いてるかんじが強いんですよね。インデントが効かないのも厳しい(笑)。</p>

<p><strong>川田：</strong>そうなんです。以前、私はTypeScriptを使っていたんですが、あれはビルドした結果がストレートに想像できるのがいい。あと、将来を見据えるとやっぱりES6を推しちゃいますね。</p>

<p><img src="/wp-content/uploads/2015/11/DSC08857.jpg" alt="" width="640" height="438" class="aligncenter size-full wp-image-17747" srcset="/wp-content/uploads/2015/11/DSC08857.jpg 640w, /wp-content/uploads/2015/11/DSC08857-300x205.jpg 300w, /wp-content/uploads/2015/11/DSC08857-207x142.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<h2>Nodeのデプロイツールに定番がほしい</h2>

<p><strong>白石：</strong>getaさんはどうですか？</p>

<p><strong>geta6：</strong>開発環境の課題は、Node.jsのデプロイツールとプロセスマネージャーに定番がないことですね。デプロイは、信頼性をとってcapistranoを使ってるんですよ。Nodeのデプロイツールはどれも機能が貧弱で手数も多いので、定番でいいのが出てこないかなって思ってます。</p>

<p><strong>白石：</strong>プロセスマネージャーは何を使ってるんですか？</p>

<p><strong>geta6：</strong>プロセスマネージャーはPM2を使ってます。capistranoからシンボリックリンク設置して、currentで新しいファイルをディレクトリに送るんですが、Nodeのファイルシステムが変わってから、シンボリックリンクを追跡して、デプロイ前のファイルのところで監視しちゃうようになったんです。そこでプロセスマネージャーが生きちゃってるので、デプロイしてもファイルが新しくならないんです。そこで一回殺すというのをやってるので、ダウンタイムが若干できてしまうっていう問題点があります。</p>

<p><strong>白石：</strong>そういった課題の改善に取り組んでいるんですね。次にチャレンジしたいことはありますか？</p>

<p><strong>geta6：</strong>API側はバックエンドのプロセスマネージャーがUnicornなんですけど、ラインがN個しかなくて、同時に来ちゃったらつまっちゃうんです。Node側でいいかんじでリクエストをバッファリングしてうまく送れないかと。受付サーバーをNodeにしてゆっくり流すというようなことをしたいです。</p>

<p><strong>白石：</strong>なかなかエッジなプロジェクトになりそうですね。</p>

<p><img src="/wp-content/uploads/2015/11/DSC08859.jpg" alt="" width="640" height="394" class="aligncenter size-full wp-image-17749" srcset="/wp-content/uploads/2015/11/DSC08859.jpg 640w, /wp-content/uploads/2015/11/DSC08859-300x185.jpg 300w, /wp-content/uploads/2015/11/DSC08859-207x127.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><strong>geta6：</strong>requestIdleCallBackだっけ？あれも何かやってみたい。</p>

<p><strong>川田：</strong>ピクシブで「<a href="https://tokyo-web-perf.doorkeeper.jp/events/30701" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">東京 Web Performance</a>」という濃い勉強会をやったんですけど、エッジすぎて人が集まらないかなと思ったら、エッジな人が結構集まってきて(笑)。第一回は「requestIdleCallback」を味見したんですが、広告やアナリティクスに割といいかんじで使えそうだったんで、全力で攻めるんじゃないかって話をしてました。ピクシブに思いのほか、いい影響を及ぼしそうな予感がしてます。</p>

<p><strong>白石：</strong>じゃあ、そこも次のチャレンジになりそうですね。今日は面白いお話を聞かせていただき、ありがとうございました。</p>

<p><img src="/wp-content/uploads/2015/11/DSC08876.jpg" alt="" width="640" height="448" class="aligncenter size-full wp-image-17736" srcset="/wp-content/uploads/2015/11/DSC08876.jpg 640w, /wp-content/uploads/2015/11/DSC08876-300x210.jpg 300w, /wp-content/uploads/2015/11/DSC08876-207x145.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>
]]></content:encoded>
			</item>
	</channel>
</rss>
