2020-06-06

東京都 新型コロナウイルス感染症対策サイトを読む その3

続きをやっていく
前回みたいに順番に見ていってもいいけど、特に気になる箇所がないコンポーネントもあるので
適当にソースを眺めて気になった記述の部分を重点的に見ていくことにする

i18nタグ(コンポーネント)

pages/about.vue に以下のような部分がある

<i18n
  tag="p"
  path="Google Analyticsによる情報送信を回避する場合は、Google がサポートする{addon}をご利用ください。"
>
  <template v-slot:addon>
    <external-link
      :url="$t('https://tools.google.com/dlpage/gaoptout?hl=ja')"
      :icon-size="16"
    >
      {{ $t('測定を無効にするブラウザ アドオン') }}
    </external-link>
  </template>
</i18n>

これはVue I18nのスロット構文という機能らしい

  • tag="p" でPタグを生成する
  • path="Google〜〜〜" はI18nのキーで assets/locales で定義されている各言語のテキストが埋め込まれる
  • <template v-slot:addon> 〜 </template> で作成されるHTMLが i18n コンポーネントのpath内にある {addon} に展開される

ここでもう一つ気になるのが external-link という子コンポーネントに対して、 urlicon-size というpropsに加え、 {{ $t('測定を無効にするブラウザ アドオン') }} という要素も渡しているという点
これはVue.js本体のスロットコンテンツという機能を使っている

渡した {{ $t('測定を無効にするブラウザ アドオン') }} の部分は、 ExternalLink.vue<slot /> の部分に展開されている
Rubyの yield を思い出した

ExternalLink.vuev-icon は前回説明した通り Vuetify のコンポーネントで、 mdi-open-in-newアイコン名のこと(ちゃんと @mdi/font パッケージも入ってる)

role属性, scope属性

pages/contacts.vue にv-bindによってモバイル環境の時だけ role: 'presentation' という属性が付与される部分がある
<table class="Contacts-Card-Table" v-bind="tableAttrs">〜</table>

また、thタグに scope という属性が付与されている箇所がある
<th class="text-center" scope="col">

これはHTMLの仕様で、アクセシビリティの向上を目的とした属性らしい
要素に意味付けを行い、役割を与えることで、スクリーンリーダーなどの読み上げソフトでwebサイトの構造を認識できるようになるというもの
ちょっとアクセシビリティについては知識が全くないので、どこかで入門しておこう

なお、この部分の修正が入ったPRはこれ
chromeのスクショの Accessibility タブは、スタイルシートのタブと同じ場所にある
(スタイルシートのタブしか見たことなかったけど、こんなタブがあったとは)

svgをコンポーネントっぽく扱う

pages/flow.vue の以下の部分

<fig-cond-sy-dr :class="$style.fig" aria-hidden="true" />

これもコンポーネントか?と思ったら、以下のような読み込みがされていた

import FigCondSyDr from '@/static/flow/cond_sydr.svg'

svg をコンポーネントっぽく扱ってる!

これは nuxt-svg-loader というパッケージを使うと実現できるらしい
nuxt.config.tsmodule で読み込まれている
便利〜

Nuxt.jsはどんなモードで動いて、どんなビルドが行われて、どこへデプロイされているのか

今更だけど、やっぱアプリが最終的にどこで動いているのか、そのためにどう作られているのかは知っておきたいので見ていく

  • nuxt.config.ts を見ると mode: 'universal' となっているので、SSRによるレンダリングがおこなわれている
  • package.json のデプロイ周りのコマンドを見ると nuxt-ts generate されている
  • nuxt.config.ts を見ると、 generate で動的にルーティングが追加されている
    • Nuxt.jsは generate を行うとpages配下に置いた.vueファイルを静的なコンテンツとして出力してくれる
    • しかし、動的なルーティングは全て無視されてしまう(コロナ対策サイトだと、pages/cards/XXXがそれに当たる)

以上から、ページを generate で生成し、動的なルーティングは nuxt.config.ts で追加して作成
配信されたHTMLはユーザーのブラウザ上でSPAとして動作している
デプロイはNetlifyにされていて、静的なサイトとして動作している

という感じだろうか

modeuniversal だとSSRを使う設定らしいが、サーバーで動いている他のアプリもなさそうだし、どう見てもSSRは使ってないように見えるんだけど
この記事を見ると、 nuxt.config.tsgenerate で動的なルーティングを設定していること自体がSSRである。という印象を受けた
SSRするならRailsみたいにアクセスに応じて動的にHTMLを生成する何かがサーバーに必要だと思っていたけど、こういう形のSSRもあるということか(確かにSSRと言えばSSRだ)

generate を使ってSPAにしつつ、あらかじめ動的なルーティングでのHTMLもSSRっぽく生成しておけるから、SSR ではなく、万能ないいとこ取り的な意味で universal という表記なのか(そう意図しているかはわからないけど)
ちょっと謎が解けた感じ