こんにちは!Prottチームのよしこです。
先月カリフォルニア州のマウンテンビューでおこなわれたGoogle I/O 2017に参加してきました!
この記事では写真で現地の雰囲気をお伝えします。加えて、最終日におこなわれたクイズ形式の参加型セッション「How Well Do You Know the Web?」がとても勉強になったので、冒頭4問の内容をご紹介したいと思います!

Google I/Oの現地の雰囲気

マウンテンビュー滞在中はとてもいい天気が続いていました。
会場のアンフィシアターまでは、無料のシャトルバスや各自調達したLyft/Uberなどのサービスで向かいます。

会場の入り口はこんな感じ。

中に入ると、受付と奥に一番大きいセッション会場であるアンフィシアターのテントが見えてきました!

受付の横にある、おおきなI/Oのロゴ。

I/O開催の前日からバッジピックアップがあり、参加者は各自受付まで参加証をもらいに行きます。このとき参加証をもらった順番で基調講演の席エリアが決まるので、前日の朝から多くの人が受付に向かっていました!

この参加証にはICタグが埋め込まれているようで、I/O中の各セッション会場に入る時に参加証をスタッフさんのAndroidにかざすと、そのセッションの席を予約しているかどうかを読み取れるようになっていました。このおかげで大変スムーズにセッション会場へ入ることができました!

Google I/Oは初日の基調講演から始まります。基調講演は一番大きな会場でおこなわれ、多くの人が詰めかけていました!

開演を待つまでの間は、泡のゲームを楽しめるようになっていました。

基調講演の内容は既にたくさんの記事でまとめられているので省略しますが、中でもひときわ大きな歓声があがっていたのはKotlin公式サポートの発表でした。

そして心に残ったのは「モバイルファーストからAIファーストへ」というメッセージです。私がIT業界に足を踏み入れた2011年は、ちょうど日本でもモバイルファーストという言葉が話題になり始めていた記憶があるので、時代の流れを肌で感じて感慨深くなりました。

基調講演が終わると、あちこちの会場でさまざまなセッションが始まります!

How Well Do You Know the Web?

Google I/Oでおこなわれたセッションの中で、おそらく唯一のリアルタイムクイズ形式だった、Webについてのセッション「How Well Do You Know the Web?」がとても勉強になったので、冒頭4問の問題と解説のトークをご紹介したいと思います。


2日目のお昼前、一番大きな会場であるアンフィシアターにてセッションが始まると、スクリーンにはこのような画面が映されました。

セッション中に The Big Web Quiz! にアクセスすると画像のようなWebアプリが表示されます。(今は参考リンク集になっています)
セッション中に出された問題の選択肢が各自の端末にリアルタイムに表示され、自分の答えをSubmitできるという参加型のクイズ形式になっていました。
簡単なウォーミングアップで操作に慣れた後、いよいよ第一問です!

Q1: スクリプトのダウンロード中に、HTMLのパースをブロックしてしまうものはどれでしょう?(複数選択可)

  1. <script src=”blah.js”></script>
  2. <script src=”blah.js” defer></script>
  3. <script src=”blah.js” async></script>
  4. <script src=”blah.js” async=”false”></script>

一問目はパフォーマンス上で重要になるscriptタグの挙動についての問題です。属性が異なっていますが、はたして…

回答時間が終わったあとに開示される会場の回答内容の割合はこんな感じでした。
(回答中にも選択肢を伏せて割合だけがリアルタイムで表示されていたため、どの割合がどの選択肢かを推測されないように表示順がランダムになっています。画像は4, 1, 3, 2の順)

Q1 答え:

  1. <script src=”blah.js”></script>

Q1 解説:

script要素はデフォルトでダウンロード中と実行中にHTMLのパースをブロックしますが、deferasyncの属性が付加されている場合には、ダウンロード中にHTMLのパースをブロックしません。
deferasyncの違いは実行のタイミングです。deferのほうはHTMLのパースが最後まですべて完了したあとに、HTMLパース中にscriptタグが出てきた順で実行されます。一方asyncは、HTMLのパースが終わっていなくてもそのスクリプトのダウンロードが完了したらすぐに実行されます。なので、ダウンロード完了のタイミングによって実行順が変わってしまいます。

(※水色がダウンロード、オレンジが実行)

asyncのようにスクリプトの実行順が可変だと、スクリプト同士が互いに依存していたときにどのような挙動になるかわからず、再現性のないバグの原因になる可能性があります。
deferは予測可能なタイミングかつ予測可能な順序で実行されるため、その心配はありません。しかし、たとえば長い長い記事のページがあったとき、ページの一番上にあるボタンを修飾するためのスクリプトをdeferで実行してしまうと、ページが最後までパースされたあとに実行されるため、ボタン表示とのタイムラグが生まれてしまいます。このように、「どれを使えばよいか」というのは状況に依存します。ツールはルールではないので、色々な方法を試して、ユーザーにとって一番快適な方法を探してください。

ちなみに最後の選択肢async="false"については、ブラウザは属性の値を無視するため、asyncと同じになります。属性の値を無視するというのはasyncだけでなく、booleanが値となるようなほとんどの属性に当てはまります。 [解説ここまで]


scriptがHTMLのパースをブロックするという前提を知らなかった方も多いのではないでしょうか?また async="false"には会場で参加した人の大部分もひっかかっていましたね。ReactやAngularなどのフレームワークでは属性にboolean値を渡すことで内部的に有無を切り替えることが多いので、混同してしまいそうな部分です。

次は新しいscriptのロード方法についての問題です!

Q2: ES Modulesの仕様で一番最初に実行されるスクリプトはどれでしょう?

<script src="script-one" type="module"></script>
<script type="module">console.log('script-two')</script>
<script defer>console.log('script-three')</script>
<script src="script-four" defer></script>
  1. script-one
  2. script-two
  3. script-three
  4. script-four

二問目は最近ブラウザへの実装も進んでいるES Modulesに関する問題。ブラウザ上で使用する場合にはscript要素に type="module" を指定する形になっています。実行順にはどう影響するのでしょうか?
会場の回答内容の割合はこんな感じでした。(画像は2, 4, 1, 3の順)

Q2 答え:

3. script-three

Q2 解説:

script要素が type="module" のES Modules形式で記述された場合、デフォルトで defer 属性が付加されたときと同じ挙動になります。これはsrcにファイルを指定した場合でも、script要素内に直接スクリプトを記述した場合(インライン)でも同じです。
一方defer 属性はインラインのscript要素に適用することができません。type="module" によってインラインのscript要素を defer にできるのは新しい挙動です。
というわけで1・2・4番はすべてdefer属性のタイミングで実行されます。しかし3番のdeferはインラインのscript要素に付加されているため無効です。4つの選択肢の中で唯一deferが付加されていないことになるので、3番が一番早く実行されます。

ちなみにtype="module" のscript要素にもasync属性を適用することができます。この場合はasyncの挙動となり、importで依存しているすべてのスクリプトがダウンロードされた直後に実行されます。 [解説ここまで]


defer属性はインラインのscriptに指定できないということと、ES Modules形式で読み込んだスクリプトはすべて defer と同じ挙動になるという2点がポイントの問題でした。会場でも正解できた人は14%と、なかなかの難問でしたね。

次は2問続けてキャッシュについての問題です。

Q3: Cache-Control: must-revalidate, max-age: 31536000 の意味はどれでしょう?

  1. キャッシュしないでください
  2. キャッシュしてください、でも必ずサーバーでの検証後に使用してください
  3. キャッシュしてください、そして31,536,000秒(1年)の間はサーバーの検証なしで使用できます

会場の回答内容の割合はこんな感じでした。(画像は3, 2, 1の順)

Q3 答え:

3. キャッシュしてください、そして31,536,000秒(1年)の間はサーバーの検証なしで使用できます

Q3 解説:

must-revalidateは、キャッシュが指定されたmax-ageを過ぎた場合にキャッシュをサーバーで再検証しなければならないことを意味します。max-ageを過ぎていないキャッシュはサーバーでの検証なしに自由に使用できます。

では、must-revalidateno-cacheに変わるとどうでしょうか?

Q4: Cache-Control: no-cache, max-age: 31536000 の意味はどれでしょう?

  1. キャッシュしないでください
  2. キャッシュしてください、でも必ずサーバーでの検証後に使用してください
  3. キャッシュしてください、そして31,536,000秒(1年)の間はサーバーの検証なしで使用できます

会場の回答内容の割合はこんな感じでした。(画像は2, 1, 3の順)

Q4 答え:

2. キャッシュしてください、でもサーバーでの検証後に使用してください

Q4 解説:

no-cachemust-revalidate, max-age: 0 のショートハンドなので、no-cacheのあとにある max-age: 31536000は無視されます。つまりno-cacheの場合、キャッシュされる可能性はあるものの、キャッシュを使用する前には必ずサーバーで検証しなければならないという意味になります。(なぜno-cacheという名前になったかはわからないとのこと…)

パフォーマンスのためにリクエストは少ないほうがいいので、画像やCSS、JSなどのサブリソースは不変なリソースとして扱い、そのキャッシュ期間はできるだけ長くすることが望ましいです(1年など)。そして、そのリソースを更新するときにはURLを変更します。cat.4e22cdf.gifのような一意のURLを作ることで手助けしてくれるビルドツールがたくさんあります。webpackもそのうちの一つです。
しかし、/about-us/などユーザーが直接訪れるページはそういうわけにはいきません。そういうページはno-cacheを使うのが最善です。
また、/messages/のようなプライベートなデータが含まれるページにはキャッシュを許可しないno-storeをつけるとよいでしょう。[解説ここまで]


must-revalidateno-cache、名前から挙動を想像するとなかなかややこしいですね。どちらの問題も正答率は50%を下回っていました。

このあともクイズは続き、その数は全14問!普段馴染みのあるCSSやJS, HTMLの挙動についての質問もあり、どれもわかりそうでわからない良問です。私は普段の自分の業務内容と近しい問題なのになかなか正答できず、悔しい思いをしながら楽しく勉強することができました 😂
正解発表のあとのジョークを交えた軽快な解説も大変勉強になるので、興味を持たれた方はぜひ最後まで動画で楽しんでみてください!

Goodpatchはこれまでに毎年1〜2名ほど、Google I/OやWWDCなどの国際的な技術カンファレンスへの社員の参加を支援してきています。
私は今回が初めてのGoogle I/Oでしたが、セッションの他にもハンズオン形式で技術を学べるCodelabsやAR/VRのSandbox、交流ディナーなどでたくさんの刺激を得ることができ、とても貴重な経験になりました!
人間とデジタルを繋ぐインターフェースはこれまで以上にスクリーンに囚われなくなっていきます。時代の移り変わりと共に増えていく選択肢を見失わないよう、今回の経験も業務に活かしていければと思います。