<?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>プログラミング &#8211; HTML5Experts.jp</title>
	<atom:link href="/category/programming/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>Webブラウザからハードウェアにアクセス！WebUSB APIを使ってログイン認証を実装してみよう</title>
		<link>/tokutoku393/24790/</link>
		<pubDate>Wed, 20 Dec 2017 01:00:12 +0000</pubDate>
		<dc:creator><![CDATA[ちゃんとく]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[WebUSB API]]></category>
		<category><![CDATA[WoT]]></category>

		<guid isPermaLink="false">/?p=24790</guid>
		<description><![CDATA[近年「IoT」がバズワードとなっていますが、「WoT（Web of Things）」というワードを聞いたことがあるでしょうか？ 「WoT」はごくごく簡単にいうと、既に普及しているHTMLやJavaScriptなどのWeb...]]></description>
				<content:encoded><![CDATA[<p>近年「IoT」がバズワードとなっていますが、「WoT（Web of Things）」というワードを聞いたことがあるでしょうか？</p>

<p>「WoT」はごくごく簡単にいうと、<strong>既に普及しているHTMLやJavaScriptなどのWeb技術を使ってIoTの開発を標準化しよう</strong>、という考え方です。WebBluetooth APIやWebNFC APIなど、みなさんが慣れ親しんでいるWeb技術を使ってハードウェアを制御する方法も増えてきています。</p>

<p>今回は、WebページからPCに繋がれたUSBデバイスを制御することができる「WebUSB API」の概要とサンプルを紹介します。</p>

<p>HTMLと簡単なJavaScriptで試せる内容になっていますので、Webデザイナーやディレクターなどエンジニアではない方もぜひチャレンジしてみてください！</p>

<h2>WebUSB APIとは</h2>

<p>WebUSB APIは<strong>PCに接続された全てのUSBデバイスにウェブから直接アクセスすることができる技術</strong>です。USBデバイスの認識、読み出し、書き込みなどを行うことができます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/119003/e60c1a3a-95f1-a163-598e-e9214908c49e.png" alt="スクリーンショット 2017-12-13 18.23.13.png" title="スクリーンショット 2017-12-13 18.23.13.png" /></p>

<p>Googleの2人のエンジニアによって開発され、2017年9月にはChromeブラウザ（Google Chrome 61）で正式に採用されました。</p>

<p>WebUSB APIを利用するとただちにユーザのUSBデバイス全てにアクセスできる、というわけではなく、ユーザがWebページとUSBデバイスの相互通信を明示的に許可することで開始されます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/119003/c98a6e79-dff6-b100-7413-01fc77b20901.png" alt="スクリーンショット 2017-12-13 16.19.16.png" title="スクリーンショット 2017-12-13 16.19.16.png" /></p>

<p>WebUSB APIのポリシーやセキュリティについては、Googleの開発者向けページで詳細に紹介されています。</p>

<p>⇒ <a href="https://developers.google.com/web/updates/2016/03/access-usb-devices-on-the-web" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Access USB Device on the Web</a>（Google Developers）</p>

<h3>WebUSB APIの活用シーン</h3>

<p>WebUSB APIを活用することで、これまで事前にドライバやソフトウェアのインストールが必要だったUSBデバイスのセットアップが、サイトにアクセスして許可するだけで自動で行えるなどの連携が考えられそうです。</p>

<p>またデバイスの開発者サイドのメリットとしても、OSごとに異なっていたドライバ開発がJavaScript SDKを使ってクロスプラットフォームに構築できるそう。</p>

<p><a href="https://github.com/webusb/arduino" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">webusb/arduino</a>などの例を利用してArduinoなどのマイコンボードをWebから制御することも可能になりました。</p>

<p>詳細な仕様は開発者のドラフトを確認してみてください。</p>

<p>⇒ <a href="https://wicg.github.io/webusb/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">WebUSB API</a></p>

<h3>本格利用はこれから</h3>

<p>ただし、実際にWebUSB APIを導入するにはまだまだ課題がありそうです。</p>

<p>USBアクセスを求めるWebページを公開するために資格や証明が必要ということはなく、利用ユーザは「本当に信頼できるWebページか」ということを知る方法が今のところありません。</p>

<p>また開発者サイドも、USBデバイスの情報が新しくなったり変更されたりするたびにWebページを改修する必要がある可能性もあります。</p>

<p>利用には気をつけるべきポイントが多く、WebUSBはまだ開発中の段階と捉えたほうがよさそうです。安全面、実装面ともに改良され、より使いやすい機能となっていくことに期待ですね。</p>

<h2>WebUSB APIを使ってログイン認証を実装してみよう</h2>

<p>今回は「登録済みのUSBデバイスならログインする」というWebページを作ってみます。</p>

<p><a href="https://gyazo.com/efdd078ea499c97f4b846c271cba0866" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="https://i.gyazo.com/efdd078ea499c97f4b846c271cba0866.gif" alt="https://gyazo.com/efdd078ea499c97f4b846c271cba0866" /></a></p>

<h3>用意するもの</h3>

<ul>
<li>Chromeブラウザ</li>
<li>任意のUSBデバイス（筆者はiPhone7）</li>
</ul>

<h3>手順1：Chromeのバージョンを確認する</h3>

<p>はじめに、ChromeブラウザがWebUSB APIに対応したバージョンになっているか確認します。</p>

<p>Chromeのツールバーから［Google Chromeについて］を選択します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/119003/8ea91b14-86f0-ecc1-2e25-3700fa093e79.png" alt="スクリーンショット 2017-11-22 20.21.35.png" title="スクリーンショット 2017-11-22 20.21.35.png" /></p>

<p>Chromeの情報ページが開くのでバージョンが62以上であることを確認します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/119003/809c864a-c55d-0f09-d82f-2eb59a13291f.png" alt="スクリーンショット 2017-11-22 20.23.10.png" title="スクリーンショット 2017-11-22 20.23.10.png" /></p>

<p>基本的には自動でアップデートされているはずですが、万が一されていない場合は下記を参考にアップデートしましょう。</p>

<p>⇒ <a href="https://support.google.com/chrome/answer/95414?hl=ja" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Google Chromeを更新する</a>（Google Chrome ヘルプ）</p>

<h3>手順2：ログインページを作る</h3>

<p>WebUSB APIを設置するWebページを作ります。今回はコード共有サービス「<a href="http://codepen.io/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">CodePen</a>」からログインフォームのソースコードを利用しました。</p>

<p><img src="https://qiita-image-store.s3.amazonaws.com/0/119003/d01701d7-a934-74ea-3349-9ec138efa074.png" alt="スクリーンショット 2017-11-26 18.11.58.png" title="スクリーンショット 2017-11-26 18.11.58.png" /></p>

<p><a href="https://codepen.io/Lewitje/pen/BNNJjo?q=login%20&amp;order=popularity&amp;depth=everything&amp;show_forks=false" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Calm breeze login screen</a>（CodePen）</p>

<p>［Export］からソースコードを取得しローカルに配置します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/119003/11162f82-8510-3be3-17e6-0452e538ae1c.png" alt="スクリーンショット 2017-12-12 19.42.00.png" title="スクリーンショット 2017-12-12 19.42.00.png" /></p>

<p>今回は<strong>「Username」「Password」は不要</strong>なので、<code>index.html</code>のフォーム部分から消去しておきます。</p>

<p></p><pre class="crayon-plain-tag">&lt;form class="form"&gt;
	&lt;input type="text" placeholder="Username"&gt; // この行を消去
	&lt;input type="password" placeholder="Password"&gt; // この行を消去
	&lt;button type="submit" id="login-button"&gt;Login&lt;/button&gt;
&lt;/form&gt;</pre><p></p>

<h3>ログインのイベントを作成する</h3>

<p>LoginボタンをクリックしたらWebUSB APIのイベントが発火するよう、Submitボタンを変更します。</p>

<p><code>auth()</code>というfunctionを呼ぶようにし、記述用のJSファイルの呼び出しも追加しておきます。</p>

<p></p><pre class="crayon-plain-tag">&lt;form class="form"&gt;
		&lt;button type="button" onclick="auth()" id="login-button"&gt;Login&lt;/button&gt;
	&lt;/form&gt;
	&lt;script src="js/webusb.js"&gt;&lt;/script&gt;
&lt;/body&gt;</pre><p></p>

<p>ログイン成功時のイベント（デフォルトのJQuery）は名前つき関数にしておきます。</p>

<p></p><pre class="crayon-plain-tag">function login() {
  $('form').fadeOut(500);
  $('.wrapper').addClass('form-success');
}</pre><p></p>

<h3>USBデバイスにアクセスして識別情報を取得する</h3>

<p>認証に使用するデバイスを識別するために、［Vendor ID］, ［Product ID］, [Serial Number]を調べてみます。</p>

<p>Macの方は［システム情報］-&gt;［USB］で確認できます。</p>

<p>Windowsの方はMicroSoftの<a href="https://github.com/Microsoft/Windows-driver-samples/tree/master/usb/usbview" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">usbview</a>などを利用しましょう。
<img src="/wp-content/uploads/2017/12/4c4c20ebf1b9d2c14a27ef276ede753e-300x144.png" alt="" width="300" height="144" class="alignnone size-medium wp-image-24956" srcset="/wp-content/uploads/2017/12/4c4c20ebf1b9d2c14a27ef276ede753e-300x144.png 300w, /wp-content/uploads/2017/12/4c4c20ebf1b9d2c14a27ef276ede753e.png 640w, /wp-content/uploads/2017/12/4c4c20ebf1b9d2c14a27ef276ede753e-207x99.png 207w" sizes="(max-width: 300px) 100vw, 300px" />
※このシリアル番号は、iPhone自体のシリアル番号とは別です。</p>

<p><code>/js</code>フォルダの配下に<code>webusb.js</code>ファイルを作成し、<code>auth</code>functionを作成します。コード内には取得したVendor ID（製造元 ID）、Product ID（製品 ID）、Serial Number（シリアル番号）を追加します。</p>

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

const auth = () =&gt; {
  const vendorId = XXXX; // ここにVendor ID
  const productId = XXXX; // ここにProduct ID
  const serialNumber = 'XXXXXXXX'; // ここにSerial Number
  navigator.usb.requestDevice({ 'filters': [
      { 'vendorId': vendorId, 'productId': productId }
    ]
  }).then(device =&gt; {
    if (device.serialNumber === serialNumber) {
      console.log('success!');
      login();
      return device.open;
    } else {
      console.log('false!');
      alert('認証に失敗しました');
    }
  }).catch(error =&gt; {
    console.log(error);
  });
}</pre><p></p>

<p>今回は簡易的にJSファイルに直接認証情報を書いています。</p>

<h3>ログイン機能を試してみよう</h3>

<p>登録したUSBデバイス（今回はiPhone）で試してみます。<br />
<a href="https://gyazo.com/efdd078ea499c97f4b846c271cba0866" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="https://i.gyazo.com/efdd078ea499c97f4b846c271cba0866.gif" alt="https://gyazo.com/efdd078ea499c97f4b846c271cba0866" /></a>
認証が成功しました。</p>

<p>登録していないiPhoneでも試してみます。<br />
<a href="https://gyazo.com/c7af13bc72c09579ff6604ede333a825" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="https://i.gyazo.com/c7af13bc72c09579ff6604ede333a825.gif" alt="https://gyazo.com/c7af13bc72c09579ff6604ede333a825" /></a>
認証に失敗しました。</p>

<p>これでUSBデバイスを識別することができました！</p>

<h2>まとめ</h2>

<p>今回はUSB接続したスマートフォンを利用しましたが、マウス、キーボード、フラッシュメモリなどUSBデバイスならどんなものでも利用可能です。</p>

<p>またWeb USB以外にも、WebBluetooth APIやWebNFC APIなどWeb技術を使ってハードウェアにアクセスする方法は増えています。ぜひこれからの開発に利用してみてください！</p>
]]></content:encoded>
			</item>
		<item>
		<title>「テクニックは語りません」竹洞先生に聞く、本気のWebパフォーマンス道</title>
		<link>/shumpei-shiraishi/24420/</link>
		<pubDate>Thu, 09 Nov 2017 01:00:54 +0000</pubDate>
		<dc:creator><![CDATA[白石 俊平]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[システム開発]]></category>
		<category><![CDATA[Webパフォーマンス]]></category>

		<guid isPermaLink="false">/?p=24420</guid>
		<description><![CDATA[連載： HTML5 Conference 2017特集 (14)こんにちは、編集長の白石です。 この記事は、9月24日に開催されたHTML5 Conference 2017に登壇したエキスパートに、お話されたセッションの...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/html5-conf2017/" class="series-457" title="HTML5 Conference 2017特集" data-wpel-link="internal">HTML5 Conference 2017特集</a> (14)</div><p>こんにちは、編集長の白石です。</p>

<p>この記事は、9月24日に開催された<a href="http://events.html5j.org/conference/2017/9/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">HTML5 Conference 2017</a>に登壇したエキスパートに、お話されたセッションのトピックを中心に語っていただこうとういものです。セッションの内容をより深く理解する手助けになるだけでなく、本記事単体でも面白く読んでいただけることを目指しています。</p>

<p>今回お話を伺ったのは、html5j パフォーマンス部を運営していらっしゃる竹洞 陽一郎さんです。</p>

<p><img src="/wp-content/uploads/2017/10/42A5419.jpg" alt="" width="640" height="415" class="alignnone size-full wp-image-24619" srcset="/wp-content/uploads/2017/10/42A5419.jpg 640w, /wp-content/uploads/2017/10/42A5419-300x195.jpg 300w, /wp-content/uploads/2017/10/42A5419-207x134.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /><span style="font-size: 80%;"><strong>▲HTML5 Conference 2017セッション風景 （写真提供：html5j　撮影：刑部友康）</strong></span></p>

<p>竹洞さんのセッション「テクニックではなく、今、本気で取り組むべきWebパフォーマンス」に関するスライド資料は、<a href="https://speakerdeck.com/takehora/tekunitukudehanaku-jin-ben-qi-dequ-rizu-mubekiwebpahuomansu" rel="noopener follow external noreferrer" target="_blank" data-wpel-link="external">こちら</a>で公開されています。</p>

<h2>民法（債権法）が改正されて、何が変わる？</h2>

<p><b class="speaker siraisi">白石:</b> 民法（債権法）が改正された、ということに注目なさってるそうですね。</p>

<p><b class="speaker takehora">竹洞:</b> はい、民法の大規模な改正法案が今年5月に成立しました。3年以内に施行されることになっており、備えが必要です。様々な改正項目がありますが、中でも品質の担保を行う義務が明文化されたことで、ソフトウェア業界にも大きな影響が及ぶものと考えています。</p>

<p><b class="speaker siraisi">白石:</b> 具体的にはどういうことなのでしょうか？</p>

<p><b class="speaker takehora">竹洞:</b> <strong>「瑕疵担保」っていう概念がなくなる</strong>んです（参考: <a href="http://itpro.nikkeibp.co.jp/atcl/news/17/052601508/?rt=nocnt" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">改正民法が成立、「瑕疵担保責任」などシステム開発契約に影響大 (ITpro)</a>。</p>

<p>今までは「瑕疵担保」という概念があったおかげで、とりあえずは品質を担保しない状態で納品を行い、その後の瑕疵期間で問題を修正していく…というのが一般的に行われていました。ですが今後は、納品時に一定の品質を保証することが開発側に求められるようになります。</p>

<p><b class="speaker siraisi">白石:</b> そのことが、どういう影響をおよぼすと考えられますか？</p>

<p><b class="speaker takehora">竹洞:</b> 私としては、ソフトウェア品質が全般的に向上することで、市場が健全化すると考えています。</p>

<p><strong>品質への理解が低い市場は、必ずと言っていいほど衰退する</strong>んです。
消費者が品質の善し悪しが判断できない状態だと、価格が一番の判断材料になります。
そうなると結局、品質を犠牲にした価格競争にならざるを得ない。</p>

<p><b class="speaker siraisi">白石:</b> 「安かろう悪かろう」が当たり前になってしまうわけですね。</p>

<p><b class="speaker takehora">竹洞:</b> そう。そういうスパイラルに陥らないためには、品質への意識を高く保つ必要があるんです。</p>

<p>例として適切かはわかりませんが、たとえば<strong>麻薬の売人って、品質にものすごく気を使う</strong>んです。 質の悪い麻薬が出回るようになると、価格に対する期待と同程度の「ハイ」の状態を得られず、その結果、価格の下落を招き、結局市場が衰退してしまうからです。こうした現象を、アメリカの中古車市場の分析から「情報の非対称性」として研究したジョージ・アカロフ博士は、2001年にノーベル経済学賞を受賞しています。</p>

<p><img src="/wp-content/uploads/2017/10/DSC05329.jpg" alt="" width="640" height="427" class="alignnone size-full wp-image-24621" srcset="/wp-content/uploads/2017/10/DSC05329.jpg 640w, /wp-content/uploads/2017/10/DSC05329-300x200.jpg 300w, /wp-content/uploads/2017/10/DSC05329-207x138.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<h2>「品質保証」がウェブ業界を変える</h2>

<p><b class="speaker siraisi">白石:</b> しかし、品質保証が義務付けられるとなると、開発のコストが上がるということになりませんか？</p>

<p><b class="speaker takehora">竹洞:</b> それはあり得ます。そのことが、受託開発のビジネスなどをより難しくしてしまうことも考えられます。</p>

<p>例えばウェブ制作会社は、一般的には納品後に入金が入るという仕組みになっていますよね。
だから、まずは品質がそこそこの状態で納品してしまう…ということも起きるわけです。 パフォーマンスはその悪い例で、まずはチューニングしていない状態で納品する。すると、後でパフォーマンス・チューニングの依頼が来てまた売上につながる…なんて事情も実際にはあるわけです。</p>

<p>こうしたこれまでの商慣行が崩れてしまう可能性はありますね。 品質保証が義務付けられるせいで、納品までにより時間がかかるようになるとすると、入金が遅くなるということに繋がる。しかし、民法債権法改正では、部分単位やステージ毎の請負金額の要求ができるようになっています。</p>

<p><b class="speaker siraisi">白石:</b> それだけ聞くと、受託開発や制作を行っている企業にとっては、ただただ厳しくなるようにも聞こえますね。 そもそも、「品質を保証して納品」ってどういうことなんでしょう？ 完璧なソフトウェアを作らねばならない…なんてそもそも無理だとも思うのですが。</p>

<p><b class="speaker takehora">竹洞:</b> その点については安心していいと思います。 「品質を保証する」というのは、「完璧な製品」を意味しているわけじゃないんです。 テスト項目について顧客と合意し、その結果を提出すればいい。実は、ソフトウェア品質には、<a href="http://www.itmedia.co.jp/im/articles/1111/07/news153.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">V&amp;V</a>といって、Verification(検証)とValidation(妥当性確認)という二つの概念があります。</p>

<p>検証(Verification)とは、仕様・設計・計画などの要求事項を満たしているかどうかの確認です。妥当性確認(Validation)とは、機能や性能が本来意図された用途や目的に適っているか、実用上の有効性があるかの確認です。Webパフォーマンスは、品質においては、妥当性確認にあたります。</p>

<p>従来、ソフトウェア開発における「品質」、特に受託開発においては、検証確認が主体でした。もちろん、応答速度の遅延などで使いものにならないという妥当性確認もあったものの、それはハードウェア性能であったり、データベース設計の問題であったりと、「表示」そのもののロジックに原因はあまりなかったのです。</p>

<p>要求仕様の実現という意味での検証については、仰るとおり「完璧な製品」というのは、ほぼ存在し得ない。それは、ソフトウェアが、論理記述であって、物理法則の縛りがなく、かつ、連続性の保証がないためです。</p>

<p>連続性の保証とは、物理法則であれば、100Kgの重さまで耐えられるテーブルであれば、当然ながら、80Kgや10Kgなど、100Kg以下の重量に耐えられることです。しかし、ソフトウェアは二値論理がベースであるために、100という値で大丈夫であっても、80や10という値で大丈夫であるという保証がない世界です。</p>

<p>2002年に亡くなられた、オランダの著名な計算機科学者で、構造化プログラミングの提唱者でチューリング賞を受賞しているエドガー・ダイクストラ博士が「テストは誤謬を見つけることはできるが、それがないことを証明することはできない」と指摘しています。</p>

<p>ですから、バグや欠陥がないことを保証するというのは無理なんです。</p>

<p><b class="speaker siraisi">白石:</b> なるほど、それなら少し安心です。バグや欠陥のないソフトウェアなんて不可能ですし。</p>

<p><b class="speaker takehora">竹洞:</b> 品質についても顧客との合意内容に盛り込む必要が生じる、ってことですよね。 そうした合意があるのとないのとでは、品質に対する意識が全然違ってきます。品質については、検証として従来もやってきたことです。ところが、WebがソフトウェアのUIの主体となることによって、今まで問題にならなかった「表示」に関するロジックが突如、問題となり始めた。突如といっても、もう20年ぐらいになるわけですが…</p>

<p>その部分は、検証ではなくて、妥当性確認なんですが、妥当性確認のテストのノウハウが日本では普及していなかった。今、そこが問われているわけです。</p>

<p><img src="/wp-content/uploads/2017/10/DSC05348.jpg" alt="" width="640" height="411" class="alignnone size-full wp-image-24622" srcset="/wp-content/uploads/2017/10/DSC05348.jpg 640w, /wp-content/uploads/2017/10/DSC05348-300x193.jpg 300w, /wp-content/uploads/2017/10/DSC05348-207x133.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><b class="speaker siraisi">白石:</b> なるほど。「完璧な製品を作る」ことが品質保証なのではなく、「妥当性品質に対してどこまで保証するかを明確にする」ということなんですね。</p>

<p><b class="speaker takehora">竹洞:</b> そうです。そうして、妥当性品質についての期待値を高く保つことは、Webに関する業界として必要なことだと思いますよ。</p>

<p>例えば日本の住宅市場は、品質保証がうまくいっていない例だと思うんです。 日本の住宅って、非常に寿命が短いじゃないですか。その理由は様々ですが、一つに中古住宅に対する品質の期待値が低いことがあると思っています。 品質保証がない空き家を買うくらいなら、新築のほうがいいって心理です。</p>

<p><b class="speaker siraisi">白石:</b> 確かにそういう一面はある気がしますね。ぼくは安さに釣られて中古住宅を買ったクチですが(笑)、一生住めるなんて少しも期待してませんし。</p>

<p><b class="speaker takehora">竹洞:</b> それって、結局その家はいつか捨てることになるってことで、財の蓄積が進んでいないとも言えると思うんです。 社会的に見ると、将来世代に引き継ぐ財が形成されていないとも言える。財の蓄積が期待できないと、そこの投資は進まない。お金が集まってこないのです。</p>

<p>ウェブのように技術がどんどん進歩していく世界に財の蓄積は有り得るのか？システム構築費用は5年で償却されるのであれば、5年持てばいいじゃないか？という考えられるのは、仰るとおりです。</p>

<p>しかし、プレゼンテーションとしてのUIデザインと、データとしてのコンテンツやユーザのデータは分けて考えるべきで、だからこそ、HTMLとCSS、JavaScriptで役割分担をしているわけじゃないですか。システムの永続性というものを考慮してWebサイトの設計を行うことは非常に重要なのです。</p>

<p>減価償却期間の5年も持たない、3年程度で捨てざるを得ないとなれば、企業財務的にはそこはできるだけ安く済ませるべきなのです。しかし、品質が保証されて、減価償却の5年を超えて使えるとなると、将来価値が上がる。企業財務的にはおいしいお話なのです。そこに気付いてほしい。メンテナンス費用は当然発生するでしょうけど、新規で作るより安いですし、何より「継承」できることが大きなメリットなんです。</p>

<p>UIデザインや技術力だけで勝負しているWeb制作会社さんは、その点に、早く気づかれた方が良いと思います。お金を握っている経営者や財務担当者は、別のロジックで判断しているわけですから。</p>

<p>ですから、ウェブサイトも、いつか捨てるものとなれば、そこに予算を掛けようとは思わない。品質が保証されないのであれば、なおさらのことです。</p>

<p>「お客様からあまり予算をいただけない」と嘆くことがあるかと思いますが、その背景には、品質が保証されていないので修正するより作り直した方がいいと考えられていること、いつかWebサイトは捨てて新しく作るものと考えられている背景は認識しておくべきだと思います。</p>

<h2>ウェブサイトの品質を決める3つの要素</h2>

<p><b class="speaker siraisi">白石:</b> では具体的に、ウェブサイトにおける品質を保証するというのは、何をすればいいんでしょうか？</p>

<p><b class="speaker takehora">竹洞:</b> ウェブサイトの品質は主に3つの要素から成っていると言っていいでしょう。</p>

<p>一つは<strong>アクセシビリティ</strong>。
一つは<strong>セキュリティ</strong>。
最後が<strong>パフォーマンス</strong>です。</p>

<div id="attachment_24422" style="width: 650px" class="wp-caption aligncenter"><img src="/wp-content/uploads/2017/10/ab193805fd71ab248f659082cef24bb5-640x480.png" alt="Webサイトの三大品質" width="640" height="480" class="size-large wp-image-24422" srcset="/wp-content/uploads/2017/10/ab193805fd71ab248f659082cef24bb5-640x480.png 640w, /wp-content/uploads/2017/10/ab193805fd71ab248f659082cef24bb5-300x225.png 300w, /wp-content/uploads/2017/10/ab193805fd71ab248f659082cef24bb5-768x576.png 768w, /wp-content/uploads/2017/10/ab193805fd71ab248f659082cef24bb5-207x155.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">Webサイトの三大品質</p></div>

<p>これらはそれぞれJISで規定されてもいる重要な指標です。これらをしっかり担保していく体制づくり、それがウェブサイトの品質保証に繋がります。</p>

<p><b class="speaker siraisi">白石:</b> ウェブサイト制作にも、これらを担保するワークフローを確立していくべきということですね。</p>

<p><b class="speaker takehora">竹洞:</b> そうです。そしてこれらは、運用と一体になって改善していくべきものでもありますので、DevOpsの観点から考えるのも重要です。</p>

<p>ただ一つ不思議なのが、日本でDevOpsに関して述べている文献や書籍って、ほとんどの場合品質保証のことが抜けてしまっているんですよね。
品質に対する意識が高まらない原因は、こういうところにもあると思います。</p>

<div id="attachment_24423" style="width: 650px" class="wp-caption aligncenter"><img src="/wp-content/uploads/2017/10/depops-640x480.png" alt="DevOps" width="640" height="480" class="size-large wp-image-24423" srcset="/wp-content/uploads/2017/10/depops-640x480.png 640w, /wp-content/uploads/2017/10/depops-300x225.png 300w, /wp-content/uploads/2017/10/depops-207x155.png 207w, /wp-content/uploads/2017/10/depops.png 720w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">DevOps</p></div>

<h2>ウェブサイトの品質を高めるための心構え</h2>

<p><b class="speaker siraisi">白石:</b> 品質を向上させるためのコストが低く見積もられがちというところもあるんでしょうか。</p>

<p><b class="speaker takehora">竹洞:</b> というよりは、そのコストが認識されていないというのが正しい気がします。 「品質、費用、期間の3要素を同時に満たすことはできず、トレードオフの関係にある」といった、プロジェクトマネジメントやソフトウェア開発見積りの基本もあまり浸透していない感覚がある。</p>

<p><b class="speaker siraisi">白石:</b> なるほど。当たり前の話ですが、品質を高めようとすれば、時間的、金銭的なコストを支払う必要があるということですね。</p>

<p><b class="speaker takehora">竹洞:</b> はい。そして品質保証が当たり前になれば、品質保証のためのコストがかかるのも当たり前になる。今は、その当たり前のコストを払っていないだけとも言えるのです。</p>

<p><b class="speaker siraisi">白石:</b> では、そうした品質保証、特にパフォーマンスについて、状況を改善していくにはどんな知識が必要になるんでしょう？</p>

<p><b class="speaker takehora">竹洞:</b> そうですね、小手先のテクニックはたくさんありますし、いろんなところで語られてもいますので、もう少し根源的なところから考えると、結局「基礎」と「長期的な視野」が重要になると思うんです。</p>

<p>基礎というのは、コンピューターやネットワークに関する基本的な知識。 長期的な視野と言うのは、数年後にインターネットがどうなっているか、といった話です。</p>

<p><b class="speaker siraisi">白石:</b> なるほど。</p>

<p><b class="speaker takehora">竹洞:</b> 例えば、パフォーマンスに関する話を突き詰めていくと、意外なほどハードウェアに関する知識って大事なんです。 パフォーマンスって、最終的には絶対にハードウェアに依存するわけですからね。</p>

<p>例えば、とある大規模サイトで遅延が発生していたんですが、その原因を追求するのすごく大変だったんです。 アプリケーションをいくら調べても、データベースのクエリをいくら見直しても、ネットワークの状態を見ても、原因がわからなかった。</p>

<p><b class="speaker siraisi">白石:</b> 結局、どんな原因だったんですか？</p>

<p><b class="speaker takehora">竹洞:</b> そのサーバはVMWareで仮想化されていて、サーバ負荷に応じてCPUリソースが動的に割り当てられるようになっていました。ただ、あらかじめ割り当てられているCPUリソースが足りなかったせいで、CPUの動的割り当てが頻繁に発生してしまっていたんです。 その割り当てが行われる際に、サーバの処理が遅延してしまっていたんですね。</p>

<p><b class="speaker siraisi">白石:</b> それは深い原因ですね…</p>

<p><b class="speaker takehora">竹洞:</b> ここまで奥深くに原因がある場合って、ハードウェアを含めたアーキテクチャ全般の知識が必要になります。 だから結局、コンピューター全般の知識って必要だなと。だから私の会社では、入社したら最初の一歩として、まずPCを自作してもらうようにしています(笑)。</p>

<h2>全てを変える、5Gネットワーク</h2>

<p><b class="speaker siraisi">白石:</b> 数年後にインターネットがどうなっているか、というお話も聞かせていただけますか？</p>

<p><b class="speaker takehora">竹洞:</b> はい、具体的には5Gネットワークの話になりますね。5Gはアプリケーションの作り方を含め、全てを変える可能性がある技術だと思っています。</p>

<p><b class="speaker siraisi">白石:</b> 5Gネットワークって全然知らないのですが、どんな感じなんでしょう？</p>

<p><b class="speaker takehora">竹洞:</b> 大きく3つのトピックがあると考えています。</p>

<p>一つは<strong>ネットワークスライス</strong>。インターネットを「輪切り」にするイメージで、用途に応じて別々のネットワークを提供していくようになります。</p>

<p>電波には周波数によって特性があり、サービスの特性に応じて周波数を割り当てて異なるネットワークを構成できるので、ネットワーク全体の利用効率が大きく向上すると考えられています。</p>

<div id="attachment_24424" style="width: 650px" class="wp-caption aligncenter"><img src="/wp-content/uploads/2017/10/a2394912a431f48b924b7fd9decf0e62-640x480.png" alt="ネットワークスライス" width="640" height="480" class="size-large wp-image-24424" srcset="/wp-content/uploads/2017/10/a2394912a431f48b924b7fd9decf0e62.png 640w, /wp-content/uploads/2017/10/a2394912a431f48b924b7fd9decf0e62-300x225.png 300w, /wp-content/uploads/2017/10/a2394912a431f48b924b7fd9decf0e62-207x155.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">ネットワークスライス</p></div>

<p>次に<strong>指向性アンテナ</strong>です。今までは、基地局といういわば「傘」を中心として、そこから広がるように無線ネットワークが構築されていました。</p>

<p>しかしこれからは、パネル型のアンテナがビルの壁面に貼られるようになり、そこから端末と直接「ビーム」をやり取りするように通信を行います。通信の受信強度が高まるだけでなく、他の電波との干渉も減らせます。</p>

<div id="attachment_24426" style="width: 650px" class="wp-caption aligncenter"><img src="/wp-content/uploads/2017/10/dfdead9390dbb2a8a72a6eba14a82677-640x480.png" alt="指向性アンテナ" width="640" height="480" class="size-large wp-image-24426" srcset="/wp-content/uploads/2017/10/dfdead9390dbb2a8a72a6eba14a82677.png 640w, /wp-content/uploads/2017/10/dfdead9390dbb2a8a72a6eba14a82677-300x225.png 300w, /wp-content/uploads/2017/10/dfdead9390dbb2a8a72a6eba14a82677-207x155.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">指向性アンテナ</p></div>

<p>最後に<strong>モバイル・エッジ・コンピューティング</strong>です。これは、4Gですと、地域の基地局をまとめているRNC(Radio Network Controller)配下に、仮想サーバー（エッジサーバー）を設置できるようになるのです。 今まで携帯の会社はコアネットワークを公開していなかったので、これは大きな変化です。</p>

<div id="attachment_24425" style="width: 650px" class="wp-caption aligncenter"><img src="/wp-content/uploads/2017/10/8b6b5080377333396bc358c212e7653e-640x480.png" alt="モバイルエッジコンピューティング" width="640" height="480" class="size-large wp-image-24425" srcset="/wp-content/uploads/2017/10/8b6b5080377333396bc358c212e7653e.png 640w, /wp-content/uploads/2017/10/8b6b5080377333396bc358c212e7653e-300x225.png 300w, /wp-content/uploads/2017/10/8b6b5080377333396bc358c212e7653e-207x155.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">モバイルエッジコンピューティング</p></div>

<p>これは分散コンピューティングの新たな可能性を示しているといえます。インターネットより手前でトラフィックを捌けるわけですから、サーバーの応答性も大きく向上します。</p>

<p><b class="speaker siraisi">白石:</b> へえ、知りませんでした！世界中のエッジサーバー上に、静的リソースのキャッシュを置けたりしたら、すごく速くなりそうですね。</p>

<p><b class="speaker takehora">竹洞:</b> それだけではありません。エッジサーバーで可能な限り処理を行い、必要な処理だけインターネット上のサーバーに送るようにすることもできます。アプリケーションの処理を、エッジサーバーとインターネット上のサーバーで分担するというわけです。</p>

<p>もしくは、全てエッジサーバー上で処理を行うような、非インターネットのローカルなサービスを行うことも可能です。</p>

<p><b class="speaker siraisi">白石:</b> そうなると、アプリケーションの作り方も大きく変わってきそうですね。夢が拡がりますね…。5Gネットワークって、具体的にはいつ頃普及が見込まれているのでしょうか？</p>

<p><b class="speaker takehora">竹洞:</b> 2020年の東京オリンピックまでには使えるようになるだろうと言われています。</p>

<p>10月12日に、NTTドコモ、富士通、富士通研究所がモバイル・エッジ・コンピューティングを使った高画質動画配信や映像解析を活用した人物検知システムの実証実験を行って成功した旨の<a href="http://pr.fujitsu.com/jp/news/2017/10/12-1.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">プレスリリース</a>を発表してています。</p>

<p>また10月13日には三菱商事が、この分野のリーディングカンパニーである<a href="https://www.jig-saw.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">JIG-SAW</a>と、モバイル・エッジ・コンピューティングの実証実験成功の<a href="https://news.biglobe.ne.jp/economy/1013/dre_171013_4304155723.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">プレスリリース</a>を発表しています。</p>

<p><b class="speaker siraisi">白石:</b> ワクワクしますね。本日は民法から5Gネットワークまで、幅広いお話を聞かせていただき、ありがとうございました！</p>
]]></content:encoded>
		
		<series:name><![CDATA[HTML5 Conference 2017特集]]></series:name>
	</item>
		<item>
		<title>WebGLの現状と未来を、Grimoire.jsを生んだスーパークリエータに聞いてきた！</title>
		<link>/shumpei-shiraishi/24589/</link>
		<pubDate>Thu, 02 Nov 2017 01:00:22 +0000</pubDate>
		<dc:creator><![CDATA[白石 俊平]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[デザイン]]></category>
		<category><![CDATA[Grimoire.js]]></category>
		<category><![CDATA[WebGL]]></category>

		<guid isPermaLink="false">/?p=24589</guid>
		<description><![CDATA[連載： HTML5 Conference 2017特集 (12)こんにちは、編集長の白石です。 この記事は、9月24日に開催されたHTML5 Conference 2017に登壇したエキスパートに、お話されたセッションの...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/html5-conf2017/" class="series-457" title="HTML5 Conference 2017特集" data-wpel-link="internal">HTML5 Conference 2017特集</a> (12)</div><p>こんにちは、編集長の白石です。</p>

<p>この記事は、9月24日に開催された<a href="http://events.html5j.org/conference/2017/9/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">HTML5 Conference 2017</a>に登壇したエキスパートに、お話されたセッションのトピックを中心に語っていただこうとういものです。セッションの内容をより深く理解する手助けになるだけでなく、本記事単体でも面白く読んでいただけることを目指しています。</p>

<p>今回お話を伺ったのは、東京理科大学4年の石井翔さんです。</p>

<p><img src="/wp-content/uploads/2017/10/42A5128.jpg" alt="" width="640" height="412" class="alignnone size-full wp-image-24605" srcset="/wp-content/uploads/2017/10/42A5128.jpg 640w, /wp-content/uploads/2017/10/42A5128-300x193.jpg 300w, /wp-content/uploads/2017/10/42A5128-207x133.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>石井さんのセッション「WebGLの今とこれから ~今のWeb開発で使うからこそ知っておきたい周辺技術~」に関するスライド資料は、こちらで公開されています。</p>

<p><a href="http://html5.grimoire.gl/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">スライド資料</a>
（注: 重いのとモバイルから見えないのはご容赦ください by 石井翔さん）</p>

<h2>WebGLの現状</h2>

<p><b class="speaker siraisi">白石:</b> 本日は取材をお受けいただいてありがとうございます！簡単に自己紹介をお願いします。</p>

<p><b class="speaker isii">石井:</b> 東京理科大学4年生の石井 翔です。昨年、私が進めている<a href="https://grimoire.gl/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Grimoire.js</a>（注: モバイルからだと多少レイアウトが崩れます by 石井翔さん）というプロジェクトが<a href="https://www.ipa.go.jp/jinzai/mitou/2016/20170530.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">未踏IT人材発掘・育成事業に採択され</a>、スーパークリエータに認定されました。</p>

<p><b class="speaker siraisi">白石:</b> Grimoire.jsはWebGLのライブラリですね。Grimoire.jsについてもあとでお聞かせ願いたいのですが、まずはWebGLの概要や現状についてお話いただけますか？</p>

<p><b class="speaker isii">石井:</b> WebGLは、一言で言えばWeb上で3Dコンテンツを扱うための技術です。2010年に仕様が策定されており、既に多くのブラウザで実装されている技術です。ブラウザ上でどの技術が使えるかを測定する<a href="https://caniuse.com/#feat=webgl" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Can I Use</a>での結果を見ても、92%以上のブラウザがサポートしていて、広く使える状態にあると言っていいでしょう。</p>

<p>ただこれは、WebGL 1.0の話です。<a href="https://caniuse.com/#feat=webgl2" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">WebGL 2.0はまだまだ</a>ですね。ChromeとFirefoxだけが対応しているという状態で、特にiOSで使えないのが厳しいです。「ブラウザを限定すれば使える」という状態です。</p>

<p><b class="speaker siraisi">白石:</b> WebGL 1.0と2.0って何が違うんですか？…ぼく、3Dプログラミングが全然わかってないので、理解できるか自信がないのですが(笑)</p>

<p><b class="speaker isii">石井:</b> 浮動小数点テクスチャなどがWebGL 2.0の主な機能ですが、3Dプログラミングの知識がない人に向けて話すのはちょっと難しいですね(笑)
とりあえず、ライブラリ作者なら知っておくべきですが、ライブラリのユーザーはそれほど気にする必要はないかと思います。
ライブラリ作者も、WebGL 2.0が使えない環境では1.0にフォールバックするように実装していることが多いでしょうし。</p>

<p><small>
（筆者注: WebGL 2.0の強化点については<a href="https://qiita.com/emadurandal/items/4c7bd2a26ef2d732d734" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Qiitaで良い記事を見つけました</a>。ぼくにはちんぷんかんぷんですが…）
</small></p>

<p><b class="speaker siraisi">白石:</b> なるほど、あまり気にしなくていいと(笑) 安心しました。</p>

<p><b class="speaker isii">石井:</b> 3Dをご存じない方にとって大事なのは、<strong>そもそもWebGLとはGPUを扱うための技術だ</strong>ということをしっかり理解しておくことです。</p>

<p>CPUは、CPUは複雑な処理を逐次的に処理することを得意としています。CPUの場合はコアの数が4とか8とかに限られていることが普通です。</p>

<p>一方GPUの場合は、「異なるデータに対して同じ処理を施す」のを並列で実行するのに特化しています。なのでGPUは、コアの数が1,000を超えることも普通です。
こうした特徴を持つGPUだからこそ、大量の頂点を移動する処理など、3Dプログラミングに必要とされる「単純な処理の並列実行」に向いているんです。</p>

<p><b class="speaker siraisi">白石:</b> こうした特徴は、最近だと機械学習の分野とかにも活かされているんですよね。単純なベクトル計算とかが多いから。</p>

<p><b class="speaker isii">石井:</b> そうです。で、WebGLってそもそもOpenGL（※）と同じなので、CGの取り扱いに関しては共通している部分がほとんどです。<strong>ただ、置かれている環境は、OpenGLネイティブのゲームやアプリとは随分違う</strong>。</p>

<p>一番違う点は、WebGLは必要とされるリソースが全部Web上にあって、ダウンロードが必要という点です。モデルデータの読み込みに時間がかかるんですよね。</p>

<p>だから今まではゲームなど、「読み込みに時間がかかりそうだ」とユーザーも了解しているコンテンツが多かったんです。でも、本来使うデータをしっかり選べば短いロード時間で使えるものも多いんですよ。シェーダーアートとか。</p>

<p><small>
※OpenGL（オープンジーエル、Open Graphics Library）は、クロノス・グループ (英: Khronos Group) が策定している、グラフィックスハードウェア向けの2次元/3次元コンピュータグラフィックスAPIである（<a href="https://ja.wikipedia.org/wiki/OpenGL" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Wikipediaより引用</a>）
</small></p>

<p><b class="speaker siraisi">白石:</b> 確かに、WebGLでできたゲームとか、読み込みに数分待たされるものもありましたね。</p>

<p><b class="speaker isii">石井:</b> はい。モデルデータが大きいと、それだけダウンロードやデータ読み込みに時間がかかってしまう。なので、<strong>そうしたWebGLの問題を解決すべく、CGの世界にも進化が起きようとしている</strong>んです。</p>

<p><img src="/wp-content/uploads/2017/10/42A5125.jpg" alt="" width="640" height="417" class="alignnone size-full wp-image-24608" srcset="/wp-content/uploads/2017/10/42A5125.jpg 640w, /wp-content/uploads/2017/10/42A5125-300x195.jpg 300w, /wp-content/uploads/2017/10/42A5125-207x135.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<h2>ランタイム向け3Dデータフォーマット「glTF」</h2>

<p><b class="speaker siraisi">白石:</b> 具体的にはどのような進化ですか？</p>

<p><b class="speaker isii">石井:</b> 一つは<strong><a href="https://www.khronos.org/gltf" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">glTF</a> (GL Transmission Format) と言って、汎用的な3Dアセットフォーマット</strong>です。ツールに依存しない軽量フォーマットとして、Khronosが普及を進めています。</p>

<div id="attachment_24632" style="width: 650px" class="wp-caption aligncenter"><img src="/wp-content/uploads/2017/10/e1ac15f7811659bca0d029023946090c-640x334.png" alt="glTF" width="640" height="334" class="size-large wp-image-24632" srcset="/wp-content/uploads/2017/10/e1ac15f7811659bca0d029023946090c.png 640w, /wp-content/uploads/2017/10/e1ac15f7811659bca0d029023946090c-300x157.png 300w, /wp-content/uploads/2017/10/e1ac15f7811659bca0d029023946090c-207x108.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">glTF</p></div>

<p><b class="speaker siraisi">白石:</b> ツールに依存しない、というのはどういう意味ですか？</p>

<p><b class="speaker isii">石井:</b> 以前WebGL上でモデルファイルを扱う際には、MayaやBlenderといったツールのファイルをそのまま読み込んで利用することが一般的でした。これは言わば、<strong>「Photoshopのpsdファイルはあるけど、jpgやpngなどの汎用的な画像フォーマットがない」という状況</strong>です。</p>

<p><b class="speaker siraisi">白石:</b> そんな状況だったんですね…知りませんでした。ゲームやアプリとしてひとまとめにパッケージングしてしまうから、汎用フォーマットが必要とされなかったんでしょうか。</p>

<p><b class="speaker isii">石井:</b> 概ねそういうところです。そういう状況を変えようと、<a href="https://ja.wikipedia.org/wiki/COLLADA" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">COLLADA</a>という汎用フォーマットがKhronosによって提案され、一定程度普及はしています。</p>

<p>ただ、COLLADAファイルはCG編集ツール間でデータをやり取りするためのフォーマットとして設計されているため、WebGLアプリケーションが読み込んで利用するには、編集用のパラメーターなど不要な部分も多いんです。また、XML形式だというのも、ファイルサイズや解析速度の点で不利になります。</p>

<p>glTFは、COLLADAファイルから編集用のパラメータを取り除いて、JSON形式にしたものと言ってほぼ差し支えありません。</p>

<p><b class="speaker siraisi">白石:</b> なるほど。ただ、そういうフォーマットって、普及させるのがなかなか大変な気もしますが、どうなんでしょう？</p>

<p><b class="speaker isii">石井:</b> glTFは既に様々なライブラリにもサポートされていますし、普及は中々順調と言えると思います（参考: <a href="https://github.com/cx20/gltf-test" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">glTFのライブラリサポート状況</a>）。</p>

<p><strong>glTFの面白いところは、大手ベンダーの採用意欲が高い</strong>というところです。MicrosoftやAutodeskという大手ベンダーが乗っかってきているんですよ。
Khronos自身WebGLの仕様策定元なので、この分野で発言力が強いこともあります。また、最近では<a href="https://www.apple.com/jp/apple-watch-series-3/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Apple Watchのページ</a>でglTFが使われてたりもします。</p>

<p><b class="speaker siraisi">白石:</b> Apple Watchの公式サイトでもですか！それはかなりの人がアクセスしたでしょうね。確かに、これ単なる画像じゃない。スクロールと共に水滴が別々の動きをしてる…！（重いけど）</p>

<div id="attachment_24625" style="width: 650px" class="wp-caption aligncenter"><img src="/wp-content/uploads/2017/10/bf93ab1915cccd50fb572e6bd170ab1a-640x395.png" alt="Apple Watch Series 3のサイト" width="640" height="395" class="size-large wp-image-24625" srcset="/wp-content/uploads/2017/10/bf93ab1915cccd50fb572e6bd170ab1a.png 640w, /wp-content/uploads/2017/10/bf93ab1915cccd50fb572e6bd170ab1a-300x185.png 300w, /wp-content/uploads/2017/10/bf93ab1915cccd50fb572e6bd170ab1a-207x128.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">Apple Watch Series 3のサイト</p></div>

<p><b class="speaker isii">石井:</b> glTFは「オーディオにおけるMP3, ビデオにおけるH.264、画像におけるJPEG」といったように、「3DといえばglTF」となることを目指しているとのことで、普及にかけるKhronosの意気込みも並々ならぬものがあります。
<img src="https://www.khronos.org/assets/uploads/apis/2016-gltf-jpeg-of-3d.jpg" alt="" /></p>

<h2>頂点データ専用の圧縮形式「draco」</h2>

<p><b class="speaker isii">石井:</b> もう一つ注目の技術としては、Googleがオープンソースで開発している<a href="https://github.com/google/draco" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">draco</a>という圧縮形式です。頂点データを効率よく圧縮する技術で、元々の頂点データのサイズに比べて4倍から16倍の圧縮率を誇ります。</p>

<p><img src="/wp-content/uploads/2017/10/ea3f6e4f266b99b2233c19fe0d906450-640x338.png" alt="" width="640" height="338" class="aligncenter size-large wp-image-24626" srcset="/wp-content/uploads/2017/10/ea3f6e4f266b99b2233c19fe0d906450.png 640w, /wp-content/uploads/2017/10/ea3f6e4f266b99b2233c19fe0d906450-300x158.png 300w, /wp-content/uploads/2017/10/ea3f6e4f266b99b2233c19fe0d906450-207x109.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><b class="speaker siraisi">白石:</b> 先ほどのglTFにしか使えないんですか？</p>

<p><b class="speaker isii">石井:</b> いえ、汎用的なポリゴンデータ形式（.ply）に対応しているので、元のファイルフォーマットは選びません。</p>

<p><b class="speaker siraisi">白石:</b> ブラウザによる対応も必要なんですか？</p>

<p><b class="speaker isii">石井:</b> いえ、ブラウザがネイティブ対応するというものでもないんです。<strong>dracoによって圧縮されたポリゴンデータは、JavaScriptでデコードすることができます</strong>。</p>

<p><b class="speaker siraisi">白石:</b> なるほど、アプリケーションが自前で圧縮データを展開するんですね。でもそれだと、デコード処理にかかる時間がちょっと心配です。</p>

<p><b class="speaker isii">石井:</b> WebAssemblyでできたデコーダーもあるし、Web Workersで展開すればUI処理を阻害することもないので、そこはあまり問題ないと思いますよ。使うブラウザを選ぶということもありませんし、Three.jsのようなライブラリに任せてしまえば、アプリケーションはデコードについて意識する必要もありません。</p>

<p><b class="speaker siraisi">白石:</b> ほかには、Webだと画像のサイズを結構気にしたりしますが、CGの世界ではどうなんでしょう？</p>

<p><b class="speaker isii">石井:</b> CGだと、テクスチャ画像のサイズを削減するという話になりますね。ただ、単に画像のファイルサイズを小さくするだけでは片手落ちなんです。
いくら元画像のファイルサイズを小さくしても、GPUに乗るときにはフルサイズにデコードされてしまうので、メモリ使用量などにすごく影響するんですね。</p>

<p>なので、GPUが直接扱えるテクスチャ圧縮形式というものがありまして、それらを利用すると、GPU上でも圧縮した状態で画像を扱うことができます。DirectXだとS3TCという形式、iOSだとPowerVR Texture Compression (PVRTC) というように、ベンダーごとに異なってくるんですが。</p>

<p><b class="speaker siraisi">白石:</b> ベンダーごとに異なるんだと、取り扱いが面倒ですね。</p>

<p><b class="speaker isii">石井:</b> はい、なのでこういうフォーマット変換はWebpackなどで自動化されるべきだと思います。このように、今まではエンジンが自動的に行なってきたことも、WebGLの場合はプログラマーが自分で意識しなくてはなりません。</p>

<p><b class="speaker siraisi">白石:</b> まとめると、3DをWeb上で行うためにはいろいろな課題があって、それが徐々に解決されつつあるということですね。汎用モデルフォーマットが普及しつつあり、頂点データの圧縮ツールも登場した。そして、テクスチャ圧縮も自動化されるだろうと。</p>

<p><b class="speaker isii">石井:</b> そうです。そもそもWebは、多様なデバイスがネットワークで繋がれていることが前提です。そういうユビキタスな環境で、3Dが自由に表現できる世界に向けて、今まさに具体的で重要な進化が起こっているということです。</p>

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

<h2>WebGLの未来</h2>

<p><b class="speaker siraisi">白石:</b> こうした動きを踏まえて、WebGLの未来はどうなると思いますか？</p>

<p><b class="speaker isii">石井:</b> 今のコンピューターの世界は、やはり2Dを前提としているのは間違いありません。3Dが利用されるシーンは、ゲームなど、コンピューティングのごく一部に限られていました。マテリアルデザインなども、3Dの要素をうまく取り入れてはいますが、前提は2Dです。</p>

<p>ただ、今、GoogleやApple、Microsoftなどの強力なベンダーたちが、こぞってARやMRに力を入れています。このまま進めば、映画館や不動産屋さんとか、あらゆるお店の軒先にARのオブジェクトが浮いている…という世界は普通に来るんじゃないかと思っているんです。3Dがより身近になる世界です。</p>

<p>ただ、そういうのを見るために、<strong>わざわざアプリをインストールするのは面倒</strong>ですよね。近い将来、そういう面倒くささが、AR/MRの普及を妨げる大きな一因になってくるんじゃないかと思うんです。</p>

<p>しかしWebGLがそういう状況を打開できるんじゃないか、と期待しています。WebGLはWebブラウザさえあれば動きます。PCでもスマホでも動く。アプリのインストールが必要ないし、しかも安全なサンドボックス上で動きます。</p>

<p><b class="speaker siraisi">白石:</b> 確かに！もしかすると、ビーコン技術との組み合わせとか（※）で、アプリのインストールを必要とせず、気軽にバンバンARコンテンツを見るような時代が来るかもしれませんね。</p>

<p><small>
※Webとビーコン技術との組み合わせとして、<a href="https://developers.google.com/beacons/overview" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Eddystone</a>という仕組みがGoogleから考案されている
</small></p>

<p><b class="speaker isii">石井:</b> 実際、Googleが<a href="https://github.com/google-ar/WebARonTango" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">WebAR</a>という仕様を作ったりもしていますし、ARには各社力を入れているので、Webでも早晩ARが使えるようになるだろうと思います。</p>

<p><b class="speaker siraisi">白石:</b> でも実際、要素技術が揃っているだけでは世の中変わらない…という現実もあるかと思います。WebGLも、実際には随分前から使えるようになっていたわけですし。こういう「要素技術が揃っているだけでは越えられない壁」は、どうやったら超えられると思いますか？</p>

<p><b class="speaker isii">石井:</b> 難しい問題ですが、一つは3Dコンテンツの制作コストが高いというのも、普及を妨げる要因にはなるのかなと思います。ただそれは、「人が作る」ことを前提とするからコストが高くつくんだと思うんですよね。</p>

<p>そういう点では、2Dに関しては既に<a href="https://paintschainer.preferred.tech/index_ja.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">PaintsChainer</a>（AI技術を使い、線画を自動で着色するサービス）や<a href="http://make.girls.moe/#/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">MakeGirlsMoe</a>（AIで自動的に萌えキャラを作成するサービス）のようなサービスが出てきています。同様に、自動で3Dコンテンツを生成するようなサービスも近いうちに登場して、コンテンツの制作コストが劇的に下がるんじゃないでしょうか。</p>

<p><b class="speaker siraisi">白石:</b> <strong>AIサービスでコンテンツの制作コストが激減する</strong>というのは面白い発想ですね〜</p>

<p><b class="speaker isii">石井:</b> <a href="https://www.adobe.com/jp/sensei.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Adobe Sensei</a>も最近話題になっていますし、デザインの一部をAIに任せるというトレンドが来つつあるのは確実かなと思いますね。</p>

<h2>Grimoire.jsは、WebGLをWebエンジニアにとっての「筆」にする</h2>

<p><b class="speaker siraisi">白石:</b> では最後に、開発を進めていらっしゃる<a href="https://grimoire.gl/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Grimoire.js</a>についても、簡単にご紹介頂けますでしょうか？Three.jsなどのライブラリとは何が違うんでしょう？</p>

<p><img src="/wp-content/uploads/2017/10/grimoire-logo-640x172.png" alt="" width="640" height="172" class="aligncenter size-large wp-image-24627" srcset="/wp-content/uploads/2017/10/grimoire-logo.png 640w, /wp-content/uploads/2017/10/grimoire-logo-300x81.png 300w, /wp-content/uploads/2017/10/grimoire-logo-207x56.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><b class="speaker isii">石井:</b> Grimoire.jsはWeb開発の中でWebGLを扱うためのフレームワークです。<a href="http://threejs.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Three.js</a>や<a href="http://www.babylonjs.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Babylon.js</a>は、発想がCG中心なんですよね。画面全体をCGで構築するようなコンテンツにはいいのですが、Webコンテンツと混在させて、相互がやり取りするようなプログラムを作るには適していないんです。<strong>CGとWebには大きな隔たりがある</strong>。それに決められた構造を両者に与えて橋をかける必要があった。</p>

<p>この隔たりは、プログラミングスタイルにも大きく表れてきます。</p>

<p>CGの場合は、フレームごとにグラフィックを変更させていく、いわば<strong>フレーム指向</strong>です。<br />
一方でWebの場合は、イベントに応じて処理を行うのが普通ですよね。いわば<strong>イベント指向</strong>です。<br />
こうした隔たりがあるせいで、CG側とWeb側が、お互いにどうデータを受け渡しすればいいか、正解がないというのが今の状況です。</p>

<p>Grimoire.jsは、CG側とWeb側の、2つのAPIを提供することで、両者がシームレスに同居するようなアプリケーションを簡単に作ることができるように設計されています。</p>

<p><b class="speaker siraisi">白石:</b> 具体的にはどのようなコードになるんでしょう？</p>

<p><b class="speaker isii">石井:</b> Grimoire.jsは、GOMLという専用のマークアップ言語でCGを記述することができます。そして、GOMLの要素を変更することで、簡単にCGを変更できるんです。例えば、立方体にテクスチャを貼り付けて、自動的に回転するようなCGは以下のようなマークアップで簡単に実現できます。</p>

<p><img src="/wp-content/uploads/2017/10/cube-640x541.png" alt="" width="640" height="541" class="aligncenter size-large wp-image-24634" srcset="/wp-content/uploads/2017/10/cube.png 640w, /wp-content/uploads/2017/10/cube-300x254.png 300w, /wp-content/uploads/2017/10/cube-207x175.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p></p><pre class="crayon-plain-tag">&lt;goml&gt;
  &lt;scene&gt;
    &lt;camera&gt;&lt;/camera&gt;
    &lt;mesh texture="logo.png" geometry="cube"&gt;
      &lt;mesh.components&gt;
        &lt;Rotate speed="1,1,1" /&gt;
      &lt;/mesh.components&gt;
    &lt;/mesh&gt;
  &lt;/scene&gt;
&lt;/goml&gt;</pre><p></p>

<p>そして例えば、マウスが重なった時だけこの立方体が2倍の大きさになる…という処理は、以下のようなJavaScriptで実現できます。</p>

<p></p><pre class="crayon-plain-tag">gr(function() {
  var mesh = gr('#simple .canvas')('mesh')
  mesh.on('mouseenter', function () {
    mesh.setAttribute('scale', '2.0')
  })
  mesh.on('mouseleave', function () {
    mesh.setAttribute('scale', '1.0')
  })
})</pre><p></p>

<p><b class="speaker siraisi">白石:</b> おお、簡単ですね！これならWebエンジニアでも簡単に扱えそうです。</p>

<p><b class="speaker isii">石井:</b> はい、そうなんです。イベントを受けてパラメーターを書き換えるという流れは、今のWebアプリケーションフレームワークなどの潮流を見れば古い感じを受けるかもしれませんが、結局のところこれだけあればいくらでもラップすることができます。そのようなモダンなWeb開発の環境でもシームレスに環境を選ばず導入できるんです。Grimoire.jsの目標は「<strong>WebGLを、Webエンジニアにとっての『筆』にする</strong>」ことなんです。</p>

<p>一方で、CG側にはUnityに近いようなインターフェースのAPIが提供されています。TypeScriptで記述できるビルド環境が提供されているので、Webに疎いCGサイドでもすぐにWebエンジニアの使う筆を作ることができます。再利用可能で、最終的なパラメーター調整などをWeb側が簡単に行えるわけです。実際、そのためにChrome拡張でWebGLの空間をそのまま操作できる<a href="https://chrome.google.com/webstore/detail/grimoirejs-devtool-20/clioppdjbagckdddfdhpollnkbpepkhn" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">インスペクタ</a>も提供しています。</p>

<div id="attachment_24628" style="width: 650px" class="wp-caption aligncenter"><img src="/wp-content/uploads/2017/10/inspector-640x257.png" alt="Grimoire.js Inspector" width="640" height="257" class="size-large wp-image-24628" srcset="/wp-content/uploads/2017/10/inspector.png 640w, /wp-content/uploads/2017/10/inspector-300x120.png 300w, /wp-content/uploads/2017/10/inspector-207x83.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">Grimoire.js Inspector</p></div>

<p>WebエンジニアにとってCGをより身近にすること、そしてCGがより一般的な世界にすることを目指しています。</p>

<p><b class="speaker siraisi">白石:</b> とても期待しています！本日はWebGLの基本的な事柄から<a href="https://grimoire.gl/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Grimoire.js</a>まで、いろいろ教えていただいてありがとうございました。</p>

<p><b class="speaker isii">石井:</b> 1.0リリースを年内に行いたいと思っています。興味がある方がいたら公式サイトから開発チームのSlackなどに入ると新しい様々な情報が拾えるかと思います。またいくつかの例も載っているのでご覧いただけると幸いです。</p>

<p><DIV align=right>（撮影：刑部友康 写真提供：html5j HTML5 Conference 2017事務局）</div></p>
]]></content:encoded>
		
		<series:name><![CDATA[HTML5 Conference 2017特集]]></series:name>
	</item>
		<item>
		<title>WebAssemblyの基礎から最新動向まで、@chikoskiに聞いてきた！</title>
		<link>/shumpei-shiraishi/24409/</link>
		<pubDate>Wed, 25 Oct 2017 01:00:17 +0000</pubDate>
		<dc:creator><![CDATA[白石 俊平]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[WebAssembly]]></category>
		<category><![CDATA[asm.js]]></category>

		<guid isPermaLink="false">/?p=24409</guid>
		<description><![CDATA[連載： HTML5 Conference 2017特集 (9)こんにちは、編集長の白石です。 この記事は、9月24日に開催されたHTML5 Conference 2017に登壇したエキスパートに、お話されたセッションのト...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/html5-conf2017/" class="series-457" title="HTML5 Conference 2017特集" data-wpel-link="internal">HTML5 Conference 2017特集</a> (9)</div><p>こんにちは、編集長の白石です。</p>

<p>この記事は、9月24日に開催された<a href="http://events.html5j.org/conference/2017/9/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">HTML5 Conference 2017</a>に登壇したエキスパートに、お話されたセッションのトピックを中心に、様々なお話を伺おうというものです。セッションの内容をより深く理解する手助けになるだけでなく、本記事単体でも面白く読んでいただけることを目指しています。</p>

<p>今回お話を伺ったのは、WebAssemblyコミュニティを率いてらっしゃる清水 智公さん（@chikoski）です。清水さんのセッションは「<a href="http://events.html5j.org/conference/2017/9/session/#d5" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">WebAssembly MVPまとめと、今の議論の内容からいくつか</a>」でした。</p>

<p><img src="/wp-content/uploads/2017/10/DSC05255.jpg" alt="" width="640" height="409" class="alignnone size-full wp-image-24599" srcset="/wp-content/uploads/2017/10/DSC05255.jpg 640w, /wp-content/uploads/2017/10/DSC05255-300x192.jpg 300w, /wp-content/uploads/2017/10/DSC05255-207x132.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>※スライド資料は<a href="https://speakerdeck.com/chikoski/20170924-html5conference-wasm" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">こちら</a>で公開されています。</p>

<iframe class="embedly-embed" src="//cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fspeakerdeck.com%2Fplayer%2F847ab70cbf364637b574d6ee1d8382ce&#038;url=https%3A%2F%2Fspeakerdeck.com%2Fchikoski%2F20170924-html5conference-wasm&#038;image=https%3A%2F%2Fspeakerd.s3.amazonaws.com%2Fpresentations%2F847ab70cbf364637b574d6ee1d8382ce%2Fslide_0.jpg&#038;key=internal&#038;type=text%2Fhtml&#038;schema=speakerdeck" width="500" height="416" scrolling="no" frameborder="0" allowfullscreen></iframe>

<p><br></p>

<h2>WebAssemblyとは何か？</h2>

<p><b class="speaker siraisi">白石:</b> 今日はよろしくお願いします。まずは自己紹介をお願いできますか？</p>

<p><b class="speaker simizu">清水:</b> WebAssemblyのコミュニティを運営している清水です。<a href="https://twitter.com/ikkou" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">@ikko</a>さんと一緒に、「<a href="https://emsn.connpass.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">emcscripten night !!</a>」というイベントを四半期に一回くらいのペースで開催しています。</p>

<p><b class="speaker siraisi">白石:</b> では早速ですが、<strong>WebAssembly（WASM）とは何なんでしょうか？</strong></p>

<p><b class="speaker simizu">清水:</b> 一言で言うと、<strong>Webブラウザ上で実行できる、ポータブルなバイナリ形式</strong>です。現在、「MVP（Minimul Viable Product: 最小限有用な機能を備えたプロダクト）」の実装が完了し、ほぼすべてのメジャーブラウザで利用できるという状態です。</p>

<p><b class="speaker siraisi">白石:</b> ポータブルというと、ブラウザにも、OSにも、デバイスにも依存しないということですね。</p>

<p><b class="speaker simizu">清水:</b> その通りです。Javaをご存じの方であれば、classファイル形式を思い浮かべていただくと理解は早いと思います。</p>

<p><b class="speaker siraisi">白石:</b> なるほど。なぜそうしたバイナリ形式が必要とされたんでしょうか？</p>

<p><b class="speaker simizu">清水:</b> これまでWebページで動作するプログラミング言語といえば当然JavaScriptだったわけですが、<strong>JavaScriptは遅い</strong>という問題がありました。asm.jsでスピードの面は大分改善されたのですが、今度はサイズが大きくなってしまうという問題も生まれました。それで早く動かせて、サイズもasm.jsよりは小さいものとして、WebAssemblyが生まれたんです。</p>

<p>遅さの原因の一つは、JavaScriptは変数の型が動的だということです。例えばJavaScriptで足し算を行うコードがあるとしたら、いろんな可能性を考慮しなくちゃいけないんですよね。</p>

<p>値が整数かもしれないし、浮動小数点かもしれない。文字列かもしれないし、<code>valueOf()</code>を持つオブジェクトかもしれない。こういう可能性を踏まえると、単なる足し算といえども最適化は容易じゃないわけです。</p>

<p>ですがWebAssemblyの場合は、コンパイル時に変数の型が決まるので、最適化が容易なんです。今では、<strong>ネイティブに比べて2/3くらいの速度</strong>というところまで改善されています。</p>

<p><b class="speaker siraisi">白石:</b> なるほど。サイズが小さくなるという点についてはいかがでしょう。</p>

<p><b class="speaker simizu">清水:</b> JavaScriptは当然テキスト形式ですが、テキストってやはり冗長なんですよね。例えば、とあるゲームのコードを全部JavaScriptに変換したところ、40メガバイトを超えるサイズになってしまったことがあります。</p>

<p>これでは、JavaScriptのソースコードをダウンロードするだけでかなりの時間がかかってしまうし、実行にかかるコストも半端ではありません。</p>

<p>WebAssemblyは、サイズを小さくすることを最初から念頭に置いたバイナリ形式ですので、確実にサイズは縮まります。元のJavaScriptファイルにもよりますが、ミニファイして圧縮した場合に比べても小さくなるのは確実。場合によっては半分以下のサイズになることもあります。</p>

<p><b class="speaker siraisi">白石:</b> それほど素晴らしいのであれば、将来的にはJavaScriptを置き換えていくような存在になるのでしょうか？</p>

<p><b class="speaker simizu">清水:</b> いえ、WASMはJavaScriptの置き換えは目指しておらず、あくまで補完する存在という位置付けです。例えば、WASMはDOMに直接アクセスすることができませんからね。</p>

<h2>WASMへの対応状況</h2>

<p><b class="speaker siraisi">白石:</b> では改めて、ブラウザのWASMへの対応状況を教えていただけますか？</p>

<p><b class="speaker simizu">清水:</b> 先ほども申し上げたとおり、ほとんどのメジャーブラウザで使えます（参考: <a href="http://caniuse.com/#feat=wasm" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Can I Use</a>）。Safariが11から対応するようになったのは大きいですね。iOSでも使えるようになったということなので。
Edgeも先日のCreator’s updateでデフォルトでWebAssemblyを利用できるようになりました。また、Node.jsでもWebAssemblyは動作します。</p>

<p><b class="speaker siraisi">白石:</b> Nodeでも動くんですか！知りませんでした。WASMにコンパイル可能な言語には、どのようなものがありますか？</p>

<p><b class="speaker simizu">清水:</b> 様々なコンパイラで利用されている、<a href="https://ja.wikipedia.org/wiki/LLVM" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">LLVM</a>という中間言語があるんですが、LLVMに変換される言語だったらだいたい大丈夫です。<a href="https://github.com/kripken/emscripten" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Emscripten</a>というツールを使うと、LLVMからWASMに変換できるのです。</p>

<p>LLVMにコンパイルできる言語というと、C/C++/Objective-Cなどが挙げられます。また、<a href="https://www.rust-lang.org/ja-JP/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Rust</a>もWebAssemblyに対応しています。</p>

<p>あとUnity限定になってしまうのですが、C#にも対応しています。他には<a href="https://github.com/AssemblyScript/assemblyscript" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">AssemblyScript</a>といって、WebAssemblyを出力できるTypeScriptのサブセット言語も存在します。</p>

<p><b class="speaker siraisi">白石:</b> C#やTypeScriptもあるんですね！WebAssemblyにはガベージコレクタがないと聞いていたので、それらの言語が使えるというのは驚きです。</p>

<p>ちなみに、WASMを出力できる言語や動作する環境がたくさんあるのはわかったのですが、実際どれくらい実用的なんでしょうか？</p>

<p><b class="speaker simizu">清水:</b> 今は、<strong>ざっくり言ってC言語のコードをコンパイルして動かす能力は備えている</strong>というところです。
C++への対応は完全じゃありません。C++の例外をまだうまく扱えないんですよね。</p>

<p><b class="speaker siraisi">白石:</b> Cと言えば、メモリを直接操作するようなコードを直接書けると思うのですが、それがWebAssembly上だとどのように動作するのでしょうか？</p>

<p><b class="speaker simizu">清水:</b> WebAssemblyのコードには専用のメモリ空間が割り当てられるんです。C言語におけるメモリ操作などは、そのメモリ空間に対して行われます。そのメモリ空間は、JavaScriptコードからも<code>ArrayBuffer</code>オブジェクトとして参照できます。</p>

<p>ちなみに、WebAssemblyの仕様上は64ビットのメモリ空間を扱えるのですが、現在の実装上では32ビットに制限されていますね。</p>

<h2>WASMを使う</h2>

<p><b class="speaker siraisi">白石:</b> WASMを使うコードはどういうふうになりますか？</p>

<p><b class="speaker simizu">清水:</b> まず、WASMのバイナリが必要です。拡張子は<code>.wasm</code>です。そのファイルを<code>fetch()</code>でも<code>XMLHttpRequest</code>でも何でもいいので読み込んで、バイナリコードを<code>ArrayBuffer</code>化し、<code>WebAssembly.instanciate()</code>というメソッドに渡します。</p>

<p>すると、WebAssemblyコードの実行結果が<code>Promise</code>の戻り値として返ってくるので、そこにエクスポートされている関数をJavaScript側から呼び出すことが可能です。</p>

<p></p><pre class="crayon-plain-tag">// MDNのサンプルを引用
// https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate

// WASMファイルを読み込み
fetch('sample.wasm').then(response =&gt;
  // ArrayBuffer化
  response.arrayBuffer()
).then(bytes =&gt;
  // インスタンスを生成
  WebAssembly.instantiate(bytes)
).then(result =&gt;
  // 生成されたインスタンスのエキスポートされた関数を呼び出し
  result.instance.exports.exported_func()
);</pre><p></p>

<p><b class="speaker siraisi">白石:</b> なるほど、使うのはそれほど難しくなさそうですね。JavaScriptからシームレスに関数の呼び出しを行えるのが素晴らしい。</p>

<p><b class="speaker simizu">清水:</b> はい、それにWASMのコード内から、外部JavaScriptのコードを呼び出すことも簡単にできます。<code>WebAssembly.instantiate()</code>の第二引数で、WASMコードがインポートするメンバーを指定できるんです。</p>

<p></p><pre class="crayon-plain-tag">// MDNのサンプルを引用
// https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate

// WASMがインポートして使用するオブジェクト
var importObject = {
  imports: {
    imported_func: function(arg) {
      console.log(arg);
    }
  }
};
fetch('simple.wasm').then(response =&gt;
  response.arrayBuffer()
).then(bytes =&gt;
  // インポートするオブジェクトを指定
  WebAssembly.instantiate(bytes, importObject)
).then(result =&gt;
  result.instance.exports.exported_func()
);</pre><p></p>

<p><b class="speaker siraisi">白石:</b> なるほど、ダイナミックリンクが可能なんですね。WASMがJavaScriptをどう補完するのか、よくわかりました。</p>

<h2>WASMはどう使われていくか</h2>

<p><b class="speaker siraisi">白石:</b> WASMが登場したことで、具体的に何が変わっていくと思いますか？</p>

<p><b class="speaker simizu">清水:</b> まずはやはり、C/C++で書かれたコードをWASMに変換して使うのが一番最初に思いつくユースケースです。
コンシューマー向けのサービスでいうと、やはりゲーム系がすぐに思いつきますね。</p>

<p>例えば新たなゲームタイトルをスマホ向けにネイティブで開発しつつ、WASMでコンパイルしてWeb版も同時に開発するということができます。
UnityはWebAssemblyに対応しているので、そういう開発を行うのは比較的簡単です。</p>

<p><b class="speaker siraisi">白石:</b> なるほど、スマホ版だけじゃなくてWeb版も同時に開発して公開できれば、ユーザーへのリーチが拡大しそうですね。</p>

<p><b class="speaker simizu">清水:</b> 実際、とあるベンダーさんが、Android用のゲームをWebブラウザでも動作するようにしたところ、ユーザー数はかなり増えたと聞いています。</p>

<p><b class="speaker siraisi">白石:</b> では、<strong>まずはネイティブとWebのクロスプラットフォーム開発でWASMは活躍しそう</strong>だと。
<strong>他にはC言語で書かれた資産とかもWeb上で使えそう</strong>ですよね。例えばgzipのライブラリとか。</p>

<p><b class="speaker simizu">清水:</b> そう、圧縮や暗号系、画像処理などの、Cで書かれたライブラリをWeb上に移植するのにも向いていますね。
CPUに依存する処理を高速化するのには、すごく向いています。</p>

<p>Cで書かれたコードの移植といえば、<a href="https://github.com/vvanders/wasm_lua" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">lua</a>もWASMにコンパイルできたそうです。</p>

<p><b class="speaker siraisi">白石:</b> おお、言語処理系まで！そうか、よく考えたら、現在のWASMにガベージコレクタがなくとも、ガベージコレクタを備えた処理系ごとコンパイルしちゃえばいいんですね。</p>

<h2>WASMのこれから</h2>

<p><b class="speaker simizu">清水:</b> はい、ちょうどガベージコレクタの話が出たので、WASMのこれからという話をしたいと思います。WASMの次のターゲットとして、<a href="https://github.com/WebAssembly/gc/blob/master/proposals/gc/Overview.md" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ガベージコレクタが提案されています</a>。</p>

<p>こちらはおそらく、「ガベージコレクタを使いたい場合は使える」という設計になると予想されています。</p>

<p><b class="speaker siraisi">白石:</b> ガベージコレクタが使えるようになったら、WASMをターゲットにした言語処理系とかが作りやすくなりそうですね。WASMで提案されている仕様は他にもありますか？</p>

<p><b class="speaker simizu">清水:</b> まず、<a href="https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">スレッドを使えるようにする</a>という提案があります。
やはり、pthread (POSIXスレッド: C言語で使用できるマルチスレッドAPI)を使いたいという要望が多いんですね。
複数のWeb Workers（Web環境でマルチスレッディングが可能なAPI）で共有できる Shared ArrayBuffer は既に利用可能ですが、複数のスレッドを待ち合わせる<code>wait</code>や<code>wake</code>と言った命令も使えるようにすることを見据えています。</p>

<p>他には、先ほども申し上げたように<a href="https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">例外</a>を扱えるようにして、C++コードもWASMに正しくコンパイルできるようにすること。WASMのモジュールとECMA Scriptモジュールの整合性を取る…と言った提案も行われています。</p>

<p><b class="speaker siraisi">白石:</b> WASMの未来、楽しみですねー。最後にお聞きしたいのですが、現時点でWASMを試すのにおすすめの言語はありますか？C/C++で書くのはなかなかしんどいなあ、と…</p>

<p><b class="speaker simizu">清水:</b> HTML5 Experts.jpの読者に向けてという話であれば、TypeScript（のサブセット）をWASMにコンパイルできる、<a href="https://github.com/AssemblyScript/assemblyscript" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">AssemblyScript</a>を使うのはおすすめです。Web技術者が軽く試してみるという用途には最適だと思います。</p>

<p><b class="speaker siraisi">白石:</b> 本日は、WebAssemblyについて基礎から最新情報まで教えていただき、ありがとうございました。</p>
]]></content:encoded>
		
		<series:name><![CDATA[HTML5 Conference 2017特集]]></series:name>
	</item>
		<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>ニュースタブ新設で月間アクティブユーザー数が5900万人を突破した「LINE NEWS」の開発技術と体制を聞いてきた！</title>
		<link>/miyuki-baba/24053/</link>
		<pubDate>Fri, 22 Sep 2017 01:00:29 +0000</pubDate>
		<dc:creator><![CDATA[馬場 美由紀]]></dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[システム開発]]></category>
		<category><![CDATA[Assault]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[LINE]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[React.js]]></category>

		<guid isPermaLink="false">/?p=24053</guid>
		<description><![CDATA[2017年2月に新設されたニュースタブによって、ユーザー層をより広く拡大し、2017年3月時点で月間アクティブユーザー数5900万人を突破した「LINE NEWS」。そのニュースタブは、WebViewで実装されているのを...]]></description>
				<content:encoded><![CDATA[<p>2017年2月に新設されたニュースタブによって、ユーザー層をより広く拡大し、2017年3月時点で月間アクティブユーザー数5900万人を突破した「LINE NEWS」。そのニュースタブは、WebViewで実装されているのをご存じでしたか？</p>

<p>LINEのニュースタブをReact.jsで開発しているフロントエンド、JavaとPerlで開発しているサーバーサイドのエンジニアの方々に、どんな開発技術や体制で開発しているのか、HTML5 Experts.jp白石俊平編集長が直撃インタビューしてきました！</p>

<h4>今回お話を聞いた「LINE NEWS」開発チームの皆さん</h4>

<p><img src="/wp-content/uploads/2017/09/maezawa.jpg" alt="" width="90" height="90" class="alignnone size-full wp-image-24089" /><br><span style="font-size: 90%;"><strong>LINE株式会社 前澤 春樹さん</strong><br>Javaのサーバーサイド担当。200以上の媒体社様向け管理画面のコンテンツ入稿システム開発や、公式アカウントから発信されるメッセージ配信システムが主な担当。</span></p>

<p><img src="/wp-content/uploads/2017/09/morifuji.jpg" alt="" width="90" height="90" class="alignnone size-full wp-image-24092" /><br><span style="font-size: 90%;"><strong>LINE株式会社 森藤 賢司さん</strong><br>Perlで作られている一般ユーザーから見えるニュースタブ、記事ページのバックエンドや社内向けの管理画面を担当。</span></p>

<p><img src="/wp-content/uploads/2017/09/otsuki.jpg" alt="" width="90" height="90" class="alignnone size-full wp-image-24095" /><br><span style="font-size: 90%;"><strong>LINE株式会社 大槻 友諒さん</strong><br>フロントエンドエンジニア。WebViewでつくられているニュースタブの実装を担当している。React.jsなどの最新技術に触れることも多い。</span></p>

<p><img src="/wp-content/uploads/2017/09/tomita.jpg" alt="" width="90" height="90" class="alignnone size-full wp-image-24097" /><br><span style="font-size: 90%;"><strong>LINE株式会社 富田 梓さん</strong><br>マークアップエンジニア。デザイナーの作成したPSDをもとにしたCSSの設計と実装を行う。ニュースタブの他、PC/SPのWeb、キャンペーンページなどニュース関連全般を担当。</span></p>

<h2>なぜ、ニュースタブはWebViewなの？</h2>

<p><strong>白石</strong>：今日は主にニュースタブにフォーカスしてお話を聞いていきますね。LINEのニュースタブは、なぜWebViewを使ったのでしょうか。</p>

<p><strong>大槻</strong>：もともと記事ページはWebViewで作っていました。ニュースタブを作ろうという話になったときに、記事ページと同じ技術で作るほうが開発スピードも早いし、やりやすい。バージョンアップなども、そろえたほうがリリースしやすいということでWebViewで作ることになりました。</p>

<p><img src="/wp-content/uploads/2017/09/line-1.jpg" alt="" width="640" height="600" class="alignnone size-full wp-image-24282" srcset="/wp-content/uploads/2017/09/line-1.jpg 640w, /wp-content/uploads/2017/09/line-1-300x281.jpg 300w, /wp-content/uploads/2017/09/line-1-207x194.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><strong>白石</strong>：じゃあ、ニュースタブ以外はネイティブでできているんですね。</p>

<p><strong>大槻</strong>：そうです。トークやタイムラインなど、メインの機能はネイティブで実装されています。並んでるタブの中だと、ニュースタブだけがWebViewです。</p>

<p><strong>白石</strong>：WebViewとネイティブといった複数の技術を混ぜるのって、大変だったんじゃないでしょうか。</p>

<p><strong>大槻</strong>：ネイティブとWebView間でデータやイベントをやり取りする必要があって、そのための仕組みをアプリエンジニアと協力して実現しました。ユーザーにはLINEアプリの一部として見えるので、挙動やパフォーマンスに違和感が出ないようにするのが大変でした。</p>

<p><img src="/wp-content/uploads/2017/09/714103152f1f91a24b71227d63f2b089.jpg" alt="" width="640" height="421" class="alignnone size-full wp-image-24137" srcset="/wp-content/uploads/2017/09/714103152f1f91a24b71227d63f2b089.jpg 640w, /wp-content/uploads/2017/09/714103152f1f91a24b71227d63f2b089-300x197.jpg 300w, /wp-content/uploads/2017/09/714103152f1f91a24b71227d63f2b089-207x136.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><strong>白石</strong>：WebViewだと、読み込みや表示が遅かったりしません？</p>

<p><strong>大槻</strong>：いえ、結果的にそこまで遅いということはなかったです。Webだからの限界はありましたけど、WebViewだから特別つらいことはありませんでした。</p>

<p>LINEバイトやLINEギフトといったファミリーアプリにはすでにWebViewの技術が使われていて、知見があったことも役立ったんだと思います。</p>

<p><strong>白石</strong>：React.jsを使っているとのことですが、SPA的な開発だとマークアップはそんなに必要じゃないと思うんですが、両方必要なのはどうしてなんでしょう。</p>

<p><strong>富田</strong>：うちは分業体制をとっていて、僕と大槻さんが所属しているチームはフロントエンドを担当しています。案件によってJSとマークアップの両方を一人が担当することもありますが、newsでは規模の大きさもあって担当が分かれています。</p>

<p>デザインからHTMLを起こして、それを渡しているので、一般的に言われているReactを使うイメージとはちょっと違うかもしれません。</p>

<p><strong>大槻</strong>：セマンティックなHTMLを書くとか、CSSを設計するといったところは完全にお任せしてします。一回組んだものを、パーツとして分解してJSXに落とし込んでいます。</p>

<p><strong>白石</strong>：PCでも記事ページそのものは見られるんでしたっけ？</p>

<p><strong>富田</strong>：記事ページは見られます。</p>

<p><strong>白石</strong>：あ、レスポンシブ対応しているんですね。</p>

<p><strong>富田</strong>：いえ、レスポンシブとかではなくて、PC専用に作っています。SNSなどでシェアされたURLはPCからでもアクセスできるため、PC用の記事ページを用意しています。</p>

<p><img src="/wp-content/uploads/2017/09/a62e25023750308dc74bc0daa58c6104.jpg" alt="" width="640" height="427" class="alignnone size-full wp-image-24139" srcset="/wp-content/uploads/2017/09/a62e25023750308dc74bc0daa58c6104.jpg 640w, /wp-content/uploads/2017/09/a62e25023750308dc74bc0daa58c6104-300x200.jpg 300w, /wp-content/uploads/2017/09/a62e25023750308dc74bc0daa58c6104-207x138.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<h2>JavaとPerlでサーバー管理</h2>

<p><strong>白石</strong>：サーバーサイドでJavaとPerlという複数言語を使っているのはなぜですか？</p>

<p><strong>森藤</strong>：もともとPerlで全体が作られていたのですが、社内の方針で最近はJavaで作ろうという流れになってきています。なので、最近のレポジトリとかはJavaで作ってます。まあ、歴史的背景です(笑)。</p>

<p>Perlはニュースタブと記事ページ、あと社内向けのCMSもPerlで作られています。</p>

<p><strong>白石</strong>：へえ！CMSは自作なんですね。ちなみに、ReactはAPIを出すのに使ってるんですか？</p>

<p><strong>森藤</strong>：はい、ニュースタブの部分は、全てAPIで実装されています。</p>

<p><img src="/wp-content/uploads/2017/09/7fc05e3e81bcb17d5b5ad87ec08a1f58.jpg" alt="" width="640" height="415" class="alignnone size-full wp-image-24141" srcset="/wp-content/uploads/2017/09/7fc05e3e81bcb17d5b5ad87ec08a1f58.jpg 640w, /wp-content/uploads/2017/09/7fc05e3e81bcb17d5b5ad87ec08a1f58-300x195.jpg 300w, /wp-content/uploads/2017/09/7fc05e3e81bcb17d5b5ad87ec08a1f58-207x134.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><strong>白石</strong>：Reactでサーバーサイドレンダリングしているのでしょうか。</p>

<p><strong>大槻</strong>：いえ、クライアント側でレンダリングしています。</p>

<p>APIでとってきたデータをローカルストレージにのせておいて、ネットワークがないところでも画面が真っ白にならないように工夫しています。</p>

<p><strong>白石</strong>：JavaとPerlで分かれていますけど、システム間連携しているんですか？</p>

<p><strong>森藤</strong>：データベースで連携しています。データベースはMySQLを使っています。</p>

<p><strong>白石</strong>：MySQLをクラウド上で？</p>

<p><strong>森藤</strong>：いえ、オンプレです。本番環境は、現在ほとんどオンプレのサーバーで動いていますが、最近構築したサーバーや開発環境はプライベートクラウドの「Verda」というサービスを使っています。</p>

<p><strong>白石</strong>：えっ、どこかの製品を買うのではなく、自分たちで作ってるんですか。かっこいいですね。</p>

<p><strong>森藤</strong>：DB周りはDBA（データベース管理者）のチームが運用しています。DBサーバーの構成は、マスター1台に参照やバックアップに使うスレーブが数台ある感じです。テキストで入稿するデータなので、データ容量が一気に増えて困ったとか、容量が足りなくなったという話も聞いたことがないですね。</p>

<p><strong>白石</strong>：Javaで入稿システムを作っていらっしゃるんですよね。ScalaやKotlinなんかも使っているんでしょうか？</p>

<p><strong>前澤</strong>：Javaだけです。最近のモダンな言語に比べると、やっぱりJavaは冗長というかすごいコード量を書かないといけないのは大変なんですが…。</p>

<p><img src="/wp-content/uploads/2017/09/7e28640bea28ad295c056205fe2d3ed1.jpg" alt="" width="640" height="427" class="alignnone size-full wp-image-24142" srcset="/wp-content/uploads/2017/09/7e28640bea28ad295c056205fe2d3ed1.jpg 640w, /wp-content/uploads/2017/09/7e28640bea28ad295c056205fe2d3ed1-300x200.jpg 300w, /wp-content/uploads/2017/09/7e28640bea28ad295c056205fe2d3ed1-207x138.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><strong>白石</strong>：ぼくは昔Javaエンジニアだったのですごく気になるんですが、Javaのバージョンは何ですか？</p>

<p><strong>前澤</strong>：Java 8です。</p>

<p><strong>大槻</strong>：僕も前職では、エンタープライズ系のサービスをJavaで書いていました。その時はバージョンが古くて4でした。あと8をちょっと触ったくらい。当時はジェネリクスもアノテーションもなくて(笑)。</p>

<p><strong>白石</strong>：僕はXML地獄でしたね(笑)。EclipseみたいなIDEとかは使ってますか？</p>

<p><strong>前澤</strong>：Eclipseは使ってなくて、IntelliJ IDEAを使ってます。</p>

<h2>React.jsを選択した背景は？</h2>

<p><strong>白石</strong>：フロントエンドのReact.jsはいつから使ってるんですか？</p>

<p><strong>大槻</strong>：ニュースタブができてからなので、2017年2月からですね。</p>

<p><strong>白石</strong>：苦労したこととかありますか？</p>

<p><strong>大槻</strong>：React.jsだから苦労したことは特になかったんですが、どのライブラリにするかは結構検証しました。Vue.jsやRiot.jsなんかもいろいろ試してみたのですが、結局React.jsにしました。</p>

<p>Create React Appでベースを立ち上げた経緯もあって、最初の環境を整えるのはすごくスムーズでした。React.jsは結構書きやすくて、世の中で使われているアプリも多く、バージョンアップも早いし、安定していて信頼できました。</p>

<p><strong>白石</strong>：なるほど。stateの管理とか、Reduxは使ってますか？</p>

<p><strong>大槻</strong>：Reduxは最初は使おうと思ったのですが、意外と過剰なスペックがあってやめました。代わりにFlux Utilsを使っています。</p>

<p><img src="/wp-content/uploads/2017/09/b469fca96ff63ef07dd9aa9661fa216d.jpg" alt="" width="640" height="416" class="alignnone size-full wp-image-24144" srcset="/wp-content/uploads/2017/09/b469fca96ff63ef07dd9aa9661fa216d.jpg 640w, /wp-content/uploads/2017/09/b469fca96ff63ef07dd9aa9661fa216d-300x195.jpg 300w, /wp-content/uploads/2017/09/b469fca96ff63ef07dd9aa9661fa216d-207x135.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<h2>足りない開発ツールはどんどん作る</h2>

<p><strong>白石</strong>：ほかにLINEさん独自の開発手法があれば教えてください。</p>

<p><strong>大槻</strong>：フロントのアクセス解析はGoogle アナリティクスを使っているんですが、そのほかに社内で開発した「LINE Analytics」という解析ツールを使っています。JavaScriptのエラー部分もリアルタイムに収集できるので、リリース直後に増減を確認したりしています。</p>

<p><strong>白石</strong>：LINEさんは結構社内で作る文化があるんですね。自分たちでも作るというのは、意思決定が必要だと思うんですが、どんなかんじで決めているんですか？</p>

<p><strong>富田</strong>：その辺は結構自由にやらせてもらえる風土ですね。プロジェクトで使うツールだけでなく、たとえばメーラーやスケジュール管理といった社内システムについて内製する部署があります。既製品でもの足りなかったら、自分たちで作っちゃおうみたいな。</p>

<p><strong>大槻</strong>：分業しているのでサーバーに触れること自体は少ないんですが、JSやCSSの配信ツールをフロントエンドチーム内で開発したりと、役割内で足りないものは作って配布させたりする人が多いですね。</p>

<p>サーバー側はCIも自前で作ってると聞きました。社内の承認フローがそれほどかたくないので、わりと気軽に自前で作ってます。</p>

<p><strong>白石</strong>：CIもですか！Jenkinsとかを使わずに？</p>

<p><strong>前澤</strong>：Perlでは内製のCIを使っていますが、JavaではJenkinsを使ってビルドしていて、ビルドした成果物をサーバーに配布するシステムは内製です。CDNのオリジンサーバーも自作してますね。</p>

<p><img src="/wp-content/uploads/2017/09/602ad76d16be61a37571ec369267e1b3.jpg" alt="" width="640" height="427" class="alignnone size-full wp-image-24145" srcset="/wp-content/uploads/2017/09/602ad76d16be61a37571ec369267e1b3.jpg 640w, /wp-content/uploads/2017/09/602ad76d16be61a37571ec369267e1b3-300x200.jpg 300w, /wp-content/uploads/2017/09/602ad76d16be61a37571ec369267e1b3-207x138.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<h2>秒間2万のアクセスを捌くパフォーマンス</h2>

<p><strong>白石</strong>：パフォーマンスなんかもかなり気をつかっているんじゃないでしょうか。</p>

<p><strong>森藤</strong>：はい。APIアクセスが秒間2万くらいのアクセスがあるので試行錯誤しています。APPサーバーの台数は約30台くらいなんですが。</p>

<p><strong>森藤</strong>：去年の6月に高速化プロジェクトがあって、CDNを追加しました。CDNはAkamaiを使っています。クエリーをちゃんと書いてなかったりするとサービスが止まるので、SQLには気をつけてキャッシュに貯めるようにしていますね。</p>

<p><strong>白石</strong>：フロントエンドのパフォーマンスで工夫した点はどうですか？</p>

<p><strong>大槻</strong>：ニュースタブは縦に長いんですけど、DOMが増え過ぎるとメモリを食ってアプリがクラッシュしてしまう問題がありました。</p>

<p>iPhoneでは横スワイプでタブ移動できるので、左右のタブを予め描画している分よりDOMが多く、見えないDOMをいかに削除していくかなどの工夫をしています。</p>

<p><img src="/wp-content/uploads/2017/09/03af4a0fd0dd99fb25cd675d50767410.jpg" alt="" width="640" height="413" class="alignnone size-full wp-image-24147" srcset="/wp-content/uploads/2017/09/03af4a0fd0dd99fb25cd675d50767410.jpg 640w, /wp-content/uploads/2017/09/03af4a0fd0dd99fb25cd675d50767410-300x194.jpg 300w, /wp-content/uploads/2017/09/03af4a0fd0dd99fb25cd675d50767410-207x134.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<h2>タスク管理・チーム間の共有ツールは？</h2>

<p><strong>白石</strong>：皆さんは所属する組織は違うとのことですが、「LINE NEWS」プロジェクトのタスク管理やチーム間の共有ツールはどうしていますか。</p>

<p><strong>富田</strong>：ニュースチームのプロジェクトとして定例ミーティングをして、進捗管理しています。管理に使っているツールはJIRAですね。</p>

<p><strong>白石</strong>：進め方はアジャイルですか？</p>

<p><strong>富田</strong>：そんなにアジャイルぽくはないです。企画チームが20人くらいいて、案件ベースを作ってくれるので、早い段階で開発からもフィードバックしたり、企画と一緒に練ったりします。1週間のスプリント制でやっています。</p>

<p><img src="/wp-content/uploads/2017/09/a93d802f163a1d84f00d15d6fa46a45b.jpg" alt="" width="640" height="419" class="alignnone size-full wp-image-24150" srcset="/wp-content/uploads/2017/09/a93d802f163a1d84f00d15d6fa46a45b.jpg 640w, /wp-content/uploads/2017/09/a93d802f163a1d84f00d15d6fa46a45b-300x196.jpg 300w, /wp-content/uploads/2017/09/a93d802f163a1d84f00d15d6fa46a45b-207x136.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><strong>白石</strong>：ニュースチームは全体で何人くらいいらっしゃるんですか？</p>

<p><strong>前澤</strong>：企画や開発、制作、編集、アライアンス、モニタリング、PR・マーケティングなどを含めると、プロジェクトに関わっている人は100人を超えています。エンジニアは現在、バックエンドが8人、フロントエンドが4人です。</p>

<p><strong>白石</strong>：大型プロジェクトですね。CIは自作されてるとのことでしたけど、DevOpsみたいな工夫ポイントはありますか？</p>

<p><strong>前澤</strong>：これまでは五月雨で流動的だったけど、人が増えてきたので週1回のサイクルを整えたり、模索しているところです。</p>

<p><strong>白石</strong>：ソースコードの管理やリリースのルールとかはどうでしょう。</p>

<p><strong>森藤</strong>：ソースコードの管理はGitHubです。Perl側は最低2人レビュアーがいないとリリースやマージしちゃいけないことになっています。</p>

<p><img src="/wp-content/uploads/2017/09/39bde474619f03cb353ff513ca4ae7b9.jpg" alt="" width="640" height="421" class="alignnone size-full wp-image-24149" srcset="/wp-content/uploads/2017/09/39bde474619f03cb353ff513ca4ae7b9.jpg 640w, /wp-content/uploads/2017/09/39bde474619f03cb353ff513ca4ae7b9-300x197.jpg 300w, /wp-content/uploads/2017/09/39bde474619f03cb353ff513ca4ae7b9-207x136.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<h2>急成長するサービスと開発体制に合った環境を構築</h2>

<p><strong>白石</strong>：最後に今後こうしたいという抱負や、チャレンジしたい目標を教えてください。</p>

<p><strong>前澤</strong>：LINEのサービスが急速に成長して、エンジニアも増えているので、開発時期によってリポジトリやフレームワークの使い方も違ってきています。それを統一したいと思っているんですけど、結構大変そうです(笑)。</p>

<p><strong>森藤</strong>：これまでのサーバーサイドはほとんどPerlだったんですけど、ここ数年みんなJavaを書くようになって、Perlを書くエンジニアが減ってきているんです。サーバー側をもっとJavaに置き換えていけたらと思ってます。</p>

<p><strong>大槻</strong>：TypeScriptを導入も検討していきたいです。依存するライブラリの都合もあって、簡単ではないかもしれませんが。</p>

<p><strong>富田</strong>：ニュースのプロジェクトが始まったのが2013年で、最近では更新が滞っているruby-sassやgrunt、compassといった古い環境に依存しており、日々の更新に忙しくてそういった根幹部分はなかなか手を入れることが難しかったんですが、最近のリリースで、タスクランナーに依存したコンパイルをやめたり、node-sassへの移行したりしました。</p>

<p>それに伴ってチームで使っている社内用のツールやsassのライブラリを更新しているので、今後も新しい技術についてそれらに生かせるか検証しつつ対応できればと思っています。</p>

<p><strong>白石</strong>：LINEさんは独自の開発ツールをどんどんつくっていく行動力と技術力が素晴らしいですね。今日はいろいろ面白い話をありがとうございました！</p>

<p>LINEさんでは、9月28日(木) にエンジニア向け技術カンファレンス「<a href="http://linedevday.linecorp.com/jp/2017/" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">LINE DEVELOPER DAY 2017</a>」を開催するそうです。LINEの様々なサービスにおける技術領域でのチャレンジや開発体制などについて語られるとのことなので、興味のある方はぜひ参加してみてください。</p>

<p><img src="/wp-content/uploads/2017/09/DSC02651-2.jpg" alt="" width="640" height="415" class="alignnone size-full wp-image-24057" srcset="/wp-content/uploads/2017/09/DSC02651-2.jpg 640w, /wp-content/uploads/2017/09/DSC02651-2-300x195.jpg 300w, /wp-content/uploads/2017/09/DSC02651-2-207x134.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>
]]></content:encoded>
			</item>
		<item>
		<title>日本最大級のHTTP/2移行、TLS 1.3、そしてQUICについてヤフーに聞いてみた！</title>
		<link>/shumpei-shiraishi/24164/</link>
		<pubDate>Fri, 15 Sep 2017 00:48:15 +0000</pubDate>
		<dc:creator><![CDATA[白石 俊平]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[システム開発]]></category>
		<category><![CDATA[HTTPS]]></category>
		<category><![CDATA[QUIC]]></category>
		<category><![CDATA[http2]]></category>
		<category><![CDATA[ヤフー]]></category>

		<guid isPermaLink="false">/?p=24164</guid>
		<description><![CDATA[連載： HTML5 Conference 2017特集 (5)こんにちは、編集長の白石です。 この記事は、9月24日に開催されるHTML5 Conference 2017に登壇するエキスパートに、予定しているセッションの...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/html5-conf2017/" class="series-457" title="HTML5 Conference 2017特集" data-wpel-link="internal">HTML5 Conference 2017特集</a> (5)</div><p>こんにちは、編集長の白石です。</p>

<p>この記事は、9月24日に開催される<a href="http://events.html5j.org/conference/2017/9/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">HTML5 Conference 2017</a>に登壇するエキスパートに、予定しているセッションのトピックを中心に、様々な技術的なお話を伺おうというものです。セッションの内容をより深く理解する手助けになるだけでなく、本記事単体でも面白く読んでいただけることを目指しています。</p>

<p>今回お話を伺ったのは、ヤフー株式会社にお勤めの大津繁樹さんと新部長則さんです。</p>

<p><img src="/wp-content/uploads/2017/09/DSC04596.jpg" alt="" width="640" height="400" class="alignnone size-full wp-image-24194" srcset="/wp-content/uploads/2017/09/DSC04596.jpg 640w, /wp-content/uploads/2017/09/DSC04596-300x188.jpg 300w, /wp-content/uploads/2017/09/DSC04596-207x129.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /><br><span style="font-size: 80%;">▲<strong>左から、ヤフー株式会社 大津繁樹さん、新部長則さん</strong></span></p>

<p>お二人のセッションは「<a href="http://events.html5j.org/conference/2017/9/session/#b2" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">大規模運用で見えるWebプロトコルの理想と現実、そして今後</a>」（ルームB 13:20-14:00）です。
（現在HTML5 Conferenceは定員オーバーの状態ですが、無料イベントということもあってキャンセルも多めに出るらしいので、諦めずにキャンセル待ちすることをお勧めします！）</p>

<h2>日本最大級のHTTPS &amp; HTTP/2化案件の実際</h2>

<p><b class="speaker siraisi">白石:</b> まず簡単な自己紹介からお願いできますでしょうか？</p>

<p><b class="speaker nibe">新部:</b> 私は2005年の7月に入社し、Yahoo!メールや広告の画像配信を行うCDNの運用などを経て、現在は全社で利用しているリバースプロキシの運用を行っています。
現在、社内でプラットフォームと呼ばれる部分にはだいたい関わっている感じですね。</p>

<p><b class="speaker ohtsu">大津:</b> まさに、新部さんのチームは、ヤフーのトラフィックをほとんど全て受け止めていると言って間違いありません。国内最大級のトラフィックを支えているんです、半端ないですよ。</p>

<p><b class="speaker siraisi">白石:</b> では大津さんも自己紹介をお願いできますか？</p>

<p><b class="speaker ohtsu">大津:</b> 私は昨年の10月に入社したばかりです。大きく2つの仕事をしていまして、Node.jsのコミッターとして社内のサポートを行っているのと、IETFでネットワークプロトコルの標準化活動に関わっています。</p>

<p><b class="speaker siraisi">白石:</b> ありがとうございます。では、ヤフーのサービスをHTTPS + HTTP/2化した際のことを伺ってもいいですか？</p>

<p><b class="speaker nibe">新部:</b> まずはヤフーのサービスをHTTPSに移行するところから始めたんです。HTTPS化に伴うコストや影響の試算を踏まえて、2015年10月に、全社横断でHTTPS化するプロジェクトが発足したんです。</p>

<p>HTTPS化するにあたっては大きな問題が2つありました。1つは、TLSの暗号化・復号化の処理が重たいということ。もう1つは、証明書の管理が煩雑にならないようにしなくてはならないということでした。なにせドメインでいうと1,000以上、サービスも100以上ありますので。</p>

<p><img src="/wp-content/uploads/2017/09/bc4381f4affc0b228260a833a3758bfb.jpg" alt="" width="640" height="427" class="alignnone size-full wp-image-24195" srcset="/wp-content/uploads/2017/09/bc4381f4affc0b228260a833a3758bfb.jpg 640w, /wp-content/uploads/2017/09/bc4381f4affc0b228260a833a3758bfb-300x200.jpg 300w, /wp-content/uploads/2017/09/bc4381f4affc0b228260a833a3758bfb-207x138.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><b class="speaker siraisi">白石:</b> 規模感が普通の会社とは桁違いだ…。</p>

<p><b class="speaker nibe">新部:</b> なので、全社共通のリバースプロキシを作って対応することになったんです。そのリバースプロキシでTLSを一旦終端させて、そこから先は通常のHTTP/1.1に変換し、各サービスにリクエストを転送する。</p>

<p><b class="speaker siraisi">白石:</b> そのリバースプロキシって、だいたいサーバ何台分くらいになるんでしょう…？</p>

<p><b class="speaker nibe">新部:</b> <strong>500台以上</strong>ですね。</p>

<p><b class="speaker ohtsu">大津:</b> 「以上」と言っても幅があると思いますが、<strong>そのかなり上の方</strong>ですよ、実際の数字は(笑)。</p>

<p><b class="speaker siraisi">白石:</b> す、すごい…！</p>

<p><b class="speaker nibe">新部:</b> そして、2016年3月、最初にリバースプロキシに乗ったのはヤフオク！です。</p>

<p><b class="speaker siraisi">白石:</b> なんでヤフオク!を最初のサービスに選んだんですか？</p>

<p><b class="speaker nibe">新部:</b> 検証の意味も強かったので、ある程度以上の規模感のあるサービスをデプロイしたかったんです。あと、下手すると人命を左右するような「何があっても絶対に止められない」サービスは避けたかった。</p>

<p><b class="speaker siraisi">白石:</b> なるほど。</p>

<p><b class="speaker nibe">新部:</b> ヤフオク！も、いきなり全部をHTTPS化したわけじゃなくて、最初は一部だけ、その後範囲を広げていったという感じです。
幸いにもそれほど大きな事故も起こることなく進んでいき、2017年の3月末には、特定のクライアントに提供しているところを除いたすべてのサービスがHTTPSで動作するようになりました。</p>

<h2>HTTP/2化は正直、「エイヤ」でやった</h2>

<p><b class="speaker siraisi">白石:</b> なるほど、HTTPS化は、様々なご苦労はあったことと思いますが、比較的順調に推移したということですね。そして今では多くのサービスがHTTP/2を利用しているんですよね。<strong>HTTP/2化はどういう流れで進んでいったんですか？</strong></p>

<p><b class="speaker nibe">新部:</b> これはちょっと言いにくいし、言っていいのかもわからないんですが…<strong>正直、「エイヤ」でやってしまったところもありますね(笑)</strong>。</p>

<p>全社共通のリバースプロキシを構築できたし、ここをHTTP/2化してしまえば、全部HTTP/2にできるじゃん、と。弊社のエンジニアもHTTP/2サーバの実装に携わっていたりもしたので、自分たちで作った成果を自分たちで使いたいという要望もありまして…。</p>

<p><img src="/wp-content/uploads/2017/09/51c35f6b549c0e867e11f9359ea822e5.jpg" alt="" width="640" height="427" class="alignnone size-full wp-image-24196" srcset="/wp-content/uploads/2017/09/51c35f6b549c0e867e11f9359ea822e5.jpg 640w, /wp-content/uploads/2017/09/51c35f6b549c0e867e11f9359ea822e5-300x200.jpg 300w, /wp-content/uploads/2017/09/51c35f6b549c0e867e11f9359ea822e5-207x138.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><b class="speaker siraisi">白石:</b> で、「エイヤ」でやっちゃったと(笑)。</p>

<p><b class="speaker nibe">新部:</b> まあ、全部をいきなり切り替えたわけじゃないですけどね。こちらも一部のサーバだけを切り替えて、問題がないことを確認しつつ、だんだんと。</p>

<p><b class="speaker siraisi">白石:</b> なるほどー。ちなみにその、最も重要なリバースプロキシですが、具体的にはどのソフトを利用しているんですか？nginxとか？</p>

<p><b class="speaker nibe">新部:</b> いや、<a href="http://trafficserver.apache.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Apache Traffic Server</a>というプロダクトです。元々これは米国のYahoo! Inc.が開発していたものをApache Software Foundationに寄贈したものです。</p>

<p><b class="speaker siraisi">白石:</b> では、Apache HTTP Serverとは関連がないんですね。</p>

<p><b class="speaker nibe">新部:</b> そうです。このサーバをHTTP/2対応させるパッチの開発に、弊社のエンジニアもコミットしているんです。</p>

<h2>「HTTP/2化で速くなったかは…正直わかりません(笑)」</h2>

<p><b class="speaker siraisi">白石:</b> では、HTTP/2への切り替えは、それほど大きな問題もなくうまく行ったと。そうした環境で運用を行ってみて、実際にわかったことや問題などはありますか？例えばHTTP/2化することで、パフォーマンスが向上するんじゃないかという期待はあったと思うのですが。</p>

<p><b class="speaker ohtsu">大津:</b> そうですね…正直に言ってしまうと、HTTP/2でパフォーマンスが上がったかどうかは<strong>よくわからない</strong>んです。</p>

<p><b class="speaker siraisi">白石:</b> ああ、それ<a href="https://html5experts.jp/shumpei-shiraishi/24156/" data-wpel-link="internal">先日インタビューしたあほむさん</a> も同じこと言ってました(笑)。</p>

<p><b class="speaker ohtsu">大津:</b> 個別に見れば、速度が上がっている部分は確実にあるんです。ただ、トータルで向上したかどうかは結局よくわからないんですよね。</p>

<p>例えば、<code>window.onload</code> が速くなったかというと、そうでもないんです。ただ、<code>onload</code>についてはあまりにも様々な要因が絡むんで、測定の指標としてあまり有効でないという問題もありますけどね。なにせ、ずっと昔から運営しているサービスなので、 <code>document.write</code> にブロックされているページも残っていたりしますし。</p>

<p><img src="/wp-content/uploads/2017/09/e64a89a1dacf16720a61477a7e16379c.jpg" alt="" width="640" height="427" class="alignnone size-full wp-image-24197" srcset="/wp-content/uploads/2017/09/e64a89a1dacf16720a61477a7e16379c.jpg 640w, /wp-content/uploads/2017/09/e64a89a1dacf16720a61477a7e16379c-300x200.jpg 300w, /wp-content/uploads/2017/09/e64a89a1dacf16720a61477a7e16379c-207x138.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><b class="speaker siraisi">白石:</b> 確かに、「トータルで向上したか」と言っても「トータル」ってそもそも何なんだという定義が難しそうです。</p>

<p><b class="speaker ohtsu">大津:</b> そういうところも含めて、測定が十分に行えていないというのも課題ですね。サーバ側のログを見ると、リクエスト数ベースでHTTP/1.1とHTTP/2の割合は現在4:6くらいです。</p>

<p><b class="speaker siraisi">白石:</b> 1.1がまだいるっていうのは…ああそうか、(HTTP/2に対応していない)古いブラウザを使っているクライアントですね。クライアントの環境も様々だから、余計測定が難しいですね…。</p>

<p><b class="speaker ohtsu">大津:</b> そうなんです。一気に切り替えてしまったことで、A/Bテストなども行えていないですしね。A/Bテストを行うために、一部を一旦HTTP/1.1に戻すというのもありかもしれません(笑)。</p>

<h2>HTTP/2がサーバの処理負荷を下げる？</h2>

<p><b class="speaker siraisi">白石:</b> HTTP/2に移行する前の、HTTPSへの切り替えではいかがでしたか？先程、「TLSの処理が重たい」という懸念が事前にあったとのことでしたが。</p>

<p><b class="speaker nibe">新部:</b> 一度それで問題になったことはありますね。</p>

<p>弊社のサービスからプッシュ通知を送った時とかは、ユーザーが一斉に接続するので負荷が一時的に高まるんですが、それでCPUがパツパツになってしまったことがありまして。ただ、HTTPS化する前はCPUがボトルネックになるようなことはなかったので、やはりTLSの処理が影響していたんだろうなあと思います。</p>

<p><b class="speaker ohtsu">大津:</b> ただ、<strong>その後そういう問題は起きていないのは、HTTP/2が一役買っているのかもしれません</strong>。</p>

<p>HTTP/2はTCPセッション数が減るので、TLSの暗号化・復号化に伴う処理負荷も減ります。単純に言えば、HTTP/1.1の時に6セッションだったものがHTTP/2で1セッションになったら、TLSのコストは1/6になるわけで。</p>

<p><b class="speaker siraisi">白石:</b> なるほど！HTTP/2がサーバの処理負荷を下げるという可能性は、今まで思い至りませんでした。</p>

<p><img src="/wp-content/uploads/2017/09/c4c6994cd0eee49d9c63ee16f82a8554.jpg" alt="" width="640" height="421" class="alignnone size-full wp-image-24198" srcset="/wp-content/uploads/2017/09/c4c6994cd0eee49d9c63ee16f82a8554.jpg 640w, /wp-content/uploads/2017/09/c4c6994cd0eee49d9c63ee16f82a8554-300x197.jpg 300w, /wp-content/uploads/2017/09/c4c6994cd0eee49d9c63ee16f82a8554-207x136.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<h2>HTTP/2のさらに先へ。新しいプロトコルを知る &#8211; TLS 1.3とは？</h2>

<p><b class="speaker siraisi">白石:</b> HTML5 Conferenceでは、さらに新しいプロトコルについてもご紹介があるとのことですね。</p>

<p><b class="speaker ohtsu">大津:</b> はい、TLS 1.3やQUICについて紹介しようかと思います。</p>

<p><strong>TLS 1.3</strong>というのは、1.2までの技術的負債を精算しつつ、ハンドシェイクを速くすることを目的とした仕様です。仕様はだいたい固まっていて、現在Googleをはじめとした企業が、実験的に使用して調査中です。</p>

<p><b class="speaker siraisi">白石:</b> 技術的負債を精算して、さらに速く…って、いいことづくめですね。</p>

<p><b class="speaker ohtsu">大津:</b> ただ、TLS 1.3にはまだ大きな問題が残っています。<strong>後方互換性に関わる透過性の問題があって、通信できない場合があることが報告されているのです</strong>。</p>

<p>TLS 1.3に対応していない中間機器が、接続を無断で切断しちゃうことがあるんですよね。そういうファイアウォール、IDS（Intrusion Detection System:不正侵入検知システム）、IDP（Intrusion Prevention System:不正侵入予防システム）などが中間経路にあると、ネットワーク全体がダウンしてしまうこともあります。本来は、TLS 1.2にフォールバックしてほしいのですが…現在Googleなどが後方互換の問題を最小にするために透過性の調査を行っているところです。</p>

<p><b class="speaker siraisi">白石:</b> 通信を遮るものをどう扱うか、は難しい問題ですね。正直、簡単に解決する問題には全く聞こえませんね…</p>

<p><b class="speaker ohtsu">大津:</b> そうなんですよ。少し前に、<a href="https://www.theregister.co.uk/2017/02/27/blue_coat_chokes_on_chrome_encryption_update/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">GoogleがTLS 1.3を試験的に有効化していたところ、ある学校で問題が発生し、数万台のChromebookが通信もアップデートも行えなくなってしまうということがありました</a>。
こうなるとGoogleですらお手上げなんですよね。TLSに完全に依存しているので。</p>

<p>そう考えると、HTTP/2って「幸運」だったと思うんですよね。</p>

<p><b class="speaker siraisi">白石:</b> 「幸運」ですか。</p>

<p><b class="speaker ohtsu">大津:</b> はい、TLS 1.2という「枯れた」プロトコル上の動作を前提にできたのがラッキーでした。TLS1.2って、2008年に登場したプロトコルで、今は完全に普及しきっていますから。</p>

<p>そういう前提のないプロトコルや機能拡張だと、大変なんです。</p>

<p>例えば、TCPのデータ送受信開始を速める「<a href="https://html5experts.jp/jxck/3529/" data-wpel-link="internal">TCP Fast Open</a>」という仕様もあるのですが、<a href="https://www.nanog.org/sites/default/files/Paasch_Network_Support.pdf" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">うまく通じない現象がAppleのエンジニアによって報告</a>されていて、<a href="http://asnokaze.hatenablog.com/entry/2017/05/09/223534" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">最近Linuxで緩和策が講じられたにもかかわらず</a>、Microsoft Edgeではついにデフォルトで無効化されてしまいました。</p>

<p>TCP Fast Openは2014年に標準化されており、Linux、 macOS、 WindowsなどOSの対応も進んでいるのですが、それでもまだこういう状況です。それほど、低レイヤーのプロトコルを普及させていくのは難しい。</p>

<p>だから、私たちがHTTP/2の移行にあまり苦労しなかったことも含め、HTTP/2のアップグレードがこれほどスムーズなのは大変幸運なことなのです。</p>

<p><img src="/wp-content/uploads/2017/09/d3cf54c0f443750953b54a236fa672c3.jpg" alt="" width="640" height="427" class="alignnone size-full wp-image-24200" srcset="/wp-content/uploads/2017/09/d3cf54c0f443750953b54a236fa672c3.jpg 640w, /wp-content/uploads/2017/09/d3cf54c0f443750953b54a236fa672c3-300x200.jpg 300w, /wp-content/uploads/2017/09/d3cf54c0f443750953b54a236fa672c3-207x138.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<h2>QUICという「プラットフォーム」の可能性</h2>

<p><b class="speaker siraisi">白石:</b> <strong>QUIC</strong>についても教えていただけますか？</p>

<p><b class="speaker ohtsu">大津:</b> QUICは、<strong>ざっくり言うとUDPの上でTCP、TLS 1.3、そしてHTTP/2の一部をごちゃっとやる感じのプロトコル</strong>です。</p>

<p><b class="speaker siraisi">白石:</b> ごちゃっと(笑)。</p>

<p><b class="speaker ohtsu">大津:</b> IETFでの標準化も進められていて、今度の10月で1年になりますね。非常に有望なプロトコルで、今後のネットワークのプラットフォームになっていくポテンシャルを秘めていると期待しています。</p>

<p><b class="speaker siraisi">白石:</b> なぜそこまで期待していらっしゃるのでしょう？</p>

<p><b class="speaker ohtsu">大津:</b> 「UDPなので疎通性が良い」というのと「ユーザーランドで動作するプロトコルなのでデプロイが容易」ということが挙げられます。</p>

<p>先程TLS 1.3の普及には苦労しそうだ、という話をしましたが、QUICはUDPなので比較的通りやすいんです。また、通じなかった場合はTCPにフォールバックする機能もある。通信を行うコンピューター同士が、エンドツーエンドでQUICに対応していればいいのです。</p>

<p>ユーザーランドで動作する…というのは、TCP BBR (※) と比較するとわかりやすいと思います。</p>

<p><small>
※参考: 「<a href="http://www.publickey1.jp/blog/17/googletcptcp_bbrgoogle_cloud.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Google、TCPのスループットとレイテンシを改善する輻輳制御アルゴリズム「TCP BBR」をGoogle Cloudで利用開始 (Publickey)」</a>
</small></p>

<p>TCP BBRは、Googleが開発した新しい輻輳制御のアルゴリズムです。モバイル環境のように、パケットロスが非常に多い環境でも速度を最大化できるという利点があります。</p>

<p><img src="/wp-content/uploads/2017/09/2071b8b501257b7d07a5f4c6ebf54559.jpg" alt="" width="640" height="427" class="alignnone size-full wp-image-24201" srcset="/wp-content/uploads/2017/09/2071b8b501257b7d07a5f4c6ebf54559.jpg 640w, /wp-content/uploads/2017/09/2071b8b501257b7d07a5f4c6ebf54559-300x200.jpg 300w, /wp-content/uploads/2017/09/2071b8b501257b7d07a5f4c6ebf54559-207x138.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>しかし欠点としては、TCPのスタックってOSのカーネルに実装されているので、<strong>使おうとするとカーネルのアップデートが必要になる</strong>ということです。できれば通信を行うコンピューターがどちらもTCP BBRに対応したカーネルにアップグレードしていることが望ましいのですが、OSのアップグレードサイクルを考えると、どれほど少なく見積もっても普及には数年かかるでしょう。</p>

<p>その点QUICはUDPの上で構築されている。プロトコルの処理はユーザーランドで行われるので、デプロイするのにOSのアップグレードなどを伴いません。プロトコルのバージョンアップも、機能追加も比較的簡単だと考えられます。将来的にHTTPだけでなくDNSやWebRTCなどでQUICが利用されることも検討されています。</p>

<p><b class="speaker siraisi">白石:</b> それが、「<strong>QUICはプラットフォームになりうる</strong>」という先程の言葉の意味ですね。</p>

<p><b class="speaker ohtsu">大津:</b> はい。ただ、QUICも実際には良いことばかりではありません。「QUICを無効にしたらChromeが軽くなった」などのノウハウが最近巷に広まってきています（※）。さきほどUDPの透過性の良さについて話しましたがやはり完全に透過ではなく、これも中間経路での問題が出てきている現象だと見られています。</p>

<p><small>
※参考: 「<a href="http://tanweb.net/2017/07/11/15417/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">最近 Chrome が「重くなった・ひっかかる」と感じたら試してみてほしいこと (Tanweb.net)</a>」
</small></p>

<p><b class="speaker siraisi">白石:</b> やはり、ネットワークプロトコルのデプロイって難しいんですね…。ただ、QUICが持つ素晴らしい可能性についても、よくわかりました。</p>

<p>本日は、実際の大規模なHTTPS &amp; HTTP/2への移行経験から新しいWebプロトコルのお話まで聞けて、大変勉強になりました！
どうもありがとうございました。</p>
]]></content:encoded>
		
		<series:name><![CDATA[HTML5 Conference 2017特集]]></series:name>
	</item>
		<item>
		<title>「最近のWebパフォーマンス改善について知っておきたいコト」についてあほむに聞いてきた</title>
		<link>/shumpei-shiraishi/24156/</link>
		<pubDate>Mon, 11 Sep 2017 01:00:23 +0000</pubDate>
		<dc:creator><![CDATA[白石 俊平]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[システム開発]]></category>
		<category><![CDATA[サイト制作]]></category>
		<category><![CDATA[Webパフォーマンス]]></category>
		<category><![CDATA[http2]]></category>
		<category><![CDATA[サイバーエージェント]]></category>

		<guid isPermaLink="false">/?p=24156</guid>
		<description><![CDATA[連載： HTML5 Conference 2017特集 (3)こんにちは、編集長の白石です。 この記事は、9月24日に開催されるHTML5 Conference 2017に登壇するエキスパートに、予定しているセッションの...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/html5-conf2017/" class="series-457" title="HTML5 Conference 2017特集" data-wpel-link="internal">HTML5 Conference 2017特集</a> (3)</div><p>こんにちは、編集長の白石です。</p>

<p>この記事は、9月24日に開催される<a href="http://events.html5j.org/conference/2017/9/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">HTML5 Conference 2017</a>に登壇するエキスパートに、予定しているセッションのトピックを中心に、いろいろ伺ったものです。セッションの内容をより深く理解する手助けになるだけでなく、本記事単体でも面白く読んでいただけることを目指しています。</p>

<p>今回お話を伺ったのは、株式会社サイバーエージェントにお勤めの佐藤歩さんです（ネット上では「あほむ」「ahomu」のIDで有名）。
（プロフィールは<a href="http://events.html5j.org/conference/2017/9/speaker/index.html#ahomu" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">こちら</a>）</p>

<p><img src="/wp-content/uploads/2017/09/6ed2d7e1dc76c5d83a54be2cc27ba479.jpg" alt="" width="640" height="412" class="alignnone size-full wp-image-24174" srcset="/wp-content/uploads/2017/09/6ed2d7e1dc76c5d83a54be2cc27ba479.jpg 640w, /wp-content/uploads/2017/09/6ed2d7e1dc76c5d83a54be2cc27ba479-300x193.jpg 300w, /wp-content/uploads/2017/09/6ed2d7e1dc76c5d83a54be2cc27ba479-207x133.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>あほむさんのセッションは「最近のWebパフォーマンス改善について知っておきたいコト」（ホール 13:20-14:00）です。
（現在<a href="https://html5j.connpass.com/event/64992/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">HTML5 Conference 2017</a>は定員オーバーの状態ですが、無料イベントということもあってキャンセルも多めに出るらしいので、あきらめずにキャンセル待ちすることをお勧めします！）</p>

<h2>パフォーマンスはなぜ重要か？を違う切り口から伝える</h2>

<p><b class="speaker siraisi">白石:</b> Webパフォーマンスについて、<a href="http://events.html5j.org/conference/2017/9/session/#h2" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">「ベーシックな話を少々と、最近の動向」をお話されるということですね</a>。</p>

<p><b class="speaker ahomu">あほむ:</b> はい、そうですね。まあ、まだセッションの内容はほとんど固まっていないので、当日は全然違った話をすることになるかもしれないのですが。</p>

<p>普通パフォーマンスに関する「ベーシックな話」というと、「なぜパフォーマンス改善は重要か」ということを語られることが多いと思うんです。でも、「パフォーマンスが重要」というのは、もうエンジニアには広く認識されているんですよね。</p>

<p>足りないのは、<strong>パフォーマンス改善を「開発者の自己満足」で終わらせない</strong>ことなんじゃないかと。パフォーマンス改善が、自社のビジネスにどう寄与するのか。そこを考えないと、意味のないパフォーマンス改善を行ってしまう恐れもあるし、社内の理解も得られない。</p>

<p>「パフォーマンスは重要である」というメッセージを、そういう観点からも伝えたい気がします。それも他社の事例とか一般論から語るんじゃなくて、私自身が遭遇した実体験などを踏まえて語りたいな…と思ってます。</p>

<p><b class="speaker siraisi">白石:</b> それは面白そうですね！具体的には、どんな実体験になりますか？</p>

<p><b class="speaker ahomu">あほむ:</b> 例えば、弊社のサービスってSNSでWebページが拡散されることが、非常に大きな比重を占めているんです。つまり、TwitterやFacebookのアプリ上で、WebViewでページを表示されることがすごく多いんです。そうなると、実は<strong>ブラウザのキャッシュにすら期待できないことが多い</strong>。弊社のサービスはiOSのユーザーが多いのでなおさらです（※）。</p>

<p>とはいえ、<strong>SNSを通じてたまたま遭遇した、っていう千載一遇のチャンスは活かさなくてはならない</strong>。そういう限定された環境でも最高のUXを実現するため、最大のパフォーマンスを発揮するにはどうしたらよいかを常に試行錯誤しているんです。</p>

<p><b class="speaker siraisi">白石:</b> なるほど。確かにそれは、パフォーマンスが非常に重要なシチュエーションと言えそうです。</p>

<p><b class="speaker ahomu">あほむ:</b> こういう例を含めていろいろ紹介できるといいかもしれません。URLさえあればどこからでもアクセス可能というのはWebの利点ですが、要はどんな環境で見られるかわからないということです。だから、Webのパフォーマンス改善には終わりがないし、少しでもその助けになるよう、常に新しいアイデアや技術が考案されています。そういう技術のうち、比較的新しくて、活用しがいのあるテクニックや仕様について、いろいろご紹介できればと思っています。</p>

<p><small>
※弊社のサービスはiOSのユーザーが多いのでなおさら…Androidであれば、Chrome Custom Tabという仕組みでメインブラウザ（Chrome）とキャッシュなどのリソースが共有されることも期待できる。iOSは、Chrome Custom Tabに近いSafari View Controllerという仕組みがあるが、あまり利用されていない。
</small></p>

<p><img src="/wp-content/uploads/2017/09/520562370d1f74af395a1fd9555160cd.jpg" alt="" width="640" height="427" class="alignnone size-full wp-image-24176" srcset="/wp-content/uploads/2017/09/520562370d1f74af395a1fd9555160cd.jpg 640w, /wp-content/uploads/2017/09/520562370d1f74af395a1fd9555160cd-300x200.jpg 300w, /wp-content/uploads/2017/09/520562370d1f74af395a1fd9555160cd-207x138.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<h2>ページロードパフォーマンスの改善テクニック</h2>

<p><b class="speaker siraisi">白石:</b> では、パフォーマンスを改善していくテクニックや仕様をいくつかご紹介いただけますか？</p>

<p><b class="speaker ahomu">あほむ:</b> Webパフォーマンスを考える際には、やはりページロード (ページの読み込み速度)と ランタイム （ページ実行中のパフォーマンス）に分けて考えるのが王道です。ページロードの改善については、<strong>最近だとHTTP/2の話が中心になる</strong>と思います。</p>

<p><b class="speaker siraisi">白石:</b> なるほど、御社のサービスでは、HTTP/2対応はもうかなり進められている感じなのですか？</p>

<p><b class="speaker ahomu">あほむ:</b> はい。できるところからHTTP/2にしていくというアプローチで、現在は多くのサービスがHTTP/2を利用して動いています。</p>

<p><b class="speaker siraisi">白石:</b> 実際にHTTP/2に対応してみていかがですか？苦労した点とかはありましたか？</p>

<p><b class="speaker ahomu">あほむ:</b> 具体的な切り替え作業については、インフラの専門チームが実施してくれるので、あくまで開発側からの意見になりますが…<strong>ほとんど苦労していることはないですね</strong>。</p>

<p><b class="speaker siraisi">白石:</b> おお、本当ですか。それは素晴らしい。</p>

<p><b class="speaker ahomu">あほむ:</b> はい、HTTP/2に切り替えても、開発への影響はほとんどなかったという点はとても重要ですね。アプリケーションとネットワークで、レイヤーが違うから当然といえば当然なのですが、やはり実際に経験してみると、そのありがたさが実感できます。トレードオフがほとんどないにも関わらず、パフォーマンスの向上が見込めるのですから。</p>

<p><b class="speaker siraisi">白石:</b> でも、HTTP/2に切り替えたことで、本当にパフォーマンスアップするのか、懐疑的な意見も目にしたことがあります。実際のところどうなんでしょうか？</p>

<p><b class="speaker ahomu">あほむ:</b> うーん…実際のところ、それはありますね。<strong>HTTP/2にしただけだと、体感的に良くなったっていう実感があまりないのは、正直なところです(笑)。</strong></p>

<p><img src="/wp-content/uploads/2017/09/fb8e33c766398453904ac50859d6bf89.jpg" alt="" width="640" height="417" class="alignnone size-full wp-image-24177" srcset="/wp-content/uploads/2017/09/fb8e33c766398453904ac50859d6bf89.jpg 640w, /wp-content/uploads/2017/09/fb8e33c766398453904ac50859d6bf89-300x195.jpg 300w, /wp-content/uploads/2017/09/fb8e33c766398453904ac50859d6bf89-207x135.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><b class="speaker siraisi">白石:</b> それも正直な意見として、貴重だと思います(笑)。</p>

<p><b class="speaker ahomu">あほむ:</b> 例えばHTTP/2でヘッダ圧縮されてデータ転送量が多少減ったとしても、アプリケーションで扱うデータが最適化されてなかったら、誤差みたいなレベルになってしまいますからね。HTTP/2によるパフォーマンス向上は、確実に効いているとは思います。ですが、実際のサービスでは、常に別のところにパフォーマンスのボトルネックが潜んでいて、効果のほどが見えにくいんですよね。</p>

<p><b class="speaker siraisi">白石:</b> 他には、ページロードの最適化で知っておいたほうがいいテクニックとかありますか？</p>

<p><b class="speaker ahomu">あほむ:</b> ほかには、コンテンツの圧縮に<a href="https://github.com/google/zopfli" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Zopfli</a>や<a href="https://github.com/google/brotli" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Brotli</a>を利用していますね。他にはResource Hintsなども使っているので、お話したいですね。</p>

<p><span style="font-size: 80%;">※参考記事：<a href="https://developers.cyberagent.co.jp/blog/archives/5975/" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">FRESH! Web パフォーマンス改善 〜サーバサイド編〜</a></span></p>

<p><b class="speaker siraisi">白石:</b> Zopfli…？そんな圧縮形式があるんですか？</p>

<p><b class="speaker ahomu">あほむ:</b> はい、ZopfliもBrotliも、どちらもGoogleが開発した圧縮形式です。</p>

<p>Zopfliは、圧縮の速度は遅いですが、そのかわりに圧縮効率は非常に良い。そしてgzipとの互換性があるので、gzipに対応したブラウザであればだいたい扱えるという大きな利点があります。</p>

<p>Brotliは、gzipとの互換性はありませんが、非常に効率のよい圧縮アルゴリズムです。こちらは現在のところ、Chrome, Firefox, Edgeでのみ利用可能です。</p>

<p><b class="speaker siraisi">白石:</b> <a href="https://www.w3.org/TR/resource-hints/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Resource Hints</a>というのはどういうものですか？</p>

<p><b class="speaker ahomu">あほむ:</b> 利用するリソースを先読みするヒントをブラウザに与えるための仕様です。これを利用すると、現在のWebページに含まれていないリソースであっても、ブラウザに先読みさせることができます。dns-prefetch (名前解決を実行しておく）, preconnect （サーバ接続を行っておく）, prefetch （リソースのフェッチを実行しておく）, prerender （ページのレンダリングをバックグラウンドで実行しておく）といったタイプの先読みが可能です。
<small>
（筆者注: <a href="https://blog.jxck.io/entries/2016-02-11/resource-hints.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Jxck</a>さんのブログで詳しく解説されています）。
</small></p>

<h2>ランタイムパフォーマンスの改善テクニック</h2>

<p><b class="speaker siraisi">白石:</b> ランタイム （アプリケーション実行時）のパフォーマンスを向上させるために使用している技術にはどんなものがありますか？</p>

<p><b class="speaker ahomu">あほむ:</b> <a href="https://github.com/w3c/IntersectionObserver" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Intersection Observer</a>や<a href="https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Passive Event Listeners</a>は利用しがいがあると思います。</p>

<p><strong>Intersection Observer</strong>というのは、要素同士の領域が交差したり、もしくはビューポート（ユーザーに見えている範囲）に要素が入ったかどうかなどを検出できるAPIです（筆者注: Intersectionとは「交差」の意味）。これを利用すると、ビューポート外で行われる処理を抑制したり、遅延させたりすることが可能になるので、パフォーマンス向上には非常に効果的です。わかりやすいのは、img要素がビューポート内に現れるまで画像の読み込みを遅延させる…などですね。</p>

<p><strong>Passive Event Listeners</strong>というのは、UIイベントが <code>preventDefault()</code> （デフォルトの動作をキャンセルする）されないことを保証するための仕組みです。</p>

<p>スクロールイベントなどは、 <code>preventDefault()</code> を行うことでブラウザのスクロール処理そのものをキャンセルすることができます。逆に言うと、ブラウザはスクロールがキャンセルされる可能性を考えると、イベントハンドラを実行してから実際のスクロールを行わなくてはならない。だから、イベントハンドラの実行に時間がかかったりすると、スクロール処理が詰まってしまうんです。これが<strong>スクロールジャンク</strong>と呼ばれる現象です。</p>

<p>ただ、実際に <code>preventDefault()</code> でスクロール処理を止めたいというケースは多くはありません。なので、「このイベントハンドラはpreventDefault()を呼ばないよ」ということをブラウザに伝える手段として用意されたのがPassive Event Listenersです。</p>

<p><small>
（筆者注: これらも、Jxckさんのブログに詳しい解説がある。<a href="https://blog.jxck.io/entries/2016-06-25/intersection-observer.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Intersection Observer</a> <a href="https://blog.jxck.io/entries/2016-06-09/passive-event-listeners.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Passive Event Listeners</a>）
</small></p>

<p><img src="/wp-content/uploads/2017/09/8934352103f7dcdc633ff237e8d88b63.jpg" alt="" width="640" height="411" class="alignnone size-full wp-image-24178" srcset="/wp-content/uploads/2017/09/8934352103f7dcdc633ff237e8d88b63.jpg 640w, /wp-content/uploads/2017/09/8934352103f7dcdc633ff237e8d88b63-300x193.jpg 300w, /wp-content/uploads/2017/09/8934352103f7dcdc633ff237e8d88b63-207x133.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p><b class="speaker siraisi">白石:</b> 今おっしゃったIntersection ObserverやPassive Event Listenersは、全てのブラウザで動くわけではありませんよね？</p>

<p><b class="speaker ahomu">あほむ:</b> はい。なので、動作しないブラウザ用にFeature Detectionで分岐を設けたり、Polyfillも活用しています。</p>

<p><b class="speaker siraisi">白石:</b> なるほど。ただ、最初にお聞きした例だと「SNSで拡散されたページの最適化に注力している」というお話でした。<strong>こういうランタイム系のパフォーマンス改善って、SPA (Single Page Application) ではない通常のランディングページやメディアのサイトなどでも重要なのでしょうか？</strong></p>

<p><b class="speaker ahomu">あほむ:</b> そう思います。先程も申し上げたように、SNSを通じてサイトにアクセスしてくれるのって、ユーザーと接触できる千載一遇のチャンスなわけです。そこからモバイルアプリへの誘導を行うこともできる。なので、そういう千載一遇のチャンスで少しでも機会損失を起こさないように、入念にパフォーマンスをチューニングするのは非常に重要です。</p>

<p>個人的には、jQueryを使った普通のWebサイトこそ、ランタイムのパフォーマンスにもっと気を使うべきだし、できるとも思います。jQueryのプラグインが最新の仕様に追従すれば、プラグインをアップデートするだけで恩恵を得られるわけですから。</p>

<p>ただ逆に、プラグイン側が対応してくれなかったりすると、プラグインの中に手を入れるわけにもいかず、対応が進まないということの裏返しでもありますけどね…悩ましい問題です。</p>

<h2>パフォーマンス改善を「開発者の自己満足」で終わらせないために</h2>

<p><b class="speaker siraisi">白石:</b> これまでご紹介いただいた様々なテクニックですが、これらを活用してパフォーマンスを実際に改善していくのは、実際には骨の折れる作業だと思います。そうした、パフォーマンス改善作業に投下するコストと、それによって得られるリターンについては、どのようにお考えでしょうか？</p>

<p><b class="speaker ahomu">あほむ:</b> はい、おっしゃるとおり、これらのテクニックをただ使って、目に見えない部分でパフォーマンスを改善しても、単なる開発者の自己満足に終わってしまいます。それを避けるためには、<strong>まずは正しく計測することと、それがビジネス上のKPIとどう関連付けているかを検証していくこと</strong>が必要です。</p>

<p>まず計測についてですが、クライアントサイドのパフォーマンスを計測する指標は、現在も様々なものが考案され、利用可能です。</p>

<p>例えば<strong>First Paint</strong>。Webページの描画が開始されたタイミングを表す指標で、ChromeやEdgeでは非標準のAPIから値を得ることができます。</p>

<p>ただ、First Paintだけでは、コンテンツの表示が完了するまでの速度などについてはわかりません。最も重要なのは、ユーザーに見える範囲、つまりビューポートの描画がいつ完了するかです。</p>

<p><img src="/wp-content/uploads/2017/09/d49206c651f16b4bd779417fc8ee95c3.jpg" alt="" width="640" height="419" class="alignnone size-full wp-image-24180" srcset="/wp-content/uploads/2017/09/d49206c651f16b4bd779417fc8ee95c3.jpg 640w, /wp-content/uploads/2017/09/d49206c651f16b4bd779417fc8ee95c3-300x196.jpg 300w, /wp-content/uploads/2017/09/d49206c651f16b4bd779417fc8ee95c3-207x136.jpg 207w" sizes="(max-width: 640px) 100vw, 640px" /></p>

<p>そういう観点での指標としては<strong>Speed Index</strong>があります。Speed Indexを計測する基本的な方法としては、描画中の画面をキャプチャして、最終的な表示結果が得られるまでにどれくらいかかるかを測るというものです。弊社のサービスでは、ページビューや直帰率といったKPIとSpeed Indexの間に相関関係が認められたため、Speed Indexを中心にパフォーマンス改善を行いました。</p>

<p>さらにこうした指標は実際のユーザーの環境で得られた値を一定量集めることも大事なので、集計結果をGoogle Analyticsに送信しています。そうすることで、GAを使いなれたプロに分析をお任せすることもできますからね。</p>

<p>そうした経緯は<a href="https://developers.cyberagent.co.jp/blog/archives/9540/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">弊社技術ブログの記事</a>に詳しく書かれています。</p>

<p><b class="speaker siraisi">白石:</b> なるほど…パフォーマンス改善がビジネスに寄与するという道筋を立てることで、パフォーマンス改善が業務として意味にあるものになるわけですね。</p>

<p><b class="speaker ahomu">あほむ:</b> そうですね。パフォーマンス改善とビジネスが両輪としてうまく回るためにも、やはり様々なパフォーマンス指標や計測が大事になってきます。</p>

<p>指標は他にも<strong>First Contentful Paint</strong> （コンテンツが表示され始めた時）や <strong>First Meaningful Paint</strong> （ユーザーに意味のある表示になったとき）など様々なものが考案され、実装も行われています。よければそういう話をまとめた<a href="https://havelog.ayumusato.com/develop/performance/e744-performance_metrics.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">私のブログ記事</a>も見てみてください。</p>

<p><b class="speaker siraisi">白石:</b> なるほど、今日は貴重なお話をお聞かせいただきありがとうございました！HTML5 Conferenceでのセッションも楽しみにしています。</p>
]]></content:encoded>
		
		<series:name><![CDATA[HTML5 Conference 2017特集]]></series:name>
	</item>
		<item>
		<title>React VRでここまでできる！VRでジオラマを作ろう</title>
		<link>/karad5/23960/</link>
		<pubDate>Mon, 31 Jul 2017 01:30:45 +0000</pubDate>
		<dc:creator><![CDATA[原一浩]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[React]]></category>
		<category><![CDATA[React VR]]></category>
		<category><![CDATA[VR]]></category>

		<guid isPermaLink="false">/?p=23960</guid>
		<description><![CDATA[連載： React VR (4)前回、3Dプリミティブオブジェクトを使って、レイアウトやライティングの仕方について一通り試しました。前回扱わなかったコンポーネントに、3DモデルのためのコンポーネントModelがあります。...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/react-vr/" class="series-453" title="React VR" data-wpel-link="internal">React VR</a> (4)</div><div id="attachment_23961" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/HelloDiorama-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23961" srcset="/wp-content/uploads/2017/07/HelloDiorama.png 640w, /wp-content/uploads/2017/07/HelloDiorama-300x162.png 300w, /wp-content/uploads/2017/07/HelloDiorama-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">今回は、こんなVRジオラマをつくるぞ！</p></div>

<p>前回、3Dプリミティブオブジェクトを使って、レイアウトやライティングの仕方について一通り試しました。前回扱わなかったコンポーネントに、3Dモデルのためのコンポーネント<code>Model</code>があります。<code>Model</code>コンポーネントを使うと「obj」形式の3Dモデリングデータを読み込み、VR空間に配置することができます。</p>

<p>3Dのモデリングデータを使うと、リアルな物体だったり、複雑な形状を持ったオブジェクトを自由にVR上で扱えるため、VR空間における表現力が飛躍的に高まります。実際VRコンテンツを作る際に使うのは<code>Box</code>や<code>Cylinder</code>ではなく、<code>Model</code>コンポーネントになるでしょう。</p>

<p>今回は、3Dのモデリングデータを読み込み、ジオラマを作ってみましょう。子どもの頃、作ったプラモデルに顔を近づけて遊んだ経験はないでしょうか。VRでは、巨大な物体を目の前に表示させるのもお手のものです。</p>

<h2>新規プロジェクトの作成</h2>

<p>既に本連載の読者であれば何度か行ってきていることですが、今回もサンプルを作るにあたって新規プロジェクトを作成し、プロジェクトディレクトリへ移動します。<code>HelloDiorama</code>というプロジェクト名で進めることにします。</p>

<p></p><pre class="crayon-plain-tag">$ react-vr init HelloDiorama
$ cd HelloDiorama</pre><p></p>

<p>ジオラマに必要なものは何でしょうか? 一つは飾る対象物です。これはロボットなのかもしれないし、戦車かもしれないし、船かもしれません。3Dモデリングデータさえあれば、そしてそれをReact VRで読み込めさえすれば、なんでもジオラマにすることができます。</p>

<p>ちなみに「React VRで読み込めさえすれば」と書いているのは、Webで公開されている3Dモデリングデータの中には何故か表示できないものがあります。表示はできるけど変な形状になったりするものもあります。これはきっと時間と共に解決されていくタイプのものでしょう。気になることがあればReact VRのGitHubリポジトリでIssueを立てるとよいです。</p>

<p>続いてジオラマに必要なもう一つのものは何でしょう? それは雰囲気を与えてくれる背景です。緻密なモデルをさらに引き立ててくれる背景は、ロボットなら宇宙船の内部かもしれないし、船なら海上かもしれません。こちら背景は、今回は3Dプリミティブオブジェクトを利用してそれっぽいものを作ってみます。</p>

<h2>用意するもの</h2>

<p>ジオラマコンテンツを作るにあたって、用意するものは以下となりました。</p>

<ul>
<li>配置する対象物としての3Dモデリングデータ</li>
<li>背景の壁と床のテクスチャ</li>
</ul>

<p>まずは、配置する対象物としての3Dモデリングデータから用意しましょう。</p>

<div id="attachment_23962" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/GAZ-AA-640x350.png" alt="" width="640" height="350" class="size-large wp-image-23962" srcset="/wp-content/uploads/2017/07/GAZ-AA.png 640w, /wp-content/uploads/2017/07/GAZ-AA-300x164.png 300w, /wp-content/uploads/2017/07/GAZ-AA-207x113.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">1930年代に使われたソ連製のトラックのモデルデータ</p></div>

<p>今回ジオラマとして、シーンに配置するのは、<a href="https://ja.wikipedia.org/wiki/GAZ-AA" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">GAZ-AA</a>という1930年代に使われたソ連製のトラックにしてみました。筆者は、このトラックを好きだったわけではないですが、様々な3Dモデルを探す中でふとこのトラックを見かけ、素朴な中にも車両全面に漂う気品を魅力に感じ、採用した次第です。</p>

<p>このトラックは、ポリゴン数が4,380と、そこそこ複雑な形状をしており、テクスチャなどを含んでいてなかなかにリアリティがあります。</p>

<p>下記より、objフォーマット形式のものをダウンロードしましょう。もし他の3Dデータで試す場合、ライセンスについてチェックしておきましょう。</p>

<ul>
<li><a href="https://www.cgtrader.com/free-3d-models/vehicle/truck/gaz-aa-furgon-bread" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">GAZ- AA furgon-Bread free VR / AR / low-poly 3D Model MAX OBJ 3DS FBX MTL</a></li>
</ul>

<p>ちなみに、上記ダウンロードサイトでは、ユーザー登録が必要です。なので、ほかのものを用意できる人は好きな3Dデータを利用してOKです。「gaz-aa_bread OBJ.zip」をダウンロード、解凍したら、下記のディレクトリにそれぞれ配置します。</p>

<ul>
<li>static_assets/gaz_aa/gaz-aa_bread.mtl</li>
<li>static_assets/gaz_aa/gaz-aa_bread.obj</li>
<li>static_assets/gaz_aa/gaz-aa_bread_cabin.jpg</li>
<li>static_assets/gaz_aa/gaz-aa_bread_detail.jpg</li>
<li>static_assets/gaz_aa/gaz-aa_bread_frame.jpg</li>
<li>static_assets/gaz_aa/gaz-aa_bread_furgon.jpg</li>
<li>static_assets/gaz_aa/gaz-aa_bread_wheel.jpg</li>
<li>static_assets/gaz_aa/gaz-aa_bread_wing.jpg</li>
</ul>

<p>上記ファイルのうち、実は「gaz-aa_bread.mtl」については変更する必要があります。</p>

<p>テキストエディタなどでファイルを開き、「D:\Program Files\Autodesk\3ds Max 2009\scenes\GAZ-AA free models\gaz-aa_bread_3ds_max&#42;<strong>.jpg」となっているところを「</strong>*.jpg」に書き換えましょう。これはきっと作ったときそのままのローカルのパスが入ってしまったのですね。公開する際の要注意ポイントと言えそうです。</p>

<p>ジオラマの背景に必要な素材は、角となる2面分の壁用のテクスチャと、床に使うテクスチャです。前回使った<code>Pano</code>コンポーネントで、6面にテクスチャを貼り、部屋状にしてしまうこともできますが、それだとリアルな空間になりすぎ、ジオラマっぽくなくなるからです。3面しか壁を用意しないことで、後ろには漆黒の空間が広がる感じになり、なんだか超現実的な世界になります。</p>

<div id="attachment_23963" style="width: 310px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/wall-300x169.jpg" alt="" width="300" height="169" class="size-medium wp-image-23963" srcset="/wp-content/uploads/2017/07/wall-300x169.jpg 300w, /wp-content/uploads/2017/07/wall.jpg 640w, /wp-content/uploads/2017/07/wall-207x116.jpg 207w" sizes="(max-width: 300px) 100vw, 300px" /><p class="wp-caption-text">背景の壁のテクスチャ</p></div>

<div id="attachment_23964" style="width: 310px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/floor-300x169.jpg" alt="" width="300" height="169" class="size-medium wp-image-23964" srcset="/wp-content/uploads/2017/07/floor-300x169.jpg 300w, /wp-content/uploads/2017/07/floor.jpg 640w, /wp-content/uploads/2017/07/floor-207x116.jpg 207w" sizes="(max-width: 300px) 100vw, 300px" /><p class="wp-caption-text">床のテクスチャ</p></div>

<p>壁と床のテクスチャは以下からダウンロードしてください。</p>

<ul>
<li><a href="https://html5experts.jp/wp-content/uploads/2017/07/diorama.zip" data-wpel-link="internal">diorama</a></li>
</ul>

<p>ちなみに、壁と床のテクスチャは、僕がそのへんで適当に撮ってきたものなので、フリーでお使いいただいて構いません。</p>

<p>ダウンロードしたら、「プロジェクトディレクトリ/static_assets/diorama」以下に「floor.jpg」と「wall.jpg」を配置しましょう。</p>

<h2>STEP 1. まずは、ジオラマのベースづくりから</h2>

<p>早速トラックを配置したいと、はやる気持ちを抑えてまずはジオラマのベースとなる背景の壁と床を作るところから始めましょう。床は、1000 x 1000の大きさを持った板を想定しました。これは、<code>Pano</code>コンポーネントで作った空間と同じ大きさとなります。そして、奥の壁は床から500の高さを持つ平面です。これにテクスチャをつけることで、リアリティを持たせます。では、具体的な作業をしましょう。</p>

<p>「index.vr.js」の<code>View</code>の中を一旦空にし、下記のように修正します。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
              &lt;View
                      style={{
                        transform: [
                          {rotateY: -20},
                        ]
                      }}&gt;
                &lt;Plane
                        dimWidth={1000}
                        dimHeight={500}
                        style={{
                          transform: [
                            {translate: [-500, 220, 0]},
                            {rotateY: 90},
                          ],
                        }}
                        texture={asset('diorama/wall.jpg')}
                /&gt;
                &lt;Plane
                        dimWidth={1000}
                        dimHeight={500}
                        style={{
                          transform: [
                            {translate: [0, 220, -500]},
                          ],
                        }}
                        texture={asset('diorama/wall.jpg')}
                /&gt;
                &lt;Plane
                        dimWidth={1000}
                        dimHeight={1000}
                        style={{
                          transform: [
                            {translate: [0, -22, 0]},
                            {rotateX: -90},
                          ],
                        }}
                        texture={asset('diorama/floor.jpg')}
                /&gt;
              &lt;/View&gt;
            &lt;/View&gt;</pre><p></p>

<p>それと、importも変更しておきましょう。この先に使う<code>Model</code>コンポーネントやライティング関係のコンポーネントも加えておきます。</p>

<p></p><pre class="crayon-plain-tag">import {
  AppRegistry,
  asset,
  View,
  Plane,
  Model,
  DirectionalLight,
  PointLight,
  AmbientLight,
} from 'react-vr';</pre><p></p>

<p><code>View</code>コンポーネントが入れ子になっているのは、内側の<code>View</code>は、ジオラマの背景セットで、セット全体を変形させたい場合はこのように入れ子にしておくと、壁や床を一つの塊として扱えます。ここではジオラマのセット全体をちょっと回転させています。というのも、最初に表示したときに部屋の中央ではなく、部屋の角を見せたいためです。</p>

<p>ジオラマのセット自体を回転させずに、カメラを回転させるという表現方法もありますが、普通ジオラマというのは、インテリアの側面もあり、一番かっこいいポジションで飾るものだと思います。そこで、<code>View</code>自体をY軸に対して-20度回転させました。</p>

<p>さらに細部を見ていきましょう。3つの<code>Plane</code>が、内側の<code>View</code>コンポーネント内に配置されていますが、先頭2つの<code>Plane</code>コンポーネントは壁として配置してあります。位置を遠くに置いたのと、Y軸方向に90度回転させて垂直にそれぞれのコンポーネントが交わるようにしています。</p>

<p><code>Plane</code>コンポーネントに関わらず、3Dプリミティブコンポーネントは、テクスチャを設定することができます。テクスチャは<code>texture</code>属性で設定します。</p>

<p>ここでは<code>texture</code>属性に、「diorama/wall.jpg」を指定しました。これによりのっぺりとした壁が質感のある壁となりました。ちなみに、この壁は近くの公園の壁を撮影したものです。</p>

<p>一番最後の<code>Plane</code>は、床として配置しています。X軸方向に-90度回転させ、テクスチャを貼りました。これは海に行った時の砂岩の岩肌です。深い意味があるわけではないですが、オフロードっぽい印象になる写真が見つからなかったので、こちらを採用しました。</p>

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

<p>を実行し、ブラウザでURLを開いてみましょう。ただし、こんどは「http://localhost:8081/vr/?hotreload」で開いてみてください。「?hotreload」を付けてブラウザから開くと、ホットリロードが可能になります。これで、エディタで編集したコンテンツが自動でブラウザ側に反映されるようになります。</p>

<div id="attachment_23966" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/HelloDiorama_base-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23966" srcset="/wp-content/uploads/2017/07/HelloDiorama_base.png 640w, /wp-content/uploads/2017/07/HelloDiorama_base-300x162.png 300w, /wp-content/uploads/2017/07/HelloDiorama_base-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">配置した背景</p></div>

<p>3方向のみ<code>Plane</code>を配置しただけの簡素なジオラマセットですが、VRで角のほうを見るとなかなかどうして迫力がありますね。</p>

<h2>STEP 2. 3Dモデリングデータを配置しよう!</h2>

<p>続いて、お待ちかねの3Dモデルの読み込みです。3Dモデリングデータの読み込みには、<code>Model</code>コンポーネントを使います。<code>Model</code>コンポーネントには、<code>source</code>属性を記述することができます。渡す内容は、<code>obj</code>と<code>mtl</code>というキーを持ったオブジェクトで、それぞれobj形式のファイルとmtl形式のファイルへのパスを渡します。</p>

<p>今回であれば、「配置するモデリングデータ」で保存しておいた「static_assets/gaz_aa」以下にあるobjファイルとmtlファイルが対象になります。</p>

<p><code>Model</code>コンポーネントは、「index.vr.js」の入れ子の内側の<code>View</code>以下に配置します。サイズは小さめにし、位置調整と<code>rotateY</code>プロパティを修正して、若干の回転を加えます。これは、ちょうど左前に向いた形がきれいだからです。コードは下記のようになります。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
              &lt;View
                      style={{
                        transform: [
                          {rotateY: -20},
                        ]
                      }}&gt;
                &lt;Model
                        style={{
                          transform: [
                            {translate: [-30, -20, -110]},
                            {scale: 0.03},
                            {rotateY: 70},
                          ],
                        }}
                        source={{
                          obj: asset('gaz_aa/gaz-aa_bread.obj'),
                          mtl: asset('gaz_aa/gaz-aa_bread.mtl')
                        }}
                        lit={true}
                /&gt;
                &lt;Plane ... /&gt;
                &lt;Plane ... /&gt;
                &lt;Plane ... /&gt;
              &lt;/View&gt;
            &lt;/View&gt;</pre><p></p>

<p>これで、ブラウザをリロードしてみてください。3Dモデルが表示されるはずです。</p>

<div id="attachment_23967" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/HelloDiorama_black-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23967" srcset="/wp-content/uploads/2017/07/HelloDiorama_black.png 640w, /wp-content/uploads/2017/07/HelloDiorama_black-300x162.png 300w, /wp-content/uploads/2017/07/HelloDiorama_black-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">まだ光が当たっていないので真っ黒</p></div>

<p>ただし、真っ黒なシルエットになってしまっていますが。ということで、続いて光源を用意して、明るくしていきましょう。</p>

<h2>STEP 3. ライティングしてトラックを美しく!</h2>

<p>ライティングは、前回3Dプリミティブオブジェクトで遊んだ際に試したのを思い出してください。メインの明かり、部分的な明かり、ちょっとした調整です。今回も同じような感じで進めます。</p>

<p>実は、React VRで使われている3DライブラリのThree.js本体には、ライティングに関する様々なヘルパー機能が用意されています。例えば、照明の向き、範囲などを視覚的に表示して微調整をする機能などです。ただ、現時点のReact VRではもっと限定的なサポートとなっているのでそこまで細かくは扱いません。</p>

<p>「index.vr.js」に<code>DirectionalLight</code>と<code>PointLight</code>、<code>AmbientLight</code>コンポーネントを配置しました。これで、トラックが綺麗に表示されるでしょうか。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
              &lt;DirectionalLight
                      intensity={0.3}
                      style={{
                        color: 'white',
                        transform: [
                          {translate: [0, 0, 0]},
                          {rotateX: 45}]
                      }}/&gt;
              &lt;PointLight
                      intensity={0.5}
                      style={{
                        color: 'white',
                        transform: [{translate: [50, 20, -80]}]
                      }}/&gt;
              &lt;AmbientLight
                      intensity={0.8}/&gt;
              &lt;View ... /&gt;
            &lt;/View&gt;</pre><p></p>

<div id="attachment_23968" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/HelloDiorama_3d_model-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23968" srcset="/wp-content/uploads/2017/07/HelloDiorama_3d_model.png 640w, /wp-content/uploads/2017/07/HelloDiorama_3d_model-300x162.png 300w, /wp-content/uploads/2017/07/HelloDiorama_3d_model-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">トラックがちゃんと表示された！</p></div>

<p>ブラウザをリロードしてトラックを再表示してみましょう。明るくなったでしょうか。</p>

<h2>STEP 4. トラックをゆっくりと回転させてみる</h2>

<p>以上で一旦はジオラマは完成しましたと言ってもいいかもしれません。ただ、今まで物体を空間に置いてみて歯がゆかったのは、その物体の裏側がどうなっているのか、それが見えないということでした。ということで、アニメーションの練習がてらトラックを回転させてみましょう。</p>

<p>回転に関しては、ピッタリのサンプルが公式のリポジトリに用意されています。</p>

<ul>
<li><a href="https://github.com/facebook/react-vr/tree/master/Examples/ModelSample" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">react&#45;vr/Examples/ModelSample at master · facebook/react&#45;vr</a></li>
</ul>

<p>このサンプルを参考にトラックのアニメーションを作ってみます。ちょっとサンプルと異なるのは、Reactのコンポーネントとして作るというのと、細かなロジックを修正した点です。Reactコンポーネントとして、回転速度を定義する<code>speed</code>属性と、表示位置や大きさを定義する<code>style</code>属性を渡せるように作っておきましょう。「src/component/GazAa.js」として下記のように作成します。ちょっと長くなるので、細部の話は置いておいて、まずは一気に掲載してしまいます。</p>

<p></p><pre class="crayon-plain-tag">import React from 'react';
import {
  asset,
  View,
  Model,
} from 'react-vr';

export default class GazAa extends React.Component {

  constructor() {
    super();
    this.state = {
      rotation: 0
    };
  }

  componentDidMount() {
    this.rotate();
  }

  componentWillUnmount() {
    if (this.frameHandle) {
      cancelAnimationFrame(this.frameHandle);
      this.frameHandle = null;
    }
  }

  rotate(timestamp) {
    const delta = timestamp - this.lastUpdate || 0;
    this.setState({rotation: this.state.rotation + delta / this.props.speed});
    this.lastUpdate  = timestamp;
    this.frameHandle = requestAnimationFrame(this.rotate.bind(this));
  }

  render() {
    return (&lt;View style={this.props.style}&gt;
              &lt;Model
                      style={{
                        transform: [
                          {rotateY: this.state.rotation},
                        ]
                      }}
                      source={{
                        obj: asset('gaz_aa/gaz-aa_bread.obj'),
                        mtl: asset('gaz_aa/gaz-aa_bread.mtl')
                      }}
                      lit={true}
              /&gt;
            &lt;/View&gt;
    )
  }
}</pre><p></p>

<p>ポイントは、<code>GazAa</code>コンポーネントのローカルステートとそれを変更するためのrotate関数、そしてそこで使われている<code>requestAnimationFrame</code>関数と<code>cancelAnimationFrame</code>関数です。</p>

<p><code>GazAa</code>コンポーネントは、シーンに配置した瞬間、つまりコンポーネントがマウントされた時から回転を始めます。逆にコンポーネントをアンマウントすると回転をやめる処理をします。回転の状態はコンポーネントのローカルステートとして定義されている<code>rotation</code>です。</p>

<p><code>rotation</code>は、3Dモデルの<code>rotateY</code>としてY軸方向にどれだけ回転するかという値として使われることになります。その値をコントロールしているのが<code>rotate</code>関数です。<code>requestAnimationFrame</code>関数は、ブラウザの再描画のタイミングで<code>rotate</code>関数を呼び出すことになるので、呼び出すたびに前に呼び出された時間からの回転を<code>rotation</code>に反映していきます。<code>requestAnimationFrame</code>関数から返った値は、アニメーションをキャンセルするときに<code>cancelAnimationFrame</code>関数にて使われます。</p>

<p><code>requestAnimationFrame</code>関数について一つ知っておきたいことは、この関数はもともとブラウザに実装されていますが、ブラウザによってはサポートされていないことがあります。そこで、React VRでは、<code>requestAnimationFrame</code>関数のpolyfillとして用意されています。</p>

<p>これで大体の<code>GazAa</code>コンポーネントの仕組みが理解できたでしょうか。今はこういうスタイルでアニメーションを実現したりしますが、将来的にはもっと洗練されたアニメーション機構が用意されていくのだろうと推測します。</p>

<p>では、先ほど作った<code>GazAa</code>コンポーネントを使っていきましょう。「index.vr.js」で使うので、まずはインポートします。ファイルの先頭あたりにimport文を書きます。</p>

<p></p><pre class="crayon-plain-tag">import GazAa from './src/component/GazAa'</pre><p></p>

<p>続いて、入れ子になった<code>View</code>コンポーネントの内側に、<code>GazAa</code>コンポーネントを配置します。プロパティとしては、回転速度を定義する<code>speed</code>属性と、表示位置や大きさを定義する<code>style</code>属性を渡しています。これら属性は、<code>GazAa</code>コンポーネント内の<code>this.props.XXX</code>にて受け取ることが可能です。これらを記載したコードが以下になります。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
              &lt;DirectionalLight ... /&gt;
              &lt;PointLight ... /&gt;
              &lt;AmbientLight ... /&gt;
              &lt;View
                      style={{
                        transform: [
                          {rotateY: -20},
                        ]
                      }}&gt;
                {/* &lt;Model ... /&gt; */}
                &lt;GazAa speed={360}
                       style={{
                         transform: [
                           {translate: [-42, -20, -110]},
                           {scale: 0.03},
                         ],
                       }}/&gt;
                &lt;Plane ... /&gt;
                &lt;Plane ... /&gt;
                &lt;Plane ... /&gt;
              &lt;/View&gt;
            &lt;/View&gt;</pre><p></p>

<p>以上で、トラックが回転するジオラマの完成です。ブラウザをリロードして、じっくり見てみましょう！</p>

<div id="attachment_23961" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/HelloDiorama-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23961" srcset="/wp-content/uploads/2017/07/HelloDiorama.png 640w, /wp-content/uploads/2017/07/HelloDiorama-300x162.png 300w, /wp-content/uploads/2017/07/HelloDiorama-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">完成したVRジオラマ</p></div>

<p>もし興味があれば、<a href="https://html5experts.jp/karad5/23885/" data-wpel-link="internal">React VR×360度画像！Web上でパノラマVR表示を試す</a>を参考に、GearVRで眺めてみましょう。子供の頃叶わなかった、巨大サイズのジオラマを見ることができますよ。</p>
]]></content:encoded>
		
		<series:name><![CDATA[React VR]]></series:name>
	</item>
		<item>
		<title>Reactといえばコンポーネント！React VRの3Dプリミティブコンポーネントを探る、触る</title>
		<link>/karad5/23945/</link>
		<pubDate>Mon, 24 Jul 2017 01:00:05 +0000</pubDate>
		<dc:creator><![CDATA[原一浩]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[GearVR]]></category>
		<category><![CDATA[React VR]]></category>
		<category><![CDATA[WebVR]]></category>

		<guid isPermaLink="false">/?p=23945</guid>
		<description><![CDATA[連載： React VR (3)前回、React VRでパノラマ写真を見るというコンテンツを作成しました。 サンプルを試していただいた方は「なんか結構できたじゃん感」を満喫できたと思います。それもそのはず、360度写真の...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/react-vr/" class="series-453" title="React VR" data-wpel-link="internal">React VR</a> (3)</div><div id="attachment_23947" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_AmbientLight-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23947" srcset="/wp-content/uploads/2017/07/Hello3DObject2_AmbientLight.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_AmbientLight-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_AmbientLight-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">今回のサンプルの完成版。ライティングとかもやるぞ</p></div>

<p><a href="https://html5experts.jp/karad5/23885/" target="_blank" data-wpel-link="internal">前回</a>、React VRでパノラマ写真を見るというコンテンツを作成しました。<br />
サンプルを試していただいた方は「<strong>なんか結構できたじゃん感</strong>」を満喫できたと思います。それもそのはず、360度写真のみのコンテンツは、天球にパノラマ画像を貼り付けた時点で、目的の99%を達成できたといえるからです。ほとんど完成といっていい状態でしょう。</p>

<p>しかし、他のVRコンテンツを触ったことがある人間なら、少しもの足りなさを感じることと思います。一つは<strong>インタラクティブ性のなさ</strong>、そしてもう一つは<strong>モノの存在感のなさ</strong>です。</p>

<p>インタラクティブ性のなさは、イベント駆動型のVRコンテンツの作成というハードルが待っていますが、今回はそれはさておき、モノの存在感について書いていきます。</p>

<p>パノラマ画像だけで構成された世界は、「<strong>一見、目の前で展開されている感じなのに、触ることができないほど遠くに広がる世界</strong>」と言えます。目の前の芝生に近付いて触ることはできませんし、奥の人に近付くこともできません。</p>

<p>仮に頑張って、インタラクティブ性を高めて奥に進めるように作ったとしても、そこにあるのは<strong>拡大されて画素が粗くなった人のようなナニカ</strong>でしかありません。</p>

<p>VRのモノとしての存在を確固たるものにするために大事なことは、VR空間に実際にモノを置いてみるということになります。</p>

<p>ということで、今回はReact VRに用意されているコンポーネントのうち、モノとして置けるコンポーネント、3Dプリミティブについて扱っていきます。</p>

<h2>いろいろなタイプのReact VR Components</h2>

<p><a href="https://facebook.github.io/react-vr/docs/getting-started.html" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">公式ドキュメント</a>にあるReact VR Componentsの目次は下記のような構成になっています。</p>

<ul>
<li>AmbientLight</li>
<li>Box</li>
<li>LiveEnvCamera</li>
<li>Cylinder</li>
<li>CylindricalPanel</li>
<li>DirectionalLight</li>
<li>Model</li>
<li>Pano</li>
<li>Plane</li>
<li>PointLight</li>
<li>Scene</li>
<li>Sound</li>
<li>Sphere</li>
<li>SpotLight</li>
<li>Video</li>
<li>VideoControl</li>
<li>VideoPano</li>
<li>VrButton</li>
</ul>

<p>いろいろありますね。「<strong>あれ?、これだけしかないの?</strong>」という見方もあるかもしれません。主要なものを役割ごとにカテゴライズしてみましたので順に見ていきましょう。各種コンポーネントの実装コードに興味がある方は、<a href="https://github.com/facebook/react-vr/tree/master/ReactVR/js/Views" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">GitHubのReact VRリポジトリのViews以下</a>を見てみるとよいでしょう。</p>

<h3>空間を作るタイプのコンポーネント</h3>

<p>まず、チェックしておきたいのは空間を作るタイプのコンポーネントです。</p>

<ul>
<li>VideoPano</li>
<li>CylindricalPanel</li>
<li>Pano</li>
</ul>

<p><code>Pano</code>は、既に登場しましたが、360度写真をVR空間に貼り付けるタイプのコンポーネントです。</p>

<p><code>VideoPano</code>は、Panoと同様ですが、貼り付け可能コンテンツが360度動画となります。<code>CylindricalPanel</code>は、ちょっと特殊なコンポーネントで、内側にテクスチャを貼ることができ、子コンポーネントを収録できるタイプです。今回は触れません。</p>

<h3>ビデオ・オーディオ関連のコンポーネント</h3>

<p>ビデオの話が少し出ましたが、ビデオ・オーディオ系に関係してくるコンポーネントは以下となります。</p>

<ul>
<li>Sound</li>
<li>Video</li>
</ul>

<p><code>Sound</code>は、シーンに配置するコンポーネントですが、何か形があるわけではありません。音の発生源として配置する形になります。3Dオーディオをサポートしており、ヘッドマウントディスプレイを被って顔を左右に振ったりすると、音源の場所に応じたサウンドになることが確認できます。</p>

<p><code>Video</code>は、2Dのビデオを再生するためのコンポーネントです。これをユーザーの前面に貼ると巨大なテレビが目の前に広がったような演出ができます。</p>

<h3>ユーザーインターフェースとなるコンポーネント</h3>

<p>続いて、VR世界のユーザーインターフェースとなるコンポーネントが下記2つです。</p>

<ul>
<li>VrButton</li>
<li>VideoControl</li>
</ul>

<p><code>VrButton</code>は、ボタンです。応用性が高く、使い勝手の良いコンポーネントと言えるでしょう。<code>VideoControl</code>は、ビデオをコントロールするためのユーザーインターフェースとなります。
<code>Video</code>コンポーネントと<code>VideoControl</code>コンポーネントを組み合わせると、VR空間にビデオプレーヤーを作ることができます。</p>

<div id="attachment_23948" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/ReactVR_video-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23948" srcset="/wp-content/uploads/2017/07/ReactVR_video.png 640w, /wp-content/uploads/2017/07/ReactVR_video-300x162.png 300w, /wp-content/uploads/2017/07/ReactVR_video-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">Videoコンポーネントでビデオを表示させているサンプル</p></div>

<h3>形状コンポーネント</h3>

<p>そして、今回扱う形状コンポーネントです。</p>

<ul>
<li>Box</li>
<li>Cylinder</li>
<li>Plane</li>
<li>Sphere</li>
<li>Model</li>
</ul>

<p>上記のうち、Modelを除いた4つは<strong>3Dプリミティブコンポーネント</strong>と呼ばれます。<code>Box</code>は立方体や直方体などを作成することができるタイプのコンポーネントです。<code>Cylinder</code>は、円筒形の形状コンポーネントで、設定によっては円錐形の形状を作成することができます。<code>Plane</code>は、フラットな平面コンポーネントです。</p>

<p>ちなみに、<code>Model</code>は空間に配置するコンポーネントだけど、別の3Dソフトなどで作成したモデルデータを使用するためのもので、今回は一旦スキップします。</p>

<p>これ以外にもライティングに関するコンポーネントも存在しますが、実際に使うところで解説していきます。</p>

<p>では、今回は実際に3Dプリミティブコンポーネントを、シーンにいろいろと配置し、様々なライティングをしてみましょう。</p>

<h2>3Dプリミティブコンポーネントを配置してみよう</h2>

<p>さて、これから3Dプリミティブコンポーネントを配置していろいろ実験していくわけですが、その前に、何か仮想現実の実験ぽくするための会場づくりをしましょう。React VRで何も背景に敷かない場合、漆黒の空間に単なる立方体が浮かぶことになります。それでは何も趣がないですよね。</p>

<p>ということで、<strong>VR空間をホロデッキ（アメリカのTVドラマ・映画のスタートレックに登場するホログラフィックルーム）として定義</strong>してみましょう。ホロデッキってなあに？って方は、Wikipediaの<a href="https://en.wikipedia.org/wiki/Holodeck" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ホロデッキに関する説明と写真</a>をご覧ください。</p>

<p>ホロデッキは、黒い部屋に、方眼紙のような感じで黄色の線が入っている部屋です。これを実現するために<code>Pano</code>コンポーネントを使います。<code>Pano</code>コンポーネントは360度写真を閲覧するために前回使いましたが、<code>Pano</code>コンポーネントはもう一つ使い方があって、6つのテクスチャを配列で渡してあげると、立方体のの内側にテクスチャが貼られた部屋を作ることができます。</p>

<p>では、まず新規React VRプロジェクトを作成するところから始めてみましょう。</p>

<h3>1. 新規React VRプロジェクトを作成し、Panoコンポーネントで部屋を作る</h3>

<p>まずはなにはともあれ、新規ReactVRプロジェクトを立ち上げましょう。名前は<code>Hello3DObject</code>としましょう。</p>

<p></p><pre class="crayon-plain-tag">$ react-vr init Hello3DObject
$ cd Hello3DObject</pre><p></p>

<p>続いて、<code>Pano</code>コンポーネントを使って、テクスチャが貼られた立方体の空間を作っていきます。プロジェクトルートにある「index.vr.js」の<code>View</code>コンポーネント以下を編集していきます。今回<code>Pano</code>コンポーネントの内側には、前後左右上下の6面にテクスチャを貼ります。貼るテクスチャは、<a href="http://www.premiumpixels.com/freebies/20-seamless-photoshop-grid-patterns/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">フリーのグリッドパターン &#8211; 20 Seamless Photoshop Grid Patterns</a>のうち一枚をPhotoShopで修正した格子状のものです。</p>

<div id="attachment_23950" style="width: 310px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/holodeck-300x300.png" alt="" width="300" height="300" class="size-medium wp-image-23950" srcset="/wp-content/uploads/2017/07/holodeck-300x300.png 300w, /wp-content/uploads/2017/07/holodeck-150x150.png 150w, /wp-content/uploads/2017/07/holodeck-207x207.png 207w, /wp-content/uploads/2017/07/holodeck.png 500w" sizes="(max-width: 300px) 100vw, 300px" /><p class="wp-caption-text">ホロデッキっぽいテクスチャ画像</p></div>

<ul>
<li><a href="https://html5experts.jp/wp-content/uploads/2017/07/holodeck.zip" data-wpel-link="internal">こちらからダウンロードください</a></li>
</ul>

<p>上記リンク先でダウンロードしたファイルを解凍し、中に入っている「holodeck.png」を「static_assets」ディレクトリ以下に配置します。</p>

<p><code>Pano</code>コンポーネントに対して六面にテクスチャを貼るには、<code>source</code>属性に<code>uri</code>プロパティを持ったオブジェクトを6つ含んだ配列を渡します。<code>asset</code>関数は、ファイル名を渡すと<code>{uri: パス名}</code>の形式で返るので、<code>asset</code>関数をそのまま<code>source</code>属性へ渡せばいいことになります。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
              &lt;Pano source={[
                asset('holodeck.png'), // 右
                asset('holodeck.png'), // 左
                asset('holodeck.png'), // 上
                asset('holodeck.png'), // 下
                asset('holodeck.png'), // 後
                asset('holodeck.png')  // 前
              ]}
              /&gt;
            &lt;/View&gt;</pre><p></p>

<p>さて、まずはここで一旦ビルドしてみましょう。</p>

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

<p>ブラウザで、<code>http://localhost:8081/vr/</code>を開いてみましょう。スタートレックのホロデッキのような空間が出現したと思います。テクスチャのつなぎ目とか細かい点はサンプルということでご容赦ください。</p>

<div id="attachment_23949" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_holodeck-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23949" srcset="/wp-content/uploads/2017/07/Hello3DObject2_holodeck.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_holodeck-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_holodeck-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">ホロデッキに入った</p></div>

<h3>2. <code>Box</code>をいくつか並べて配置してみる</h3>

<p>ホロデッキ的な空間が出来たところで、<code>Box</code>コンポーネントを配置してみましょう。<code>Box</code>コンポーネントはシンプルなコンポーネントですが、よくありがちな失敗として、<code>Box</code>コンポーネントをインポートし忘れるということがあります。これから登場する<code>Cylinder</code>や<code>Sphere</code>も同様にimportし忘れがないようにしましょう。</p>

<p></p><pre class="crayon-plain-tag">import {
  AppRegistry,
  asset,
  Pano,
  Box,
  Cylinder,
  Sphere,
  View,
} from 'react-vr';</pre><p></p>

<p>では、<code>Box</code>コンポーネントを目の前に3つ配置してみます。<code>Pano</code>コンポーネントの下に<code>Box</code>コンポーネントを下記のように3つ記述します。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
                &lt;Pano ... /&gt; 
                &lt;Box dimWidth={0.5}
                     dimDepth={0.5}
                     dimHeight={0.5}
                     style={{
                       color: '#00f',
                       transform: [{translate: [1, 0, -2]}],
                     }}
                     lit={false}
                /&gt;
                &lt;Box dimWidth={0.3}
                     dimDepth={0.5}
                     dimHeight={1}
                     style={{
                       color: '#f00',
                       transform: [{translate: [0.2, 0, -2]}],
                     }}
                     lit={false}
                /&gt;
                &lt;Box dimWidth={0.7}
                     dimDepth={1}
                     dimHeight={0.3}
                     style={{
                       color: '#0f0',
                       transform: [{translate: [-0.7, 0, -2]}],
                     }}
                     lit={false}
                /&gt;
            &lt;/View&gt;</pre><p></p>

<p><code>dimWidth</code>、<code>dimHeight</code>、<code>dimDepth</code>の各属性は、幅、高さ、奥行きのサイズに相当します。この比率を変えることで、立方体や柱のようなもの、平らな板のようなものを作り出すことができます。</p>

<p>また、<code>style</code>属性で色が定義されていることもわかります。3つの色は右から青、赤、緑の原色です。<code>style</code>属性に<code>transform</code>というプロパティが定義されていますが、ここで配置を指定しています。位置関係の変形は、<code>translate</code>で指定します。配列で指定し、左からX座標、Y座標、Z座標となります。Z座標は奥行きです。ちなみにマイナスの数値になればなるほど初期状態の位置から奥へ向かって移動する形になります。</p>

<p><code>lit</code>という属性がありますが、こちらはライティングに関するプロパティで、後ほど解説します。</p>

<div id="attachment_23952" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_box-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23952" srcset="/wp-content/uploads/2017/07/Hello3DObject2_box.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_box-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_box-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">Boxコンポーネントを3つ配置した</p></div>

<p><code>Box</code>コンポーネントを配置できたところで、他のコンポーネントを配置していきましょう!</p>

<h3>3. <code>Box</code>だけでなく、<code>Cylinder</code>や<code>Sphere</code>を配置してみる</h3>

<p>さて、今度は<code>Cylinder</code>や<code>Sphere</code>もシーンに配置してみます。一旦<code>Box</code>コンポーネントのパートで作った3つのボックスは消してしまいましょう。勢いあまってホロデッキっぽくしている<code>Pano</code>まで消さないようにしてくださいね、情感がなくなってしまいますので。</p>

<p>まず、<code>Cylinder</code>コンポーネントについて。Cylinder、つまりカタカナでいうシリンダーは、円筒を意味しますが、<code>Cylinder</code>コンポーネントはプロパティ次第で円錐形にもなります。ポイントは<code>radiusTop</code>と<code>radiusBottom</code>で、<code>radiusTop</code>が小さければ山のようになっていき、<code>radiusBottom</code>が大きければ、ラッパのような形状になっていきます。どちらの値も等しい時だけ円筒形になります。</p>

<p>続いて<code>Sphere</code>コンポーネントですが、Sphereというのは球体です。<code>Sphere</code>コンポーネントはなかなか使い出があるコンポーネントで、四角形や円筒形を使う機会はそれほどないかもしれませんが、球体というのはテクスチャを貼り付ければ惑星になったりと応用性が高い3Dプリミティブコンポーネントです。下記のようにシーンに配置してみました。それぞれ一つずつ配置しています。<code>Sphere</code>コンポーネントには<code>widthSegments</code>と<code>heightSegments</code>というプロパティがありますが、これは球体を構成するセグメント（分割数）を定義しています。この数が増えるとなめらかな球体へ近づいていきます。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
                &lt;Pano ... /&gt; 
                &lt;Box dimWidth={0.3}
                     dimDepth={0.3}
                     dimHeight={0.3}
                     style={{
                       color: '#00f',
                       transform: [{translate: [0.5, -0.5, -1]}]
                     }}
                     lit={false}
                /&gt;
                &lt;Cylinder radiusTop={0.1}
                          radiusBottom={0.4}
                          dimHeight={0.8}
                          segments={20}
                          style={{
                            color: '#f00',
                            transform: [{translate: [-0.2, -1, -3]}],
                          }}
                          lit={false}
                /&gt;
                &lt;Sphere radius={0.3}
                        widthSegments={15}
                        heightSegments={15}
                        style={{
                          color: '#0f0',
                          transform: [{translate: [-2, -1, -5]}],
                        }}
                        lit={false}
                /&gt;
            &lt;/View&gt;</pre><p></p>

<p>今回、ちょっと配置に工夫をしています。<code>translate</code>プロパティの値を変更していて、手前に立方体、奥に行くにしたがって円筒形、球体と並ぶようにしています。これで3Dプリミティブの配置は完了したわけですが、何かもの足りません。のっぺりしていて立体感がないのです。ということで、この3Dオブジェクトに光を当てていきましょう。</p>

<div id="attachment_23953" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_three_obj-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23953" srcset="/wp-content/uploads/2017/07/Hello3DObject2_three_obj.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_three_obj-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_three_obj-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">配置された、球体、円錐形、立方体</p></div>

<h3>4. 3Dプリミティブオブジェクトに光を当ててみる</h3>

<p>React VRでライティング（照明）を行うには、用意されている4つのコンポーネントのいずれかもしくは複数の組み合わせを使用します。</p>

<p>用意されているReact VRコンポーネントは下記の4つです。</p>

<ul>
<li>AmbientLight</li>
<li>DirectionalLight</li>
<li>PointLight</li>
<li>SpotLight</li>
</ul>

<p><code>AmbientLight</code>は、<strong>環境光</strong>と呼ばれるもので、シーン全体に均一な影響を与える光源を定義します。これは無指向性で、すべてのオブジェクトが等しく明るくなります。</p>

<p><code>DirectionalLight</code>は、<strong>指向性があるが、距離による明かりの減光は発生しないタイプの光源</strong>です。太陽の明かりのようなものと言えます。</p>

<p><code>PointLight</code>は、<strong>ある一点から発生する光源</strong>で、距離による減光もあります。見えない間接照明のようなものと言えるでしょう。</p>

<p><code>SpotLight</code>は、文字通り<strong>スポットライトのような特性を持つととらえられる光源</strong>です。指向性があり、距離による範囲の拡大と減光があります。</p>

<p>20程度のコンポーネントしか用意されていないReact VRにおいて、ライティング関係だけで、4つもコンポーネントが用意されているのは、一つはVRにおいてそれだけ重要であるということと、React VRが使用しているThree.jsにおいても手厚いサポートがされていること、そしておそらくはこうしたライティング関係は、カスタムコンポーネントとしての作成が困難であろうことなどが推測されます。</p>

<p>まずは普通の光を当てましょう。太陽のように上から降り注ぐ普通の明かりです。こういった明かりは、<code>DirectionalLight</code>コンポーネントを使うことで実現できます。</p>

<p>では、まず準備段階として、先ほど作成した3種類の3Dプリミティブオブジェクトが持っている<code>lit</code>プロパティを<code>true</code>にしてみましょう。これで光源の影響を受けるようになります。試しに<code>true</code>にした段階で、ブラウザをリロードしてみてください。まだ光が当たっていないため、真っ黒のオブジェクトになってしまったと思います。</p>

<div id="attachment_23954" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_three_obj_black-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23954" srcset="/wp-content/uploads/2017/07/Hello3DObject2_three_obj_black.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_three_obj_black-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_three_obj_black-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">真っ黒の3Dプリミティブオブジェクト</p></div>

<p>続いて、<code>DirectionalLight</code>コンポーネントを配置します。<code>Pano</code>コンポーネントの下あたりでOKです。こんな感じにします。(importを忘れずに)</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
            &lt;Pano ... /&gt;
            {/* Lighting */}
            &lt;DirectionalLight   intensity={0.5}
                                style={{
                                color: 'white',
                                transform: [
                                    {translate: [0, 0, 0]},
                                    {rotateX: 45}]
                                }}/&gt;
            &lt;Box ... /&gt;
            &lt;Cylinder ... /&gt;
            &lt;Sphere ... /&gt;
        &lt;/View&gt;</pre><p></p>

<p><code>intensity</code>プロパティは、光の強度を設定します。また、光源にも色をつけることができ、スタイルシートで定義します。<code>transform</code>プロパティで<code>rotateX</code>の設定をしていますが、これは、ちょっと斜め前方から光を当てたいからです。本当の真上からあたる光は、側面すら陰になってしまい、あまり面白みはありません。</p>

<div id="attachment_23955" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_DirectionalLight-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23955" srcset="/wp-content/uploads/2017/07/Hello3DObject2_DirectionalLight.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_DirectionalLight-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_DirectionalLight-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">DirectionalLightを設定したシーン</p></div>

<p>次は<code>PointLight</code>コンポーネントを配置してみましょう。PointLightは点光源なので、任意の位置に配置すると、その周囲を照らしてくれます。うまく使うと印象的な効果を与えることができます。さて、今回は、PointLightをちょっと手前に配置し、しかもちょっと青系の光として照らしてみましょう。どんな感じになるでしょうか。</p>

<p><code>DirectionalLight</code>コンポーネントの下に、下記のように<code>PointLight</code>コンポーネントを設置します。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
            &lt;Pano ... /&gt;
            {/* Lighting */}
            &lt;DirectionalLight   intensity={0.5}
                                style={{
                                color: 'white',
                                transform: [
                                    {translate: [0, 0, 0]},
                                    {rotateX: 45}]
                                }}/&gt;
            &lt;PointLight intensity={5}
                        style={{
                            color: '#00f',
                            transform: [{translate: [0.1, -1, -2]}]
                        }}/&gt;
            &lt;Box ... /&gt;
            &lt;Cylinder ... /&gt;
            &lt;Sphere ... /&gt;
        &lt;/View&gt;</pre><p></p>

<p><code>intensity</code>プロパティはちょっと強めの<code>5</code>にしました。色は青色、そして位置はちょっと手前でちょっと下から照らす感じにしています。</p>

<p>すると、こんな感じで、青い光がオブジェクトに反射するような雰囲気になりました。ちょっとムーディで怪しげですね。</p>

<div id="attachment_23956" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_PointLight-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23956" srcset="/wp-content/uploads/2017/07/Hello3DObject2_PointLight.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_PointLight-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_PointLight-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">PointLightを反映させた3Dプリミティブオブジェクト</p></div>

<p>さて、これで終了にしてもいいのですが、全体的にちょっと暗いですよね、そこで光の調整をしたいと思います。</p>

<p>では<code>AmbientLight</code>コンポーネントを配置してみましょう。AmbientLightは環境光で、全てのオブジェクトに均等に光を当てるという機能を持っています。<code>AmbientLight</code>コンポーネントを使うことで、全体的な光の加減を微調整することもできます。</p>

<p></p><pre class="crayon-plain-tag">&lt;View&gt;
            &lt;Pano ... /&gt;
            {/* Lighting */}
            &lt;DirectionalLight intensity={0.5}
                                style={{
                                color: 'white',
                                transform: [
                                    {translate: [0, 0, 0]},
                                    {rotateX: 45}]
                                }}/&gt;
            &lt;PointLight intensity={5}
                        style={{
                            color: '#00f',
                            transform: [{translate: [0.1, -1, -2]}]
                        }}/&gt;
            &lt;AmbientLight intensity={0.3}/&gt;
            &lt;Box ... /&gt;
            &lt;Cylinder ... /&gt;
            &lt;Sphere ... /&gt;
        &lt;/View&gt;</pre><p></p>

<p><code>intensity</code>プロパティは、ほんの少しだけ設定しました。これでブラウザをリロードしてみると、ほんのりと明るくなったことがわかると思います。</p>

<div id="attachment_23947" style="width: 650px" class="wp-caption alignnone"><img src="/wp-content/uploads/2017/07/Hello3DObject2_AmbientLight-640x346.png" alt="" width="640" height="346" class="size-large wp-image-23947" srcset="/wp-content/uploads/2017/07/Hello3DObject2_AmbientLight.png 640w, /wp-content/uploads/2017/07/Hello3DObject2_AmbientLight-300x162.png 300w, /wp-content/uploads/2017/07/Hello3DObject2_AmbientLight-207x112.png 207w" sizes="(max-width: 640px) 100vw, 640px" /><p class="wp-caption-text">AmbientLightを反映させた3Dプリミティブオブジェクト</p></div>

<p>いろいろな形状のものを置き、ライティングを終えたところで、こんな風に思った方はいないでしょうか。<br />
「現実世界で立方体や球なんて、積み木とかにしか存在しないじゃないか！」<br />
と。</p>

<p>四角や丸を置くためにVRを始めたわけじゃないんだという気持ちはよくわかりますので、次回は応用編として既存の3DモデルをReact VRで扱う方法について解説していきます。</p>
]]></content:encoded>
		
		<series:name><![CDATA[React VR]]></series:name>
	</item>
	</channel>
</rss>
