2021年3月第1週レポート
インプット
📝 今更ながらのVue Router
先週のレポートにて素のVueプロジェクトを作っているという話を書きましたが、今週はそちらで使うVue Routerを調べました。
Vue RouterはVue.jsでSPAを作るときに、ルーティングの機能を提供してくれるVue.jsの公式プラグインです。Nuxt.jsでは規約通りにページコンポーネントをディレクトリにおいておけば、ビルド時に自動生成してくれるのでVue Routerの存在をあまり意識しなくて済むのですが、今回はそうにもいかないので朧げな知識を補強するため再調査を実施しました。
基礎
- ルート
- URLとView(Vueコンポーネント)の情報を持つレコード
- /goodsというURLに対してGoods.vueを表示する、みたいな
- TypeScriptには
RouteConfig
型が用意されている
import Goods from '../view/Goods.vue'
const route: RouterConfig = {
path: '/goods',
component: Goods
}
- このルートオブジェクト(の配列)を
VueRouter
のコンストラクタに渡すことによってVue Routerのセットアップができる。
const router = new VueRouter({
routers: [route] // 他のルートがあれば配列に入れておく
})
// VueをコンストラクタするときにrouterプロパティにVue Routerオブジェクトを渡す
new Vue({router: router}).$mount('#app')
- ルートオブジェクトで指定したコンポーネントを表示する場所はHTMLの
router-view
タグを使って指定する - Vue Routerによるルーティングをつかったリンクは
router-link
タグを使って指定する
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/goots">Goods</router-link>
</div>
<router-view/>
</div>
</template>
URLパラメータとパターンマッチング
- URLのパスに「:」を使ってパターン記述することによりURLパラメータを定義できる
- マッチしたURL上のパラメータはコンポーネント内にて
$route.params
から取得することができる
import Goods from '../view/Goods.vue'
const route: RouterConfig = {
path: '/goods/:product',
component: Goods
}
<template>
<div class="about">
<h1>This is an {{$route.params.product}}</h1>
</div>
</template>
名前付きルート
- Vue Routerではルートを定義する時に名前をつけることができる ```typescript import Goods from ‘../view/Goods.vue’
const route: RouterConfig = { path: ‘/goods/:product’, component: Goods name: ‘Goods’ }
- `router-link`の`to`にはVue Routerにて用意されている`Location`型のオブジェクトを渡すことができる
```typescript
export interface Location {
name?: string
path?: string
hash?: string
query?: Dictionary<string | (string | null)[] | null | undefined>
params?: Dictionary<string>
append?: boolean
replace?: boolean
}
- ここで
name
プロパティを使うことにより、path
を指定することなくルーティングをVueコンポーネントに仕込むことができる
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link>
|
<router-link :to="goodsLocation">Goods</router-link>
</div>
<router-view/>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import { Location } from 'vue-router'
import { Component, Prop, Watch } from 'vue-property-decorator'
@Component
export default class extends Vue {
goodsLocation: Location = {
name: 'Goods',
params: {
product: 'magic attraction'
}
}
}
- URLパラメータ部分を動的に設定したい場合などはオブジェクトを渡すのがよさそう
- スクリプト側で遷移させたい場合は
router.push()
メソッドを使う- 引数に
Location
オブジェクトを渡す
- 引数に
ナビゲーションガード
- Vue Routerではページ遷移が実行される前後に処理を追加できる仕組みがある
- このフックはグローバル、ルート、コンポーネント単位で設定できる
グローバル単位
- ページ遷移前に実行される
VueRouter.beforeEach()
に渡した関数が実行される- 関数は複数個登録することができ、登録した順に実行される
- 引数に渡す関数は
to
、from
、next
の3つの引数を受け取るto: Route
- 遷移後のRouteオブジェクト
from: Roue
- 遷移前のRouteオブジェクト
next: Function(to?: RawLocation | false | ((vm: V) => any) => void
:- ナビゲーションパイプラインの流れを制御するための関数
コンポーネント単位
- クラススタイルで書く場合には
Component.registerHooks()
を使って、フックタイミングを設定する必要がある
<template>
<div class="about">
<h1>This is an {{ $route.params.product }}</h1>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import { Component, Prop, Watch } from 'vue-property-decorator'
Component.registerHooks(['beforeRouteLeave'])
@Component
export default class extends Vue {
beforeRouteLeave() {
console.log('leave')
}
}
</script>
📝 CookieのSameSite属性
Cookieの属性といえばSecure、HttpOnly、Domain、Pathというのはこれまでも意識していましたが、SameSiteについてはうる覚え?なんかトラッキングとかに影響でるんだっけ?くらいの認識だったので調べてみました。
HTTP クッキーをより安全にする SameSite 属性について (Same-site Cookies) – ラボラジアン (laboradian.com)
SameSite属性はクロスドメインアクセス時にブラウザに保存されているCookieを送信するかどうかをコントロールするための属性です。
CookieはDomain属性とPath属性を使いリクエスト送信時にCookieをいっしょに送信する(Cookieヘッダに値を埋め込む)かどうかをURLベースでコントロールできます。SameSite属性を使うことによってDomain/Path属性によるURLベースの判定に加え、クロスドメインアクセス時にCookieを送信するかどうか判定できます。
例えば、ブラウザがA.com
のCookieを持っていたとして、B.co.jp
というサイトでA.com
へのリダイレクトが発生した時、リダイレクト時にA.com
のCookieを一緒に送信するかどうか、みたいな。
SameSite属性には「Strict、Lax、None」の3つのうちいずれかを設定できます。
- Strict Cookieを送信しない
- Lax GETリクエストかつ、Top-level navigationであるときのみ送信される
- None Cookieを一緒に送信する
セキュリティ効果だとCSRF脆弱性には効果がありそうです。CSRFは間接攻撃の一種で、ユーザを罠サイトに誘導するなどして、ユーザのブラウザから脆弱性のあるWebサイトに対してユーザが意図していないコミットリクエスト
をWebサイトに送信するものです。
このとき罠サイトには、脆弱性のあるWebサイトへ自動でPOSTするようなJavaScriptコードがあったりするわけです。Cookieベースでセッション管理をしているようなWebサイトだと、該当するCookieがブラウザに保存されていればCookieをいっしょに送ってしまうので、対策をしていなければ攻撃が成立してしまいます。
ここでSameSite属性が効いてきて、例示したケースだと、Strictの場合はCookieが送信されないので攻撃が成立しない、POSTによるリクエストなのでLaxを指定したときもCookieが送信されず攻撃が成立しない。
Laxの場合は条件付きでCookieが送信されることがあるので気をつける必要がありますが、これまでのトークンベースの対策に比べるとだいぶ容易にCSRF対策を実装できるんじゃないかなと思います。GETでコミット処理させるなを徹底するだけでだいたい防げそう。
📝 「Switch」と「Toggle」の違い
英単語シリーズ
【実務翻訳に挑戦】「切り替える」は英語でなんて言う?switchとtoggleの違い | 海外リアルLAB (gohanlab.com)
- toggleは
2つ
の状態を切り替える - switchは
2つ以上
の状態を切り替える
選択肢が3つあるときはtoggleを使うなってことですね。
アウトプット
🛠️ mixpaceにリモートレンダリングの機能が備わりました
mixpaceの新バージョンをリリースしました!
ホロラボ、超重量級3D CAD/BIM・3DCGファイルみえる化ソリューション「mixpace Remote Rendering」を提供開始|ホロラボのプレスリリース (prtimes.jp)
今回はAzure Remote Renderingを使って、mixpaceでコンバートした大量ポリゴンをもつ3Dモデルをクラウド側でレンダリングし、その結果をHoloLens2で表示できるようにする機能をリリースしています。これまでHoloLens2のスペックが足りず表示できなかった3Dモデルが、この機能を使うことによって表示できるようになります。
私は裏方というかAzureとクライアントを仲立ちする下周りを実装しました。Azure Remote Renderingでは使用する前に3Dモデルを専用のアセットにコンバートしたり、クライアントアプリ使用前にセッションを用意してあげる必要があります。そういったAzure Remote RenderingのAPIを操作するWebサービス(バックエンド&フロントエンド)を実装しました。
Azure Remote Renderingのセッションは時間経過でその状態が変化するステートフルなオブジェクトです。ですのでアプリケーション(ここではmixpace)のコンテキストの外にあるオブジェクトの状態変化を監視する必要があるのですが、今回はAzure Storage Queueを使ってポーリングするパターンを採用しました(Azure Functionsを使うという案もありました)。セッション作成時にセッションの識別情報をメッセージにしてQueueに入れておき、アプリは一定間隔でQueueからメッセージを取り出し識別情報を使ってセッションの状態を確認する、というものです。
Azure Queue Storageではキューに入っているメッセージを取り出すと一定時間(デフォルトは30秒)不可視状態となります。明示的に削除しない限り、一定時間経過後に可視状態となります(再度エンキューされるようなイメージ)。この特徴を利用することによってセッションの状態確認中にアプリがクラッシュしたとしても監視対象のセッションはQueueに残っているので、障害が発生しても不整合が発生しづらい構成になったかなと思います。
🛠️ VueでTreeビューを作っている
Async Loading Treeもできた pic.twitter.com/9RjEQ7kSPk
— d_yama (@dy_karous) March 8, 2021
VueでjsTreeのようなものを作っています。きっかけはAutodeskが公開しているForgeのサンプルコードなのですが、フロントエンドの実装の多くがjQueryベースであるため、今後いろいろ作っていく上でVueベースのボイラープレート的なものが欲しいと思ったためです。
特にForgeTreeと呼ばれる、Autodeskサービス上にホストしているファイルの一覧を取得するビューアは手触りがよく、取り入れたいポイントが多いため、これは自分で実装して仕組みを把握しておいたほうがいいなと思ったのもあります。
Vueでのツリービューの実装では、単一ファイルコンポーネントだけで実装すると肥大化しそうなので、Treeのノードを表すクラスを用意しVueコンポーネントにそのクラスのインスタンスをPropで流し込んでViewを作る、という構成にしています。