Nuxt.js ビギナーズガイドとPixiJSはじめました

2018/10/22 - 2018/10/28

AirDropを悪用した痴漢が発生しているようです。
悪用するつもりはないですが、 知らない人に画像を送れるなんてAirDropって便利なんですね...今更。
https://www.yomiuri.co.jp/national/20181028-OYT1T50021.html

Nuxt.js ビギナーズガイドを読みはじめた

Vue.js入門に続き、 Nuxt.js ビギナーズガイドという本が発売されたので読みはじめました。
こちらの本です。
nuxt-beginners-guide.elevenback.jp

200ページほどの軽めな本ですが、中身は写経していてとても面白いです。
本の内容としてはこんな感じ。

1章 Nuxt.jsの概要
2章 Nuxt.jsによるシンプルなアプリケーション開発
3章 Nuxt.jsの機能の活用
4章 中規模以上の開発を意識したNuxt.jsによるWebアプリケーション開発
5章 Nuxt.jsアプリケーションのテスティング
6章 アプリケーションのデプロイと運用
7章 プラグインとモジュール、エコシステムの開発・貢献
8章 最新情報のキャッチアップのすすめ

今週は3章まで読んだのでそこまでの学びやら感想やらをつらつらと。

1章 Nuxt.jsの概要について

Nuxt.jsがなぜ生まれたのか。Nuxt.jsがなぜ支持されているのか。について記載しています。

Nuxt.jsが支持されている要因の一つは、「アプリケーションの本質的ではないことを考える機会が少ない」ということのようです。
例えば、以下のようなところ。

  • カスタマイズしたローダーやプラグインを使わない場合はwebpackを意識する必要がない
  • Nuxt.jsはVueのエコシステム(Router, Vuexとか)と密に連携しているから自分で設定しなくてOK
  • vueの機能不足を補う独自レイヤ(middleware, plugins...)が便利

また、規約があるのも上記につながっていそう。
例えば、pagesディレクトリ配下においたvueファイルは、自動的にルーティングされてページになる。
とかとか、Nuxt.js便利じゃん!って話しが記載してあります。

2章 Nuxt.jsによるシンプルなアプリケーション開発

実際にNuxt.jsを使ったwebアプリを作っていきます。
Qiita API を使って、axiosで記事一覧を取得して表示するアプリです。

デザインはめんどくさかったので僕は何もしてませんが...イメージはつくかと思います。
f:id:yagi_suke:20181028195848g:plain

実際に書きながら学ぶスタイルは楽しくて良いですね! 写経したものは以下にupしています。
github: https://github.com/yagisuke/nuxt-beginners-app

3章 Nuxt.jsの機能の活用

レイアウト、ミドルウェアプラグイン、モジュールモードでのVuexといったNuxt.jsの便利機能を紹介しています。

レイアウト

共通のヘッダー、フッター、サイドバーというように、 Webアプリケーションを作る場合は共通のレイアウトになることが多くあり、この機能が活躍します。

Webアプリケーションを作る場合、TOPページは他ページと違ったレイアウトになることが多いので、 Nuxt.jsがはじめから用意しているdefault.vueではなく、TOPページは独自のレイアウトファイルを用意したほうが色々幸せになるよ。 と著者はアドバイスしていました。こういうちょっとしたアドバイスは素敵です。

ミドルウェア

ルーティングへのアクセス時に最初に読み込まれ、SSR処理などが行われる前に処理を行うことができる機能です。 例えば、ユーザーエージェントに合わせたリダイレクト処理や、認証が必要なページの構築など。

この本では、Cookieの値で認証済みかどうかを判定して、ページの出し分けを学ぶことができます。

プラグイン

npmパッケージやVueプラグイン、そのほか、特定の処理をグローバルに登録し、再利用性を高めるために利用します。

プラグインを利用するパターンは主に2つあるそうです。

1. UIフレームワークや、Firebase SDK、momentといった、アプリケーション全体で使うことが明確なライブラリの導入時
2. ルーティングフックや初期段階での外部CDNコードの読み込みなどの共通処理の導入時

また、SSR時に呼び出すかどうかのオプションを指定できるのも便利。 特にUIに関するものは、SSR時にwindowやdocumentが参照できないためエラーとなることがあるので注意です。
日本語ガイドだとここのこと。

モジュールモードでのVuex

Vuexにはクラシックモードモジュールモードがあります。

クラシックモードでは、自身でVuexを読み込み、ストアインスタンスを生成してVuexストアを構築します。
一方、モジュールモードは、規約に沿って記述するだけで、Nuxt.jsが勝手にVuexストアインスタンスの生成を行ってくれます。 モジュールモードで書くっきゃないですね、便利!!

Nuxt.jsの日本語ガイドにも記載されているので、分からない方は一読するのをオススメします。

PixiJSを入門しはじめた

アニメーションとか表現豊かなものは苦手なのですが、克服するためにもPixiJSに入門してみました。

以下に作ったものをドンドンコミットしていく予定ですが、今はひたすら人のソースをコピーして触って壊しての繰り返しです。 github.com

上記プロジェクト(Nuxt + PixiJS + GitHub Pages + Travis CI) の公開もしてみました。
GitHub Pagesも、Travis CIも初めてだったんですが、Nuxt.jsのガイドのおかげで割りとサクッとすぐできました。
助かりますmm
URL: https://yagisuke.github.io/nuxt-pixi/

以上、終わります。

Vue.js 入門を読んだ

週報のように書いていく予定だったんですが、前回の更新から早1ヶ月。 気を取り直して、 GitHub だったり、このブログで アウトプットしていきたいと思います。 お山なブログ も更新したいな。

2018/09/23 - 2018/10/21

今年は台風(2018年の台風)が多かった。 多かったように思っていたが、発生数は例年とあまり変わりはなく、 上陸したものが例年より多かったんだとか。

その頃僕はこんなことやっていた

Vue.js 入門を読んだ

業務ではNuxt.jsを使ってWebアプリケーションを作っています。 Vue.js を触ったこともないまま Nuxt.js を書きはじめた人なので、 だいぶ Vue力に不安があり、日本のVue.js を牽引している方々が 出版したと聞いて速攻で購入させていただきました。
gihyo.jp

ここでは、この本で新たに知った、事柄を記載していこうと思います。

コンポーネント命名ケバブケースの利用を推奨

コンポーネントは、「ケバブケース」と「パスカルケース」で書くことができます。 どちらでも書くことはできますが、著者はケバブケースで命名することを推奨していました。 Web ComponentsのCustom Elementsのドラフトの仕様が、ケバブケースで定義しており、 Vue.jsのコンポーネントは、Custom Elementsの仕様を元に作られているからです。

ケバブケース
 <kebab-component>けばぶ</kebab-component>
パスカルケース
 <PascalComponent>ぱすかる</PascalComponent>

参照: p.84, 93

v-modelの修飾子<.lazy>の挙動

v-onの.preventや.stopと同じように、v-modelにも修飾子があります。
そして、Vue.jsのガイドでは、.lazyの挙動は以下のように記載されています。

デフォルトでは、 v-model は各 input イベント (上記の IME 確定前を除いて) 後に、データと入力を同期します。 change イベント後に同期するように変更するために lazy 修飾子を追加することができます

.lazyの挙動を見てみると、リアルタイムにデータを更新するわけではなく、 以下のようにデータを更新しています。

  • 入力エリアからフォーカスを外したタイミング
  • 入力してEnterキーを押下したタイミング

f:id:yagi_suke:20181021233853g:plain

参照: p.68

v-onの修飾子<.native>を使った親コンポーネントのイベントを発火

これまで子コンポーネントから親コンポーネントのイベントを発火するには、

  • propsを使用したイベントの発火
  • emitを使用したイベントの発火

の2通りだと思っていたんですが、.nativeを使ってもできるんですね。 考えてみると、 <nuxt-link to="/" @click.native="onClick">リンク</nuxt-link> のように、 ページ遷移前にイベント挟みたい時によく使う!!って後になって気づきました。

propsを使用したイベントの発火

// 親コンポーネント
<template>
  <BButton :on-click="onParentEvent" />
</template>
<script>
import BButton from '@/components/b-button'
export default {
  components: { BButton },
  methods: {
    onParentEvent() {
      console.log('親のイベント')
    }
  }
}
</script>

// 子コンポーネント
<template>
  <button type="button" @click="onClick">
    <slot>Bボタン</slot>
  </button>
</template>
<script>
export default {
  props: {
    onClick: {
      type: Function,
      default: () => {}
    }
  }
}
</script>

emitを使用したイベントの発火

// 親コンポーネント
<template>
  <BButton @on-click="onParentEvent" />
</template>
<script>
import BButton from '@/components/b-button'
export default {
  components: { BButton },
  methods: {
    onParentEvent() {
      console.log('親のイベント')
    }
  }
}
</script>

// 子コンポーネント
<template>
  <button type="button" @click="$emit('on-click')">
    <slot>Bボタン</slot>
  </button>
</template>
<script>
</script>

.nativeを使用したイベントの発火

// 親コンポーネント
<template>
  <BButton @click.native="onParentEvent" />
</template>
<script>
import BButton from '@/components/b-button'
export default {
  components: { BButton },
  methods: {
    onParentEvent() {
      console.log('親のイベント')
    }
  }
}
</script>

// 子コンポーネント
<template>
  <button type="button">
    <slot>Bボタン</slot>
  </button>
</template>

<script>
</script>

みんなどの方式で統一しているんだろう。

参照: p.101

リダイレクト・エイリアス

routingの設定のお話しです。 リダイレクトはよく404ページの表示で使うと思うんですが、 エイリアスの方は初めて知りました。

エイリアス

エイリアスは、URL上はアクセスした時のものを保持し、 別のルートで定義したものとして遷移の処理を実行させたい時に使用します。 以下だと、 /b にアクセスすると、URL上は /b のままですが、 コンポーネントAがレンダリングされ、 /a にアクセスしたように振る舞います。

var router = new VueRouter({
  routes: [
    { path: '/a', component: A, alias: '/b' },
    { path: '/c', component: C, alias: ['/d', '/e'] }
  ]
})

リダイレクト

リダイレクトも載せておきます。 きっと見れば理解できると思います。

var router = new VueRouter({
  routes: [
    { path: '/a', redirect: '/b' },
    { path: '/b', component: B },
    { path: '/notfound', component: Notfound },
    { path: '*', redirect: '/notfound' }
  ]
})

参照: p.146

堅牢な開発スタイルを学ぶことができる

後半の8章からはTDDで簡単なアプリを作っていきます。 単体テストChai, Mocha, Sinon, Karma を使用し、component、store、routingをそれぞれ作っていきます。 また、NightWatchを使用したE2Eテストも行うので、現場以上に堅牢な開発スタイルを学ぶことができます。
写経したソース: GitHub

最後に

たらたらとダラダラと書きなぐって見ましたが、見づらいですね。
読み始めは、Vue.jsの日本語ガイド読めば読む必要のない本かなと思ったんですが、 テストの書き方とかVue.jsによるWebアプリ開発のフローをまるごと学ぶことができる良書だと感じました。 Vue.jsに興味がある方は一回手にとることをオススメします。

もくもく会に参加

家では集中できないので、普段はカフェで作業しています。 カフェだと、wi-fiがなかったり、コンセントがなかったり、狭苦しかったりで ストレスフルになることもしばしば。 なので最近は、connpassで募集されているもくもく会に参加しています。

最近参加したのだと、ここらへん。 crowdworks.connpass.com weeyble-creative.connpass.com weeyble-creative.connpass.com

同じエンジニアが休日に勉強しているのは、刺激もらえて良いですね。 ただ、段々もくもく会を探すのもめんどくさく感じてきており、 良さげなコワーキングスペースがあれば会員になっちゃおうかと検討しています。

Firebase Meetupに参加

業務で作っているアプリは、Firebaseをフル活用しているので そろそろ自分もしっかりインプットせねばと思い、参加してきました。 firebase-community.connpass.com

来月14日には、今月末にプラハで開かれるFirebase Summitの報告会も行われるそうです。 きっと新機能載せてくるだろうなー、楽しみです。 firebase-community.connpass.com

Clean Coderを読んでみた

Vue Fes Japan が11月上旬にあり、

と、vueまわりのイベントが目白押し。
本日予約していたVue.js入門が届いてその重さにびっくり、、!!
内容もしっかりずっしりそうなので、来週から読み進めてみます^^

2018/09/17 - 2018/09/22

自民党の総裁選は、知らぬ間に安倍晋三さんが3選を果たしていた。 また、格闘家で神の子KIDとして愛された山本KID徳郁選手が亡くなった。 2004年大晦日魔裟斗選手との試合は名勝負でした。

その頃僕はこんなことやっていた

Clean Coder プロフェッショナルプログラマへの道

Clean Coder を読んだ。
www.kadokawa.co.jp

本書では、筆者のボブおじさん( Robert C.Martinさん)の実体験から得た、 プロのプログラマーに欠かせない態度、規律、行動について書かれています。 今回は特に私が心がけたいことや、気になったところを備忘録として残します。

すべてのプログラマが最低限備えるべきスキル

最低限備えましょう!!

TDDの3大原則

  1. 失敗するユニットテストを書くまでプロダクションコ ードを書いてはいけない。
  2. テストを失敗させる目的以外でユニットテストを書いてはいけない(コンパイルできないのも失敗に含む)。
  3. 失敗しているユニットテストが成功するまで他のプロダクションコ ードを書いてはいけない。

TDDはこういうものだっていうのは理解しつつも、 テスト書こうなってところから。

「ボ ーイスカウトの規則 」来た時よりも美しく

ソフトウェアプロジェクトの基本的な前提として、ソフトウェアは変更しやすいというものがある。 ソフトウェアが柔軟でないと、数日かかっていた作業が、数週間、数か月とかかるようになる 。 マネジメントは、最初の勢いを取り戻そうとして、開発者を投入する。 しかし、それでは火に油をそそぐようなもので、開発者を追加すれば 、 構造の欠陥は深刻化し、障害が頻繁に発生するようになる 。

ソフトウェアを変更しやすく維持するには、モジュールを目にしたら、 構造を改善するような小さくて軽めの変更をする。 コードを読んだら、構造を調整する。 つまり、来た時よりもモジュ ールを美しくすること。 「容赦ないリファクタリング 」「ボ ーイスカウトの規則 」を常に実践すること。 それをやるためにも、しっかりTDDしましょうね!!

プロジェクトの周りにチームを作るのではなく、チームにプロジェクトを割り当てる

メンバー同士の関係作りからはじめ、お互いの変な癖、長所、短所を学び合い、お互いの協力の仕方を学ぶ。 チームがお互いの違いを認め合い、ゲル状の(絆の強い)チームになるには半年から一年と長い時間を必要とする。 だが、この状態になれば、「一緒に問題を解決する」「一緒に課題に向き合う」「一緒に仕事を成し遂げる」。

プロの開発組織は、プロジェクトの周りにチ ームを作ることはせず、 既存のゲル状のチームにプロジェクトを割り当てる。 ゲル状のチームは、同時に複数のプロジェクトを受け持つこともできる。 考え・スキル・能力に応じて作業を配分するのだ。

Tokyo Game Show 2018

会社からのススメでTGSに行ってきた。
expo.nikkeibp.co.jp

可愛いコンパニオンがいっぱい。
コンパニオンに見惚れていたら、財布がなくなり...
帰り際に見つかって一安心。

TGSの感想

私はゲームというものが嫌いだ。 ゲーム機はゲームボーイから買ったこともない。 スマホのアプリでゲームなんてやりたくもない。 目は疲れるし、なんと言っても知らない間に時間を 大量に消費するのがもったいない、そう感じていた。

しかし、ブースでウィニングイレブンをやってみて、 学生時代に友達の家でワイワイゲームをやっていた頃を思い出し、 人と時間を共有できるゲームって楽しいなと。

上京して、一人暮らしになって、家庭ができて、 気軽に自宅に友達を呼んでゲームができなくなっても、 インターネットで人と時間を共有してゲームができる。

そんな時代の変化を、大分みんなから乗り遅れたけど肌で体験できて よかったなと思えるイベントとなりました。

dotinstallでiOSアプリ開発に入門してみた

最近、まわりの人たちのアウトプット活動が盛んなので それに便乗してちょっとしたことでも書いていこうと。
まわりの環境って本当に大事。

2018/09/10 - 2018/09/16

大坂なおみ選手がUSオープンで優勝し、 樹木希林さんが亡くなり、 安室ちゃんが引退した。 安室ちゃんのイベント も終わり、 ヒカリエも明日から少し寂しくなりそうだなぁ。

その頃僕はこんなことやっていた

dotinstallでiOSアプリ開発に入門してみた

ネイティブアプリでちょっと触ってみたいと上司に言ってみたところ、 dotinstall iOSアプリのレッスンを勧められた。

dotinstall のiOSアプリ開発のコースは全8レッスン。
Xcodeの使い方や、Swiftの文法、オートレイアウト、WebView、 あとは以下のような簡単なアプリ開発を数本やる感じ。

f:id:yagi_suke:20180917231440g:plain

僕は Udemy や dotinstall 等の動画でとりあえず写経して、動かして、 その後Documentや他人のgithubを眺めて勉強するスタイルが結構気に入ってる。

dotinstall のレッスンは終わったので、次はこの本でも 読んで基礎固めしていこうと思っています。

Speeeさんのもくもく会に行ってみた

speee.connpass.com

Speeeさんのお洒落スペースを1日中使いたい放題。
休日勉強したいけど、一人だとグダグダしちゃう僕にはとっても素敵な環境でした。
しかも、美味しいコーヒーに、美味しいお昼も無料。。。 もう感謝しかりません😭😭😭 機会があればまた参加したいなと思います。

終わり。

Real World HTTPの輪読会をした part2

yagisuke.hatenadiary.com

で、「HTTP REAL WORLD」の7章のメモを記載したが、 2章のメモもあったので記載します。

HTTP/1.0のセマンティクス:ブラウザの基本機能の裏側

1章ではHTTPの基本機能が紹介された - メソッドとパス - ヘッダー - ボディー - ステータスコード

Webの高度化にともない多くの機能が追加されているが、 特にヘッダーで多くの機能が実現されている. ブラウザがこれらの基本要素をどのように応用して 基本機能を実現しているのかを2章では紹介しています.

フォーム送信について

  • シンプルなフォームの送信(x-www-form-urlencoded)
  • フォームを使ったファイルの送信(multipart/form-data)

シンプルなフォームの送信(x-www-form-urlencoded)

フォームを使ったPOST送信にはいくつかあるが、一番シンプルなものから紹介.

<form method="post">
  <input type="text" name="title">
  <input type="text" name="atuhor">
  <input type="submit">
</form>
$ curl -v --http1.0 -d title="Books Title" -d author="Books Author" http://localhost:18888

例: https://beauty.hotpepper.jp/catalog/ladys/

検索結果の並び順を変えるとフォームを使ってPOST送信され、 Content-Type:application/x-www-form-urlencoded が設定される.

urlエンコードについて

ブラウザは RFC1866 で定める変換フォーマットに従って変換をおこなうため、 以下の項目以外はエスケープが必要になる. - アルファベット - 数値 - アスタリスク - ハイフン - ピリオド - アンダースコア

GET送信の場合

POSTと違い、GETの場合はボディではなく、クエリーとしてURLに付与される.

フォームを使ったファイルの送信(multipart/form-data)

フォームを使ったPOST送信にはいくつかあるが、一番シンプルなものから紹介.

<form method="post" enctype="multipart/type">
  <input type="text" name="title">
  <input type="text" name="atuhor">
  <input type="file" name="sample">
  <input type="submit">
</form>
$ curl -v --http1.0 -F title="TITLE" -F auhtor="AUTHOR" -F attachment-file@test.txt  http://localhost:18888

参考:
フォームによるファイルアップロードの仕様
https://www.javadrive.jp/servlet/fileupload_tutorial/index2.html

300番台のリダイレクトの懸念事項

リダイレクトには懸念事項もある.

  1. URLは2000文字を目安にするべき(GETのクエリーには送信データ量に制限がある)
  2. データがURLに入るため送信した内容がアクセスログに残りセキュリティ的に懸念がある

上記回避策としてフォームを利用したリダイレクトがある.

自動リダイレクトするフォーム

<hrml>
<body action="next" onload="document.forms[0].submit()">
  <form method="post">
    <input type="hidden" name="id">
    <input type="hidden" name="password">
    ....
    <input type="submit">
  </form>
</body>
</hrml>

コンテントネゴシエーション

サーバーとクライアントは別々に開発されているため、両者が期待する形式や設定が常に一致しているとは限らない. そのため、1リクエストの中で両者がベストの設定を共有する仕組みが必要となり、それをコンテントネゴシエーションという. コンテントネゴシエーションはヘッダーを利用する.ネゴシエーションする対象とヘッダーは以下の通りとなっている.

リクエス レスポンス ネゴシエーション対象
Accept Content-Type MIMEタイプ
Accept-Language Content-Language 表示言語
Accept-Charset Content-Type 文字のキャラクターセット
Accept-Encoding Content-Encoding ボディーの圧縮

Accept: ファイル種類の決定

ChromeのAcceptは以下の通り. accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

わかりやすい画像を例に

  • image/webp
  • image/apng
  • /;q=0.8

q は品質係数と呼ばれ、0〜1で設定し、デフォルトは1となっている. これは優先度の高さを表し、サーバーは優先度が高く、対応しているフォーマットから返す. もしお互いに一致しているものがなかったら、406 Not Acceptableエラーとなる.

補足:

  • webp -> Googleが推奨するpngよりも2割程ファイルサイズが小さい画像フォーマット.
  • apng -> アニメーションするpng. gifに取って代わる次世代の新しい画像フォーマット.

Accept-Language: 表示言語の決定

GitHubのAccept-Languageは以下の通り.
Accept-Language:ja,en-US;q=0.8,en;q=0.6

ja,en-US,enの順でリクエストを送る. 言語情報を収める箱としてContent-Languageがあるが定義されているが 多くのWebサイトではそれを使っていなく、次のようにhtmlタグの中で返しているページが多いらしい. GitHubjaの日本語設定高くしているのって、時期に日本語対応してくれるのかなと思った.

<html lang="en">

Accept-Charset: キャラクターセットの決定

ヘッダーはご想像どおり以下のような感じ.
Accept-Charset: UTF-8,SHIFT_JIS;q=0.7,*;q=0.3

全キャラクターセットのエンコーダをブラウザが内包しているため、 モダンブラウザはAccept-Charsetを送信していない. なので、事前にネゴシエーションする必要がなくなったみたい.

HTMLのはHTTPヘッダーと同じ指示をドキュメントの内部に埋め込んで返すための箱.

<meta charset="UTF-8">

使用できるキャラクターセットはIANAで管理されている.
著者が一番言いたげなのはUTF-8, SHIFT_JISなど区切り文字を なぜ統一しなかったんだ...ということのように思えてきた.

Accept-Encoding: ボディーの圧縮

ボディーの圧縮は圧縮による通信速度の向上のためにも積極的にやってください. 圧縮してそれを展開してっていう処理を入れても、圧縮しない時よりも、Webページ表示までにかかるトータルの処理速度は早くなる.

  • ブラウザ利用者にとって転送速度がはやくなる
  • データ量が減ることで通信料金も安くなる

リクエスaccept-encoding:gzip, deflate, br

レスポンス content-encoding:gzip

$ curl --http1.0 --compressed http://localhost:18888

補足: - Brotli(br) -> gzipよりも効率が良い新しい圧縮フォーマット

クッキー

Webサイトの情報をブラウザ側に保存する仕組み.
クッキーもHTTPのヘッダーをインフラとして実装されている.

$ curl -v --http1.0 -c cookie.txt -b cookie.txt http://localhost:18888

-c: 指定したファイルにcookieを保存
-b: 指定したファイルと指定したkey:valueをcookieとして送信

クッキーの間違った使い方

永続性の問題

シークレットモード、改ざん、etc..、確実に保持されるものではないので、 なくなっても困らないもの、サーバーの情報から復元できるもの以外は保存しないこと.

容量の問題

容量制限がある(4Kバイトほど)、リクエスト/レスポンスのヘッダーに入るため速度が劣化するなどの問題もある.

セキュリティの問題

secureオプションを付与すればHTTPSでしか送受信されないが、HTTPの場合は平文で送受信される. パスワードや個人情報など見えて困るものを入れると情報漏洩の問題となるし、書き換えも容易なので誤動作につながるような情報は入れないようにすること.

クッキーに制約をあたえる

クッキーは特定のサービスを利用するためのトークンとして利用することが多いため、 クッキーを本来必要としないサーバに送信することはセキュリティリスクを高めることにつながる. そのため、送信先の制御や寿命を設定するような属性が存在し、HTTPクライアントはこれらの属性を解釈し、クッキーの送信を制御する責務がある.

Expires, Max-Age属性

クッキーの寿命を設定する属性.

Domain属性

クライアントからクッキーを送信する対象のサーバー. 省略時はクッキーを発行したサーバー.

Path属性

クライアントからクッキーを送信する対象のサーバーのパス. 省略時はクッキーを発行したサーバーのパス.

Secure属性

HTTPS接続での安全な接続以外は、クライアントからサーバーへのクッキー送信をしない.

HttpOnly属性

CookieJavaScriptから触ることができないようにする属性. クロスサイトスクリプティングなど、悪意のあるJavaScriptが実行されるリスクを守る.

SameSite属性

RFCには存在しない属性. リクエストの起因となったオリジンと、リクエスト先のオリジンが異なるようなリクエストには送信しないように設定する属性.
参考: http://qiita.com/flano_yuki/items/b87b2c28db0b056665ef#same-site-cookies

認証とセッション

ユーザ名とパスワードを入力してログインすることを認証といい、 サービス側はその認証情報をもとに、誰がアクセスしているかを特定する.

  • Basic認証
  • Digest認証
  • クッキーを使ったセッション管理

Basic認証

ユーザ名とパスワードをbase64エンコーディングしたもの. SSL/TLSを使っていないと、通信を傍受されたら簡単にユーザ名とパスワードが漏洩する.

$ curl -v --http1.0 --basic -u user:pass http://localhost:18888

ヘッダーにはAuthorization: Basic dXNlcjpwYXNzが付与される.

Digest認証

Basic認証より強固なものが、ハッシュ関数(A->Bは簡単だが、B->Aは簡単には計算できない)を利用したDigest認証. 認証対象画面へアクセスすると401認証エラーを返し、承認ダイアログを表示する.

www-Authenticate: Digest username="ユーザ名" realm="エリア名", nonce="0123456789", algorithm=MD5, qop="auth"

クッキーを使ったセッション管理

Basic・Digest認証は現在はあまり使われていない理由

  • 特定フォルダ配下を認証しないと見せないという使い方しかできない.
    ログインしてもしなくても良い画面とかできない
  • ログイン画面がカスタムできない.
    画像表示: https://point.recruit.co.jp/member/login/
  • 明示的にログアウトできない.
  • ログインした端末の識別ができない.
    Googleとかだと新しい端末からアクセスしたら警告メールがきますよね

クッキーとセッションを使った認証管理が主流

認証の流れとしては以下の通り 1. クライアントは、フォームでユーザ名とパスワードを送信
ユーザ名とパスワードは直接送信するのでSSL/TLSでないと簡単に漏洩するので注意 2. サーバ側ではユーザ名とパスワードで認証し、問題がなければセッショントークンを発行し、DBに保存 3. トークンはクッキーとしてクライアントに返却 こっちの方がわかりやすい:
http://qiita.com/hththt/items/07136ad74127999df271

プロキシ

プロキシはHTTPなどの通信を中継する仕組み.

プロキシサーバ導入のメリット

  1. 送信元を隠す
    Proxy を介して通信する事で、WEBページにとってはProxy が送信元として捉えられる. この為、送信元を隠す目的で使用される. 例えば、アメリカのProxyを使えば、アメリカからアクセスしているように思わせる事も可能.
  2. セキュリティ
    大企業などでは、社内からInternet を閲覧する際に、必ずと言って良いほど、Proxy を使って通信をさせてる. コレは、Proxy を中継させる事で、社員のアクセス管理を行う事が可能となり、不要なサイトへのアクセスを禁じたり、アクセスの統計を取得したりする目的で使われている.
  3. キャッシュサーバ
    Proxy の役割は、『代理サーバ』とは別に『キャッシュサーバ』としての役割を持つ. 通常、クライアントのブラウザなどにもこの『キャッシュ』機能は搭載されているが、その巨大版です。
$ curl -v --http1.0 -x http://localhost:18888/helloworld/ -U user:pass http://example.com/helloworld/

GET http://example.com/helloworld/ HTTP/1.0 / Host: example.com

$ curl -v --http1.0 http://localhost:18888/helloworld/

GET /helloworld/ HTTP/1.0 / Host: localhost:18888

キャッシュ

Webサイトのリッチ化に伴い、読み込みファイル数・サイズが増加傾向にある. 通信回線が速くなっても、毎回読み込んでいては表示速度が遅くなってしまう. キャッシュは、ダウンロード済みで内容に変化がなければ、新たに読み込むのではなく、 ダウンロード済みのものを表示してパフォーマンスをあげる仕組みである.

更新日時によるキャッシュ

HTTP1.0のキャッシュの仕組み. 当時は静的コンテンツがメインだったので、コンテンツの新旧を比較するだけで事足りていた.

仕組み

サーバーは、コンテンツの最終更新時刻をレスポンスヘッダのLast-Modifiedに入れて送信する. ブラウザ側はこのコンテンツの最終更新時刻を覚えておき、 次回リクエストした際にリクエストヘッダのIf-Modified-Sinceの中に含めて送信する. サーバー側のコンテンツに変更がなければサーバーはステータスコード304 コンテンツ未更新ステータスコードを送り ブラウザはキャッシュされたコンテンツを表示させるという仕組み.

Expiresによるキャッシュ

更新日時によるキャッシュの場合、キャッシュの有効性を確認するためにどうしても通信が発生する. その通信自体をなくす仕組みがHTTP1.0に追加されたExpiresによるキャッシュ.

仕組み

Expiresはレスポンスヘッダのひとつで、新しいファイルが存在するかどうかを確認することなく、Expiresの期限内であればブラウザでキャッシュ済みのファイルを強制的に適用する.

コンテンツが日々変わるページには不向きで、あまり変更の入らないcssやjsファイルとかによく使われる.
https://beauty.hotpepper.jp/svcSA/

Pragma: no-cache

クライアントからプロキシに対して指示を送ることもある. 実装依存の命令を含むリクエストヘッダーの置き場として、 HTTP1.0からPragmaヘッダーが定義された(no-cacheしか設定できない). リクエストしたコンテンツがキャッシュされていたとしても、 本来のサーバーまでリクエストを届けるようにするための仕組み.

HTTP/1.1ではCache-Controlにマージされました.

ETagの追加

同じ画面にアクセスしてもユーザの状態によって、コンテンツの内容が異なる場合がある. 例えば、ログイン前後や、会員ステータス(プレミアム会員、会員、会員ではない)でコンテンツを出し分ける場合など. このように動的に変更する要素が増えれば増えるほど、どの日時を根拠にキャッシュの有効性を判断すれば良いのか判断が難しくなる. その場合に使用できるのがHTTP/1.1で定義されたETagヘッダー.

仕組み

ETagはレスポンスヘッダのひとつで、 初回アクセス時に、サーバーはレスポンスにETagヘッダーにハッシュ値を付与する. ブラウザは2度目以降のアクセス時にIf-None-Matchヘッダーにダウンロード済みのETagの値をつけてリクエストする. サーバーはIf-None-Matchとこれから送りたいファイルのETagとを比較し、同じなら304 コンテンツ未更新を返し、ブラウザはキャッシュされたコンテンツを表示させるという仕組み.

ETag:"6307c-553dda1253000"
参考: https://www.ponparemall.com/

Cache-Control(1)

ETagと同時期にHTTP/1.1で追加されたのが、Cache-Control. Expiresよりも優先されるキャッシュの仕組み. まずはサーバーからレスポンスとして送付されるヘッダーについての紹介.

ディレクティブ 説明
public 複数ユーザーで共有できるようにキャッシュしてよい(プロキシOK, ブラウザOK)
private 特定ユーザーだけが使えるようにキャッシュしてよい(ブラウザOK)
max-age=n キャッシュの鮮度を秒で設定.86400を指定すると、1日キャッシュが有効でサーバーに問い合わせることなくキャッシュを利用する.それ以降はサーバーに問い合わせを行い304 コンテンツ未更新が返ってきた時のみキャッシュを利用する.
s-maxage=n max-ageと同等だが、共有(プロキシの)キャッシュに対する設定値
no-cache 一度キャッシュに記録されたコンテンツは、現在でも有効か否かをサーバに問い合わせて確認がとれない限り再利用してはならない、という意味
no-store キャッシュしない

参考:

Cache-Control(2)

リクエスト時にプロキシに対してキャッシュに関する指示をだす

Cache-Controlヘッダーをリクエストヘッダーに含めることでプロキシへ指示することができる. まずはクライアント側からリクエストヘッダーで使える設定値を紹介.

ディレクティブ 説明
no-cache Pragma: no-cacheと同等
no-store レスポンスのno-storeと同じで、プロキシサーバにキャッシュを削除するように指示する
max-age プロキシで保存されたキャッシュの有効期限を設定
max-stale キャッシュされたリソースの有効期限が切れていても指定時間内であればキャッシュを受け入れるよう設定
min-fresh 指定された時間は新鮮であるものを返すようにプロキシに要求する.逆に、指定時間内で有効期限が切れるリソースはレスポンスとして返せない.
no-transform コンテンツを改変しないようにプロキシに要求する.例えば、画像の圧縮とか
only-if-chached キャッシュからのみデータを取得するという指示で、設定時には初回をのぞいてオリジンサーバーへのアクセスは一切行わない

レスポンス時にプロキシに対してキャッシュに関する指示をだす

レスポンスヘッダーでサーバーがプロキシに対して送信するキャッシュ制御の指示についての紹介. 補足をすると、Cache-Control(1)で紹介したディレクティブもすべてプロキシに対して有効.

ディレクティブ 説明
no-transform プロキシがコンテンツを改変するのを抑制
must-revalidate no-cacheとほぼ同じだが、プロキシへの司令となる.キャッシュが期限切れだった場合、オリジンサーバでの確認無しにキャッシュを利用してはならない
proxy-revalidate must-revalidateと同じだが、共有キャッシュのみに対する要請

参考

Vary

ETagの説明では同じURLでも個人ごとに結果が異なるケースについて紹介された. 同じURLでもクライアントによって返す結果が異なることを示す場合はVaryを使用する.

仕組み

例えば、サーバがクライアントのUser-Agentリクエストヘッダーによって返す内容を変えているとする.この場合、サーバから返されたデータをproxyが素直にキャッシュしてしまうと、別のUser-Agentがproxyにアクセスしたときにサーバが意図しないデータがクライアントに返されてしまう危険がある.

その場合、レスポンスヘッダにVary: User-Agentが指定されていれば、 proxyはUser-Agentによって内容が変わることを知ることができるので、 キャッシュをしないとか、User-Agent毎に異なるキャッシュを保持するといった対応が 可能となる.

リファラ

ユーザーがどの経路からWebサイトに来たのかをサーバーが把握するために、 クライアントがサーバーに送るヘッダーをリファラーという.

Referer:https://www.google.co.jp

注意:
referrer ではなく referer.
スペルミスのままRFCに定義されちゃったらしい.

リファラーを制御する(1)

ユーザの通信内容を秘密にするHTTPSがHTTP/1.1から追加された. 保護された通信内容が保護されていない通信経路に漏れるのを防ぐため、 クライアントはリファラーの送信に制御を加えることをRFCで定められている.

アクセス元 アクセス先 送信するかどうか
HTTPS HTTPS する
HTTPS HTTP しない
HTTP HTTPS する
HTTP HTTP する

リファラーを制御する(2)

リファラーを制御する(1)を厳密に適用すると、サービス間に支障が出ることもあり、 リファラーポリシーなるものが提案され、現在ドラフトステータスとなっている.

困る事例: http://web-tan.forum.impressrd.jp/e/2015/04/14/19750

リファラーポリシーは以下の方法で設定できる.

  • Referrer-Policyヘッダー
  • <meta name="referrer" content="設定値">
  • aタグなどいくつかの要素のreferrerpolicy属性および、rel="noreferrer"属性
  • Content-Security-Policyヘッダー(廃止された模様)

リファラーポリシーとして設定できる値には次のようなものがある

  • no-referrer
    一切おくらない
  • no-referrer-when-downgrade
    現在のデフォルト動作と同じで、HTTPS→HTTP時は送信しない
  • same-origin
    同一ドメイン内のリンクに対してのみ、リファラーを送信
  • origin
    詳細ページではなく、トップページからリンクされたものとしてドメイン名だけを送信
  • strict-origin
    originと同じだが、HTTPS→HTTP時は送信しない
  • origin-when-crossorigin
    同じドメイン内ではフルのリファラーを、別ドメインにはトップのドメイン名だけを送信
  • strict-origin-when-crossorigin
    origin-when-crossoriginと同じだが、HTTPS→HTTP時は送信しない
  • unsafe-url
    常に送信

リファラーポリシーについてはこの記事がよくまってる
http://qiita.com/wakaba@github/items/707d72f97f2862cd8000

検索エンジン向けのコンテンツのアクセス制御

クローラー向けのアクセス制御の方法として、主に2つの手法が広く使われている.


参照: https://digital-marketing.jp/seo/sitemap-xml-and-robots-txt/

robots.txt

  • robots.txtファイルの用意
  • robots meta tagの設定

robots.txtはクロール最適化のために行うもの. 一方、robots meta tagは一つ一つのページのインデックスを最適化するために行うもの.
参照: https://bazubu.com/robots-txt-16678.html

robots.txtファイルはドメインのルートディレクトリに設置する必要がある. つまり、サブディレクトリ型のレンタルウェブスペースに設置されているサイトでrobots.txtファイルを使うことはできない.
参照: http://whitehatseo.jp/robots-txtの記述例と使い方を解説します/

robots.txtファイルの用意

robots.txtは、サーバーのコンテンツ提供者が、 クローラーに対してアクセスの許可・不許可を伝えるためのプロトコル. robots.txtは以下のような形式で読み込みを禁止するクローラーの名前と場所を指定する.

User-agent: *
Disallow: /cgi-bin/
Disallow: /tmp/

上記は、全クローラーに対して、/cgi-bin/フォルダと/tmp/フォルダへのアクセスを禁止している例となっている. User-agent: Googlebotのように、特定のクローラーに対しての指定も可能.

例: https://www.facebook.com/robots.txt

robots meta tagの設定

robots.txtと同じような内容をHTMLのメタタグに記述できる. robots.txtの方が優先されるが、こちらの方が細かく指定可能となっている.

<meta name-"robots" content="noindex" />

content属性にはさまざまなディレクティブが記述できる. Googlebotが解釈するディレクティブの詳細はGoogleのWebサイトに記載されている. 代表的なものを以下に示す.

ディレクティブ 意味
noindex 検索エンジンがインデックスするのを拒否する
nofollow クローラーがこのページ内のリンクを辿るのを拒否する
noarchive ページ内のコンテンツをキャッシュするのを拒否する

同じディレクティブはHTTPのX-Robots-Tagヘッダーにも記述できる X-Robots-Tag: noindex, nofollow

サイトマップ

サイトマップはWebサイトに含まれるページ一覧とそのメタデータを提供するXMLファイル. Flashを使って作られたコンテンツや、JavaScriptを多用して作られた動的ページからのリンクなど、 クローラーの実装によってはページが発見できない場合でもサイトマップによって補完できます.

<?xml version="1.0" encoding="utf-8">
<urlset xmls="http://www.sitemaps.org/schemas/sitemap/0.9"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
    http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
  <url>
    <loc>http://example.com</loc>
    <lastmod>2006-11-18</lastmod>
  </url>
</xml>

このurlタグを登録したいページ数分作成します. locタグには絶対URLを指定する.

サイトマップは前述のrobots.txt内にも記載可能。 また、各検索エンジンに対してXMLファイルをアップロードする方法がある。 Googleの場合はSearch Consoleサイトマップツールを使う

Sitemap: https://beauty.hotpepper.jp/sitemap.xml