コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

多くのブラウザはHTMLのheadにfaviconに関する記述がないと/favicon.icoに取得をしようとする

当たり前の話なんだけど、暗黙の仕様の様子なので結果をまとめる

TL;DR

  • どのブラウザもファビコンのデータが欲しいので明示的にない場合は取得しにいく
  • ブラウザごとにタイミングは異なるが、大体はページのHTMLを取得したあと
  • 最後にアクセスしたページをCookieに保存しようとすると、favicon.icoへのアクセスになる可能性があるので気をつける

favicon自体の挙動

2022年現在ではHTML Living Standardで、faviconの指定は <link rel="icon"> で指定できるようになっている(参考:faviconの仕様はHTML5から標準化されている - コード日進月歩

そのためブラウザに記述があればその指定されているパスのデータを取得する動作をする。

ただし、指定がない場合は / 配下にある favicon.ico を探し、ファイルがあればそれを使用する。これはfaviconの仕様の始祖であるIEがそういう動きだったことに由来すると思われる。(一種のデファクトスタンダード

詳しくは英語版のwikipediaにてまとめられているのでそちらを参照のこと。

faviconを取得するタイミング

前項で紹介したwikipediaにも記載があるが、多くのモダンブラウザでは「タブバー」もしくは「アドレスバー」にfaviconを出す仕様となっているので、ページを表示する場合にはほぼ確実にfaviconを取得する。そのため多くのブラウザでは閲覧するページに<link rel="icon">がない場合、次点として /favicon.ico にアクセスし表示できるデータがないかを探していく

気をつけないといけない「最後にアクセスしたページ」という観点

この場合気をつけないといけないのは「最後にアクセスしたページ」が favicon.ico になりうるということ。

昨今のWebアプリケーションは画像のアセットが別のドメインにあったりすることが多いので大体ページのgetリクエスト以降はアプリケーションサーバにアクセスすることが少なくなったので「最後にgetのあったリクエストを最後に閲覧したページとしてみなす」としても問題なく挙動してしまうシーンはあるが、このfavicon.icoが未指定の場合はfavicon.icoが最終アクセスページとして認識されてしまう可能性がある。

そもそも論Webブラウザの挙動を認識していれば最後にアクセスしたページ = 最後にgetリクエストがあったページという関連付けが成立しないことはわかるが、認識違いを起こすこともあるので気をつけたほうがいい。

関連リンク

Rails6でpublic配下を見れるようにする設定値はconfig.public_file_server.enabled

developmentでは見れたのに、productionじゃ見れないのはなぜ…となるときに見直す設定

環境

$ bin/rails -v
Rails 6.0.4.1

想定している状況

/public配下のファイルが、RAILS_ENVがdevelopmentだと見れて、productionのときに見れないときに考える設定

Railsガイド曰く

public/ディレクトリ内の静的アセットを配信するかどうかを指定します。デフォルトではtrueが設定されますが、production環境ではアプリケーションを実行するNginxやApacheなどのサーバーが静的アセットを扱う必要があるので、falseに設定されます。 - Rails アプリケーションを設定する - Railsガイド - 3.1.35 config.public_file_server.enabled

ソースコード上も初期値はtrue

どこで設定するのか

デフォルトのRailsであれば config/environmentsRAILS_ENV別の設定

productionに関しては以下のようになっている

  # Disable serving static files from the `/public` folder by default since
  # Apache or NGINX already handles this.
  config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?

関連リンク

GoogleChromeではhttpsやwwwを表示しないのは何故かをざっくり調べる

なぜ消えるのか、という話。

情報元

https://bugs.chromium.org/p/chromium/issues/detail?id=883038#c114

バグトラッキングに記載されていること

原文を転載すると以下

The Chrome team values the simplicity, usability, and security of UI surfaces. To make URLs easier to read and understand, and to remove distractions from the registrable domain, we will hide URL components that are irrelevant to most Chrome users. We plan to hide “httpsscheme and special-case subdomain “www” in Chrome omnibox on desktop and Android in M76.

Google翻訳を駆使して和訳すると以下

Chromeチームは、UI surfacesのシンプルさ、使いやすさ、セキュリティを高く評価しています。 URLを読みやすく理解しやすくし、登録可能なドメインから気を散らすものを取り除くために、ほとんどのChromeユーザーに関係のないURLコンポーネントを非表示にします。 デスクトップのChromeオムニボックスとM76のAndroidで「https」スキームと特殊なサブドメイン「www」を非表示にする予定です。

ということで、「https」などのURIスキーム部と「www」というサブドメインはユーザのために不要な情報なため消したという判断。

関連リンク

docker-composeのコンテナ名のデフォルト名は「プロジェクト名-サービス名-インデックス番号」

Version2からルールが変更になったので、そもそもどういう挙動か調べる

挙動確認したバージョン

$ docker-compose --version
Docker Compose version v2.3.3

TL;DR

  • docker-composeで立ち上がるコンテナ名を明示的に指定しない場合 {{プロジェクト名}}-{{サービス名}}-{{インデックス番号}} となる。
  • 「プロジェクト名」は docker-composeの起動オプションで指定可能だが、ない場合は COMPOSE_PROJECT_NAME環境変数が使われる
  • COMPOSE_PROJECT_NAME は格別指定がない場合は起動ディレクトリの文字列が設定される

コンテナ名決定を司るソースコード

デフォルトのコンテナ名は以下のロジックで書かれている

func getContainerName(projectName string, service types.ServiceConfig, number int) string {
    name := strings.Join([]string{projectName, service.Name, strconv.Itoa(number)}, Separator)
    if service.ContainerName != "" {
        name = service.ContainerName
    }
    return name
}

from https://github.com/docker/compose/blob/v2/pkg/compose/convergence.go

明示的に service.ContainerName があればそれが入るが、ない場合は Separator で「プロジェクト名」「サービス名」「引数の番号」となる。このとき引数の番号は1から自動的に採番されるようになっている。

プロジェクト名とは

プロジェクト名は docker-compose -p で指定できるもの。ヘルプでは以下のような記述がある。

-p, --project-name NAME Specify an alternate project name (default: directory name)

ディレクトリ名がデフォルトになるとのことだが、これは環境変数COMPOSE_PROJECT_NAME との兼ね合いで設定されているもので、以下のような説明が公式ドキュメントにある。

この変数を設定するのは任意です。 変数を設定しなかった場合 COMPOSE_PROJECT_NAME のデフォルトは、プロジェクトディレクトリの basename となります。 コマンドラインオプション の -p も参照してください。 - Compose CLI 環境変数 — Docker-docs-ja 19.03 ドキュメント

コンテナ名を指定したい場合

指定したい場合はドキュメントにあるとおり container-name を使うと指定できる。ただし重複したコンテナ名があると立ち上がらないので注意が必要。

container_name: sukina-container-mei

デフォルト名はdocker-composeのv2から変わった

デフォルトのコンテナ名だが、昔は区切りが - ではなく _ であったが、docker-composeのversinが2になるときに変更になっている。

define compose container names with a valid hostname by ndeloof · Pull Request #8655 · docker/compose

これはhostnameとしてコンテナ名が使われるため、hostnameは _ を許容していないのでhostnameとして正しくつかえるようにするための変更だった様子。

関連リンク

サーバのホスト名に使える文字は英字、数字、ハイフンそしてドット

定義の面はわからなかったのでざっくりまとめる。

出典

出典いわく

RFC1123には以下のように記述がある。

正当なインターネットホスト名の構文はRFC952[DNS:4]で規定され、RFC1034のセクション3.5[DNS:1]で繰り返し述べられている。ホスト名構文の一つの側面をここで変更する。先頭文字の制限が緩和され、英字または数字のいずれかであれば許容されるようになる。ホストソフトウェアは、より寛容なこの構文をサポートしなければならない(MUST)。

ここをもとにRFC1034の3.5のセクションを見ると文字列ルールの定義が記載されている。ドメインの定義だが、これがホスト名と同義ということになる。

<domain> ::= <subdomain> | " "
<subdomain> ::= <label> | <subdomain> "." <label>
<label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
<let-dig-hyp> ::= <let-dig> | "-"
<let-dig> ::= <letter> | <digit>

<letter> ::= 大文字のAからZと小文字のaからzの52文字のアルファベット文字
に含まれる任意の1文字
<digit> ::= 0から9までの10の数字の任意の数字

使える文字

上記のルールにはなっているが使える文字ということで汲み取ると

  • 大文字のAからZと小文字のaからzの52文字のアルファベット文字
  • 0から9までの10パターンの数字
  • . (ドット)
  • - (ハイフン)

ということになる。

使えそうで使えない文字

これを見ると実は _ (アンダースコア,アンダーバー)は使えない、がホスト名においては許容しているケースがいくつかある。詳しくは参考リンクのサイト参照のこと。

参考リンク

「アラインをとる」というビジネス用語の意味をざっくりまとめる

HTMLの text-align が脳裏に出てきて、全然関係ない言葉だと認識するのに労力がかかったので雑にまとめる

利用シーン

「AさんとBさんに例の件はアラインしている?」

意味

本来のalignの意味は以下の通り

1.〔~を〕一直線[平行]にする[並べる] 2.〔部品などを〕調整する、調節する 3.〔大義や方針で~を〕同じ立場に置く、提携させる - alignの意味・使い方・読み方|英辞郎 on the WEB

1の意味のニュアンスである「直線に並べる」というところから転じて「揃える」という意味合いがあり、「認識を揃える」という意味で使われるケースがおおい。そのため日本語に置き換えると「アラインしている」は「認識が揃っている」、「アラインを取る」は「認識を揃える」という置き換えで認識するとニュアンスとしては合致する。

参考サイト

JavaScriptにおいてイベントハンドラに何もしないダミー関数を入れる意味と効果

Reactハンズオンラーニングを読んでいてなるほどなーと思ったのでメモ

コード例

Reactでクリックイベントを付与したオブジェクトを作る関数を作るとする

function makeClickableButton(onClickEventFunction = f => f){
  return ( <button onClick={onClickEventFunction} >this is demo button</button>)
}

f => f という形で一見すると意味のない初期値をいれるような記述が今回取り上げたい話題

どういう嬉しい効果があるのか

このような書き方にすると「引数に何もセットしなくてもエラーにならない」というのが嬉しいポイント。

仮に onClick などに undefined がセットされてしまうと、クリックするとJavaScriptのバージョンによってはでエラーが上がってしまう懸念がある。そのため、必ず何かしら関数が入るようにしておきたい。特にクリック時のイベントに関して何もセットしたくないがコンポーネント自体は出したいときなどに makeClickableButton() と呼んでも問題ない形になる。

また、 undefined の変数が来ても、中身としてエラーにはならないので、防護壁の一枚としても機能する。

記事に起こした際の余談

Reactハンズオン第2版の記述をもとに検証してみたが、実際のところ直近のブラウザではonClickイベントにundefinedなものを設定してもエラーにならないので、どこかしらのバージョンで対策がされている可能性があります。

参考