コマンドが見つかりません(command not found)の対処法

npmのプログラム(パッケージ)をインストールしても、コマンドを叩いてうまくいかないことがあります。

うまくいかなかったケース

私がハマってしまったのは、ProgateのNode.jsの「Expressのアプリケーションを作成しよう」というコラムを実践していたときです。

コラムはこちら

Node.jsの新規アプリケーションを作ろう! | プログラミングの入門なら基礎から学べるProgate[プロゲート]

npmのパッケージ、「nodemon」をインストールしても nodemon app.js でサーバー起動ができないというものでした。

インストール
・グローバル

npm install -g nodemon

・ローカル

npm install nodemon

ローカルやグローバルにインストールしたり、1回アンインストールして再度インストールしてみてもだめ。

実行

nodemon app.js

とすると、
zsh: command not found: nodemon と返ってきます。

☆後ほどグローバルでインストールして実行したところ、うまくいきました。スペルミスしていたのか、何だったのでしょう...。
めでたしめでたしですが、ここはローカルにインストールした場合で進めます。

環境

  • シェルはzsh
  • nodenvからnodeとnpmはインストール済み

原因と対処法

原因はPATHが通っていないケースが大半なのではないでしょうか。

実際、パスを付けてnodemon という実行ファイルを直接叩けば実行されました。

node_modulesフォルダのあるところまで移動して

./node_modules/.bin/nodemon app.js

です。
(ローカルにインストールしたnodemonの実行です)

毎回ここまで打つのは大変なので、その他の対処法を考えてみました。

対処法その1:PATHの設定をする

PATHの設定をすれば nodemon コマンド一つで実行できます。

Macで「zsh: command not found」が出る原因と対処法

環境変数のPATHには、実行したいプログラムのあるフォルダのパスを複数登録することができるので、そこに追加する、といったものです。

今回ローカルにインストールしたプログラム(nodemon)なので、できれば汎用的なパスだけの登録にしておきたいです。

env コマンドで環境変数(PATHなど)を確認できるということは覚えておきたいです。

以下はこちらを参考にしながらまとめていきます。
どうもありがとうございます。

知らないのは損!npmに同梱されているnpxがすごい便利なコマンドだった | Developers.IO

対処法その2:npm binを使って直接叩く

npm binはカレントプロジェクトのローカルパッケージPATHを返してくれるコマンドです。

実際にプロジェクトのディレクトリ内で npm bin と叩くと、ルートディレクトリから node_module/.bin までのパスが返ってきました。

$(npm bin)/nodemon app.js

でうまくいきました。

$() の書き方は初めて知りました。

Linuxでのドル記号「$(...)」の意味と使い方 | UX MILK

対処法3:package.jsonにscriptを追加する

nodemon のコマンドをpackage.jsonのscriptに登録して使う方法です。

npmのrun-scriptというしくみを利用します。
こちら↓には npm-script とあります。
「npmのrun-script=npm-script」なのでしょうか。

Node.jsユーザーなら押さえておきたいnpm-scriptsのタスク実行方法まとめ - ICS MEDIA

npm-scriptsとは、package.jsonファイルに記述可能なシェルスクリプトエイリアスです。エイリアスとはコマンド名を別のコマンド名に置き換えることです。

gulpを使わなくても、scriptフィールドでもりもりタスクを設定できることが分かりました。

package.json

 "scripts": {
    "nodemon": "nodemon"
  },

ターミナル

npm run nodemon app.js

で動きました。

また
package.json

 "scripts": {
    "nodemon": "nodemon app.js"
  },

ターミナル

npm run nodemon

でもOKです。

毎回サーバーを起動させるので、できる限りコマンドを短くしたい、となれば
package.json

 "scripts": {
    "start": "nodemon app.js"
  },

ターミナル

npm start

でしょうか。

ところでなぜコマンド名だけのシェルスクリプトの登録でうまく実行できるのでしょうか。

scriptsフィールドではローカルインストールしたパッケージのコマンドを直接実行できるテクニックを使用したものです。

npmのパッケージの構成ファイルであるpackage.jsonに書いたものなので、そう言われたらそうですね。

対処法4:npxをつかう

npx とは

npxはnpmパッケージを簡単に実行できるコマンドです。具体的には次のようなことができます。

  • run-scriptを使用せずにローカルインストールしたコマンドを実行する
  • グローバルインストールせずに一度だけコマンドを実行する
  • GitHubやGistで公開されているスクリプトを実行する

他の記事でも出てきた、遊び心いっぱいのパッケージで私も試してみました。

npx yosay Hello!

f:id:yokoyoko_115:20201017011821p:plain

npxでは、事前インストールせずに一度だけコマンド実行でき、実行後には削除されます。

便利便利と書かれているので便利なのでしょうが、残念ながらまだ実感できず...。パッケージをお手軽に使いたくなる日が来ますように。

気になったこと

ここまで書いていて追加で気になったことをまとめました。

パッケージとモジュールの違いについて

未だに「パッケージ」と「モジュール」の差がよくわかっていません。同じだと思っていました。

どうやら違うようなので、こちらの記事を見て自分の言葉に替えてみました。

【npm】パッケージとモジュールの違いって何? - Qiita

パッケージ

パッケージとはpackage.jsonによって記述されるファイルもしくはディレクトリのことを指します。

なので、package.jsonがある、node_moduleディレクトリ内のディレクトリたちは各パッケージなのだと思います。

モジュール

モジュールとは、Node.jsの require 機能によって呼び出すことができる node_modules 内のファイルまたはディレクトリのことを指します。

この「Node.jsの require 機能によって呼び出す」というのは、今のところgulpfile.jsで見たことがあります。

モジュールとして require 機能によって読み込まれる為には、次のいずれかである必要があります。

  • package.json を含むフォルダーであり、mainフィールドを含むファイルであること。
  • index.js というファイルが入っているフォルダであること。
  • JavaScript ファイルであること。

package.jsonname フィールドはパッケージ名、 main フィールドはメインエントリー(?)といいjsファイルやディレクトリ名が入るようです。

package.jsonの内容をまとめてみました - Qiita

これらからnodemonはパッケージでありモジュールであることが分かりました。

パッケージを特にrequire 機能によって読み込まれるものをモジュールという
考え方でいいかと思いました。

自分たちもパッケージを作っているんだ、という意識を持ちました。
いろいろなパッケージを組み合わせてオリジナルのパッケージを作っているって改めてすごい。

パッケージにはコマンドを提供されているものとされていないものがある

コマンドが提供されている場合、node_modules/.bin/ 配下にコマンドが配置されます。

このことを覚えておけば、のちのち腑に落ちそうです。

実行ファイルに拡張子がついていないのは「コマンド」として打ちやすいからなのでしょうか...。中身はjsファイルですね。 そもそも .bin とは?ってなりますが、別の機会に調べます。

最後に

今までこのような「ローカルでインストールしたのにコマンドが見つからない」、といった問題にぶつかったことないのはなぜなのだろう、と考えたところ、直接コマンドを叩く機会がなかったからだと気づきました。

Node.jsのrequireでインストールしたモジュールを読み込んで、処理のコマンドをpackage.jsonでnpm-scriptとして実行していたからです。

npm-scriptで gulp sass と何の疑問を持たずに書いてきましたが、 ここにきて gulp コマンドって何でしょうか...気になります。

なにはともあれNode.jsの理解が深まってよかったです。

これまでNode.jsは単にgulpを使うために必要なものものぐらいにしか思っていなかったので、Progateのスライドも勉強になりました。

もう少し詳しく知りたいです!

おしまい。

PHPのメール送信を考える(前編)

先日WordPressプラグイン「ContactForm7 」と「WP Mail SMTP」を使ったメールフォームを作りました。
「WP Mail SMTP」には送信元アドレスやメーラーSMTP ホストなどを設定できますが、このプラグインを使わなくても「ContactForm7 」でメールフォームを作って送信できたはず、一体何が起こっているのだろう...と気になったので調べました。

メールは奥が深い

初心者(?)がイチから調べるにはあまりにも必要な知識が多すぎる! 気になることが後から後から出てきていつも以上に収拾がつかなさそうなので、ひとまずメール送信機能を作ってみます。

環境

  • MacMAMP(ローカル環境)でメールフォームを作る
  • SMTPサーバーはMAMP内に入っていれば(?)それを使って、なければGmailを使う
  • Gmailが送信側で絡むかもしれないので、送信先アドレスはyahooにする

↑書いていることも正しいのか今の時点では怪しいですが、これでスタートします。

フォームの作り方

まずはプラグインなしのPHPでメールフォームの作り方を学びます。

お問い合わせフォームを作る | GRAYCODE PHPプログラミング

きっとこちらが一般的な作り方なのだろうと信じます。

要点は

  • form要素をaction="" と空の値の属性を入れることで、1つのPHPファイル(index.php)で入力画面、確認画面、送信完了画面を用意する
  • 入力・確認はそれぞれPOST通信でデータを送る。
  • 確認・送信ボタンにそれぞれname属性を付け、その値($_POST['name名'])で入力・確認・送信完了画面の判別をする
  • メール送信は mb_send_mail関数を使う

です。

今回は入力画面、確認画面や見た目は考えず、送信だけできるページを作ります。

index.phpの一部

<?php if(empty($_POST["btn_submit"])): ?>
  <h1>ボタンを押すと送信</h1>
  <form method="post" action="">
      <input type="submit" name="btn_submit" value="送信">
  </form>
<?php else: ?>
  <h1>送信!</h1>
  <?php mySendMail(); ?>
<?php endif; ?>

<?php
function mySendMail() {
  // 変数の設定
  $to = "xxx@yahoo.co.jp";
  $subject = "メール送信のテスト";
  $text = "メール本文です。";

  // メール送信
  mb_send_mail($to, $subject, $text);
}
?>

f:id:yokoyoko_115:20200916132118p:plain
表側はとてもかんたんなつくり

送信してみる

送信先のメールアドレスが間違っていないか、いつも以上に確認して送信ボタンを押すと...

なんと送受信ができた!ダメ元だったのに。

yahooのメールアドレス宛に送信すると迷惑メール扱いすらされず受信箱に入っていました。
gmailのメールアドレスでは迷惑メールになっていました)

index.php では設定していなかった送信者情報がメールに入っていたので、送信時にどこかで設定された値が使われたと考えられます。

mb_send_mail関数について

mb_send_mail関数は、日本語などマルチバイトの文字をメール送信する時に使う関数で、中で mail関数を呼んでいます。

mb_send_mail( $to, $subject, $text, $header, $parameter);

mb_send_mail関数の引数 $header (省略できる)には、メールヘッダーに追加する送信者情報を入れる部分があります

送ったメールがスパム判定(迷惑メール)されないためのヘッダー設定 | GRAYCODE PHPプログラミング

送信者情報(抜粋)

・Content-Type – メール形式 ・Return-Path – 送信先メールアドレスが受け取り不可の場合に、エラー通知のいくメールアドレス
・From – 送信者の名前(または組織名)とメールアドレス
・Sender – 送信者の名前(または組織名)とメールアドレス
・Reply-To – 受け取った人に表示される返信の宛先
・Organization – 送信者名(または組織名)
・X-Sender – 送信者のメールアドレス
・X-Priority – メールの重要度を表す

これらの情報は、改行コードを入れながら一つの文字列にします。

MAMPのどこかで送信者情報が設定されているはずなので調べました。

PHPのメール送信に関する設定値

MAMPのスタートページから「TOOLS > PHOINFO」のページを見るとメール送信に関連する設定がありました。

Core(一部抜粋) PHP Version 7.4.2

Directive Local Value Master Value
sendmail_from no value no value
sendmail_path /usr/sbin/sendmail -t -i /usr/sbin/sendmail -t -i
SMTP localhost localhost
smtp_port 25 25

このページは phpinfo() を実行した結果を表示させたページです。
phpinfo() では、php.ini(拡張子の読みは「イニ」が多そう)ファイルなどで設定した、PHPの設定値を見ることができます。
設定値の変更はphp.iniだけではなく、Apache側からや.htaccessからもできます。優先順位があるそうです。

ちなみに読み込んでいるphp.iniの場所は、phpinfoの「Loaded Configuration File」にあります。

phpinfo関数による設定内容の確認 | PHPインストールと初期設定

php.iniファイルの確認と修正 | XAMPPの使い方

sendmailとは

phpinfoにもあった sendmail についてです。
mb_send_mail関数では内部でsendmailコマンドが実行されます。
sendmail」というのはメール転送エージェント(MTA)というメール配信用プログラムです。「postfix」というのも同じくMTAです。

メール転送エージェント:
https://wa3.i-3-i.info/word11134.html

sendmail コマンドの実行は、phpinfoにある「sendmail_path」の値を見て行われるのだと思います。

途中結果

ということは、今のところ

SMTPlocalhost ←ローカル環境にSMTPサーバがある?
SMTPのポート番号:25
送信者情報:sendmail の設定値?

と推測しました。

このsendmailpostfixの設定、何やら難しそうです...。

次回でsendmailについて調べられたらいいと思います。

挫折せずに後編を書けるといいです...!

新しく覚えた(使った)cssまとめ - 2020年春・夏

調べてその場で納得して終わりのケースが多いcss。いつでも振り返られるようにメモしました。

floatの解除に display: flow-root

【2017年最新】clearfix一番短い書き方は親要素にdisplay:flow-root;を書き加えるだけ - 自動化厨のプログラミングメモブログ│CODE-LIFE

最近あまり使う機会が減った float を使ったときに解除をどうしようかな、と思って調べました。
親要素に clearfix をかけるように、display: flow-root とするだけです。 結論、display: flow-root は2020年4月時点でIE11非対応なので、使用は断念しました(迷いどころ)。

現在:
Can I use... Support tables for HTML5, CSS3, etc

ちなみに、親要素に overflow: hidden をかける方法は非推奨と言われることが多いそうです。
本来の使い方(はみ出たら隠す)とは違うからでしょうか。

clearfix も時代を経て設定が少しずつ変わっているのですね。

最新のcleafix(2020年4月)

.clearfix::after {
    content: "";
    display: block;
    clear: both;
}

それにしても display はいろいろな値がありますね。
html5の概念からおさらいして gridlist-item は覚えておきたいなと思いました。

flotのおさらい:
CSSの【float】についてちょっと本気出して説明してみた。 | たねっぱ!

「clearプロパティを与えた要素にはmargin-topが効かない」
(※端折った表現です)

そうでしたか!

imgを指定の大きさに配置できる object-fit: cover

【CSS】object-fitはCSSだけで画像をコンテナーにフィットさせてトリミングもできるとっても素晴らしいプロパティー | WEBDESIGNDAY

このプロパティは、WordPressなどで画像を投稿してもらう際に、いろいろなサイズの画像を揃えて表示させるのに便利です。

ざっくりいうと object-fit: cover は背景画像の background-size: cover の普通の画像版です。
忘れそうになりますが、直接画像や動画要素に指定します。

また object-position では、画像の配置を指定することができます(初期値は上下左右中央)。

現在:
Can I use... Support tables for HTML5, CSS3, etc

flexコンテナの子要素、フレックスアイテムに直接指定できる align-self

align-selfプロパティの意味と使い方 | CSS | できるネット

どんな状況でこのプロパティを知ったのかもう忘れてしまいましたが、このようにボタンを下に配置したカードを横に並べたら揃ってきれいかもしれません!?

...と思ったのにalign-self 使っていません...。
イメージではボタン要素に align-self: flex-end かな、と思ったのですが、そうすると、高さの指定のない他の要素が justify-content: space-around の縦方向版みたいに等間隔の隙間を持つように配置されてしまいました。

ポイントはボックスの下に配置したい要素を margin-top: auto とすることです。

横並びレイアウトの中の一番下のボタンの位置をCSSでそろえる方法|トピックス|STEP UP WEB|大阪のホームページ制作・作成サービス

原理はどういうことなのだろう...。
ちなみに、

align-selfプロパティは、フレックスアイテムのクロス軸方向の揃え位置を指定します。

ということなので、 flex-direction: column でフレックスアイテムの並びを縦方向にすると、 align-self はクロスした、フレックスアイテムの左右の位置調整ができることになります。

そしてもしかしたらと思ったら、やはり justify-self というものがありました。

【CSS】flexboxにjustify-selfは効かない - Qiita

こちらも解決策は margin: auto みたいです。なんと...。

角の取れた四角

というか、「四角から角の取れた図形」です。

cssで少しデザインしたくなって、四角形から2つの角が取れた図形を作りました。
自力ではお手上げだったので、具体的なコードはこちらを参考にしました。

角の欠けた枠。つくるよ。 | パンスールブログ | 株式会社Penseur パンスール|東京・大阪のデザイン会社

border 絡みの図形はいつも図におこさないと混乱します。
cssの書き方は正確ではないのですが、ざっくりとしたメモの図です。

f:id:yokoyoko_115:20200825010530p:plain

border-color: transparent というのはしっかり色(透明)を指定している、ということです。borderの太さとスタイルを合わせて指定すれば透明な枠線です。隣り合う他の線と色が違えば、その境目は斜めに区切られます。

幅があって高さが0の疑似要素、というのも、今後いろいろ応用ができそうです。

a要素の疑似クラスの指定順をそろそろ覚える

毎回調べているのですが、今度こそ理屈まで覚えようと思います。

:link、:visited、:hover、:active の記述順序とその覚え方 - jmblog.jp

覚え方は「LOVE and HATE」が有名みたいです。
以下の順で書くと、状態ごとに異なるスタイルのa要素にできます。

擬似クラス 状態
link 未訪問のリンク
visited 訪問済みのリンク
hover 要素にカーソルが重なっている
active 要素がクリックされている押し始めから離す時まで

:hover:active はa要素に限らず指定できます。

図にしたら腑に落ちました!

f:id:yokoyoko_115:20200830020617j:plain

  • ちなみに、link と visited は打ち消しあうことがないので順番はどっちでも OK
  • :hover 擬似クラスと:active 擬似クラスは一連の動作である

これらがポイントだと思いました。
そしてcssでは下に書いたものが優先されることを考えて...。

  • 未訪問
  • 未訪問で要素にマウスカーソルを合わせている
  • 未訪問で要素をクリックしている
  • 訪問済み
  • 訪問済みで要素にマウスカーソルを合わせている
  • 訪問済みで要素をクリックしている

これら6つの状態のうち、より限定的であるクリックしている状態の :active が最後にきます。

:focus の扱い(PCの場合)

a要素に指定できる擬似クラスでもう一つ、 :focus があります。 :focus は主にform関連の要素に指定できます。
a要素もPCではtabキーを押すとフォーカスしますし、クリックしてもフォーカスします。
(returnキーでリンク先に遷移できますが、キーを押すことは、:active の対象ではないみたいです)

状態は、他の要素にフォーカスが移る(他の要素をクリックする)までの間です。
ただ、a要素に :focus を設定しても、クリック後、ほどなくしてページ遷移する事が多いため、フォーカスの状態は一瞬です。

ページ遷移の話はさておき、フォーカスできるある要素に
マウスを合わせる→クリック→他の要素をクリック
という操作をした場合、こんなイメージになるかと思います。

f:id:yokoyoko_115:20200830000509j:plain

そう考えると、a要素で :focus を指定したい場合は、
:hover:active の間
が適当かなと思います。

:active:focus どちらを先に指定したらいいか、下記でも試してみました。

a要素、form関連要素以外で要素をフォーカスさせる方法

フォーカスさせたい要素にtabindex 属性を指定します。

aタグ以外にもキーボードフォーカスをあてる方法 - Qiita

↑のCodepenでも検証してみました。

このクリック関連、今回はPCを想定してまとめています。
スマホの場合はマウスカーソルを要素に合わせる、という操作がないので、:hover:action:focus の扱いがまた違ってきます。

PCとスマホでクリック時のスタイルを揃えたいときなどにまた掘り下げようと思います。

最後に

あといくつかありましたが、a要素の擬似クラスの話が膨らんでしまい、ここで一度おしまいにします。 またまとまったらcssの記事書こうと思います!

コンパイルとcssを考える

ソースマップの記事を書いていたら「コンパイル」が気になってしまいました。

scss→cssコンパイルなの?

過去の記事でも混乱していました(笑)
調べているとコンパイラ言語からプログラムの実行をする過程の中でコンパイルが出てくるので図にしました。

f:id:yokoyoko_115:20200804003940p:plain

図は正確にはあってないと思います。
コンパイルによってできたオブジェクトファイルというのは中間語なのか、機械語なのか。このあたりはいろいろな記事があってうまくまとめられませんでした。
C言語を勉強してみようか...。

コンパイラとは

コンパイラ - Wikipedia

コンピュータ・プログラミング言語の処理系(言語処理系)の一種で、高水準言語によるソースコードから、機械語あるいは元のプログラムよりも低い水準のコードに変換(コンパイル)するプログラムである。

なんとオブジェクトコードに変換する以外にも広い意味で「変換」するということなんですね!
そう考えれば、scssファイルからプログラミング言語ではない、スタイルシート言語のcssへの変換も「コンパイル」と言えると。
そう解釈しないとこの一度モヤモヤした気持ちはどうすればいいのか...。

CSSプリプロセッサ

そんなときプリプロセッサという存在を知りました。

プリプロセッサとは

プリプロセッサ(プリコンパイラ)とは - IT用語辞典 e-Words

プリプロセッサとは、ソフトウェアの役割による分類の一つで、ある中心的な処理を行うプログラムに対して、その前処理(preprocess)を行うプログラムのこと。プログラミング言語コンパイラの前処理を行うものが非常に有名。一方、メインの処理に対する後処理を行うものは「ポストプロセッサ」(postprosessor)という。

「ビルド」機能とは?仕組みやコンパイルとの違いを解説 | サービス | プロエンジニア

コンパイルまでには静的解析とプリプロセッサの処理が行われます。

プリプロセッサの別名は「プリコンパイラ」のようなので、そこからscss→cssを「コンパイル」と呼ばれるようになったのではないかと思いました。

CSSプリプロセッサの種類

CSSプリプロセッサにはいくつかあります。

  • Sass (Syntactically Awesome Style Sheets)
  • Scss (Sassy CSS)
  • Less (The Dynamic Stylesheet Language)
  • Stylus
  • PostCSS

プリプロセッサはプログラムのことを指したり、言語のことを指したり(これらはメタ言語)、どちらもあるようです。
混乱しそうですが、「Sass(言語)を使うにはSass(プログラム)をインストールする必要があります」という解釈でいいかなと思いました。

おまけ

いろいろ脱線したので、副産物の中からある程度まとめられた部分をメモします。

スクリプト言語インタプリタ言語の違い

ここでもどうしても「〜言語」がよく出てくるので調べました。
コンパイラ言語(型)とインタプリタ言語(型)は対義語的だなと理解しましたがスクリプト言語というのもあるとは。

スクリプト言語とは?インタプリタ型言語との違いは? | じゃぱざむ

今まで「スクリプト言語」だと思っていたものは「インタプリタ言語」でした。

図にしようと思いましたが、雰囲気で覚えておこうと諦めました。

コンパイラ言語でかつスクリプト言語であるというjavaを勉強してみようか...。

ブラウザでのレンダリングについて考える

今度は"コンパイル後"のcssファイルがどのようにブラウザで使われているか調べました。

ブラウザでは最初にDOM ツリー、CSSOM ツリーを構築する

オブジェクト モデルの構築  |  Web  |  Google Developers

CSSはHTML同様、CSSOM ツリーという、ツリー構造のオブジェクトモデルを構築します。

CSS のバイトが文字、トークン、ノードへと変換されていき、最終的に「CSS オブジェクト モデル」(CSSOM)というツリー構造にリンクされます。

とあるので、ソースを読み込んだ後に「バイト」になっているようです。 ↑のページの図を見ると3C 62 6F...とあります。

これはいわゆる機械語です。0と1だけのもののみを指すのかと思いきや、16進数で表されるものも機械語というのですね。

この後、DOM ツリー、CSSOM ツリーができて、
→ DOM と CSSOM を組み合わせてレンダリング ツリーを作る → Layout → Paint...

と続きます。この後の処理については別の機会に学びます。

フロントエンジニアなら知っておきたいブラウザレンダリングの仕組みをわかりやすく解説! | LeapIn

HTMLの書き方を見直し

W3CのMarkup Validation Service(マークアップバリデーションサービス)でウェブページを確認する機会がありました。
これって警告・エラーなんだ!という新しい発見がありましたのでメモします。

※2020年7月現在の内容です。

コメントの中にハイフン2つが出てくると警告

<!-- --←これがよくない -->

です。
BEMで書いているとクラス名に「--」がでてきて、その要素をコメントアウトしていたので警告を受けていました。

正しいコメントを書こう

見出しタグ(h2など)はsectionタグ内では孫要素とかでも良い

<!-- NG -->
<section>
  <div>
    <p>見出しテキスト</p>
  </div>
</section>

<!-- OK -->
<section>
  <h2>見出しテキスト</h2>
  <div>
    <p>テキスト</p>
  </div>
</section>

<!-- これもOK -->
<section>
  <div>
    <h2>見出しテキスト</h2>
  </div>
</section>

section要素のすぐの子要素でなければならないと思っていました。divを使いたいことがよくあるので一安心です。

iframe要素の廃止された属性をつかうとエラー

  • frameborder
  • scrolling
  • marginheight
  • marginwidth

これらは代わりにcssで設定するように、と書かれていました。

しかし、エラーを受けている該当のコード、yahooの!タグマネージャーの部分なんですよね...。

<noscript>
<iframe src="//b.yjtag.jp/iframe?c=XXXXXXX" width="1" height="1" frameborder="0" scrolling="no" marginheight="0" marginwidth="0"></iframe>
</noscript>

公式に配布されているコードって弄りづらいのでこのままにしています。

ところでjavascripが無効のときに表示する <noscript>
どういう動きをするのか確認されている記事がありました。

HTML、noscriptタグの挙動について。(非表示なのか未解釈なのか)|マコトのおもちゃ箱 ~ぼへぼへ自営業者の技術メモ~

Unicode正規化フォームCでないとエラー

Unicodeユニコード)とは「符号化文字集合」というもので、UTF-8などの「文字符号化方式」とは別ものです。

分かりやすい記事です!
https://wa3.i-3-i.info/word11422.html

上記を踏まえて「正規化形式C」とは合成済み文字(例:が)のことをいいます。
結合文字列は文字列を結合したもの(例:か゛←「か」+「゛」)です。

「Text run is not in Unicode Normalization Form C.」というHTML Validation Serviceの警告について: 小粋空間

「正規化フォーム(形式)C」を使わないとエラーになるんですね。
これはどこでそう決定されるのでしょうか...。

ユーザーが画面拡大できないビューポートの設定だと警告

<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">

これで

Consider avoiding viewport values that prevent users from resizing documents.

という警告が出ました。
content属性の値から、 maximum-scale=1.0user-scalable=no を削除すると、ユーザーが画面サイズを変更することができます。

ビューポートもコピペで済ませている部分があるので、ちゃんと理解しないとと思います。

番外:CSSの警告・エラー

cssもチェックしたので少し載せます。

background-color と border-color は同じ色です

警告です。
同じ色だと同化してしまって背景と枠線がわからないですよ、と教えてくれているそうです。
ありがた迷惑のような気もしますが、優しさと受け取ってスルーします。

-webkit-animation is an unknown vendor extension

「-webkit-animationは不明なベンダー拡張です(Google翻訳)」という警告です。
ベンダープレフィックス関連の警告は多い印象です。
ブラウザのバージョンアップとともに -webkit- がいらなくなったりなど、刻々と変化しそうな部分なので、Autoprefixerを使っていきたいです。

CSSベンダープレフィックス-webkit-を今この瞬間に辞める為のAutoprefixerの導入 - Qiita

異なる環境でも同じ表示(クロスブラウザ)と正しいcss、どちらを取るか天秤にかけたら、前者かなぁと思います。

最後に

なかなかちゃんとhtml、cssの文法と向き合うことはないのでよかったです。
でもエラーチェック・対応はたまにがいいですね。

黄色のSourceMapのコンソールエラー - コンパイルについても

今回のエラーはChromeデベロッパーツールのコンソールエラーを調べていて気になったもののうちの1つです。
(もう一つはCookieのエラーです)

 DevTools failed to load SourceMap: Could not load content for (Chromeの拡張機能のjsのソースマップ): HTTP error: status code 404, net::ERR_UNKNOWN_URL_SCHEME

似たエラーで

DevTools failed to load SourceMap: ...

というのも見掛けました。

Chrome拡張機能のjsのソースマップファイルが読み込めない(load)か、解析できない(parse)の違いです。
(load → parseの順で処理されます)

js.mapcss.map という、map拡張子の「ソースマップ」に遭遇することは今までなかったので、せっかくなので調べました。

SourceMap(ソースマップ)とは

コンパイル前後のjsやcssファイルを紐付けるファイルです。
ソースマップファイルがあるとデバックのときにコンパイル前の、元のファイルをたどることができて便利です。

ソースマップファイルはコンパイル時に作られることもあるそうです(後述)。

ソースマップファイルの中身

Tools for Web Developers の記事からソースを拝借しました。

styles.scss

%$textSize: 26px;
$fontColor: red;
$bgColor: whitesmoke;
h2 {
    font-size: $textSize;
    color: $fontColor;
    background: $bgColor;
}

(最初の% 何でしょうか...?)

コンパイルされたcss
styles.css

h2 {
  font-size: 26px;
  color: red;
  background-color: whitesmoke;
}
/*# sourceMappingURL=styles.css.map */ 

# sourceMappingURL=styles.css.mapsourceMappingURL アノテーション といいます。
ソースマップファイルの位置を示します。
コンパイル時にアノテーションが付きます。

続いてソースマップファイル。
中身はJSON形式で書かれています。

styles.css.map

{
  "version": "3",
  "mappings":"AAKA,EAAG;EACC,SAAS,EANF,IAAI;EAOX,KAAK"
  "sources": ["sass/styles.scss"],
  "file": "styles.css"
}

version:ソースマップの仕様のバージョン
mappingsマッピング情報
sourcesコンパイル元のファイル。複数入ることもあります
fileコンパイルによる生成ファイル
他には
names:コードに出てくる変数名、関数名(←要確認)

もっと色々あるようです。

mappingsの値については、Base64というものを使っているそうですが、難しそうです。

Safx: JavaScriptのSource Mapの内部表現について

エラーの解消方法

肝心の、どうエラーを解決するかですが、

  • ソースマップを使わない → cssファイルに書かれている sourceMappingURL アノテーションを削除する
  • ソースマップを使わない → sourceMappingURL アノテーション通りにソースマップファイルを配置、さらにscssやlessファイルを配置する

のどちらかです。

ソースマップの使い方

ソースマップファイルを使おうとすると、サーバーにmapファイルだけではなく、コンパイル前のscss、lessファイルも置かなくてはならないのでしょうか。
しかし、デバックすることが目的なので、サイト管理者のローカル環境にファイルが置いてあってもソースマップを利用することができるようです。

Source Map に関する情報 – ラボラジアン

ソースマップファイルの作り方(コンパイルの方法)

便利なソースマップ。作り方にはいくつか方法があります。
ここではscss、lessファイルからcssファイルをコンパイルする場合を調べました。

SassとLESS

まずこの2つの言語をさらっと調べました。
その前にどちらもCSSメタ言語プリプロセッサです。
(単語がどういう意味なのかはおいおい)

Sass・・・「Syntactically Awesome StyleSheet」。Rubyで実装されているオープンソースソフトウェア
LESS・・・「Leaner CSS」。JavaScriptで実装されているオープンソースソフトウェア。

パターン1:Sass、Lessをインストールして実行する

コマンドラインでインストールします。

Sassの場合

Sassはその前にRubyをインストールする必要があります。
その他にもgemやbundler、compassをインストールすると便利とのことですが、ちょっと...Rubyをやることがあればまた勉強しようと思います。

sassをインストール

gem install sass

scssファイルのコンパイル

sass style.scss:style.css

これでコンパイルとともにソースマップファイルも作られます。

CSSのメタ言語Sass(SCSS)、LESSの完全入門 - Qiita

☆Nodeでもsassのモジュールがあるみたいです。

LESSの場合

一方でLESSは事前にnode.jsをインストールする必要があります。

lessをインストール

npm install -g less

lessファイルのコンパイル

lessc styles.less > styles.css

同じくコンパイルとともにソースマップファイルも作られるはずです。

lessとはNodeでいう「モジュール」ですね。イコール「オープンソースソフトウェア」のことだと解釈しました。(Rubyではsassなどを「gem」というっぽい)

Nodeを使う場合は、タスクランナーであるgulpなどを使うと、他の処理と合わせてコンパイルできて便利です。

LESSでCSSを簡単に!LESSの使い方と便利な機能 - Qiita

パターン2:(LESSのみ)クライアント側でコンパイラを使う

lessファイルを読み込んだ後でless.jsというコンパイラを読み込みます。

<link rel="stylesheet/less" type="text/css" href="styles.less">
<script src="less.js" type="text/javascript"></script>

less.jsはダウンロードして使う方法もあればCDNでもあります。

第1回 LESSのメリットと導入方法:LESSで3倍ラクするスマートフォンコーディング|gihyo.jp … 技術評論社

ただこの方法だとソースマップファイルが作られるのか分かりませんでした...。

パターン3:GUIツールを利用する

GUIコンパイラと呼ばれるツールです。WindowsでSassをコンパイルしたいときにも、GUIコンパイラを使えばRubyをインストールすることなくできます。
「Prepros」、「koala」が有名なGUIコンパイラです。

コンパイルの設定でソースマップファイルを作ることができます。

パターン4:エディタの拡張機能を使う

VSCodeでは「Easy Sass」、「Easy LESS」といったものが検索で出てきました。
ファイルを保存するとコンパイル処理が走る、といった感じらしいです。

こちらもオプションでソースマップファイルが作れそうです。
(要確認)

やっぱりコンパイルが気になる

ここまでコンパイルコンパイル書いていると疑問がふつふつと再燃してきました。
ソースマップから完全に脱線しています。

☆別で記事にしました!こちら。

実はソースマップで一番知りたかったことは、importしたscssファイルまでソースマップでたどることができるのか、なのですが、また今度確認してみます。

その他の参考

ソースマップについてコンソールに警告(DevTools failed to parse SourceMap)【Chromeデベロッパーツール】 | まろりか

ソースマップの自作は割とコワくない。 - Qiita

黄色のCookieのコンソールエラー

Chromeデベロッパーツールの「Console」で出てくる黄色のエラー(警告)に対処したのでメモします。

Cookieのエラー

A cookie associated with a cross-site resource at <URL> was set without the `SameSite` attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set with `SameSite=None` and `Secure`. You can review cookies in developer tools under Application>Storage>Cookies and see more details at https://www.chromestatus.com/feature/5088147346030592 and https://www.chromestatus.com/feature/5633521622188032.

<URL>にはyahooのURL(http://yahoo.co.jp/)やGoogleのURL(https://www.google.com/、http://.google.com/、http://.google.co.jp/)など、https/http違いのURLが入っていました。

このエラー、いろいろなサイトで見られます。しかも多いと何十個とまとめて出ています。
目を瞑りたいではありますが、調べてみるといろいろ出てきました。

まさに翻訳されている記事。詳しい!ありがとうございます。

Chrome で SameSite=None に関する Cookieについての警告が表示される | ラボラジアン

【ポイントだけ翻訳】
http://example.com/ に存在するクロスサイトなリソースに関連付けられたクッキーは、SameSite 属性がついていません。今後の Chrome のリリースでは、クロスサイトなリクエストに付属させるクッキーは、SameSite=None と Secure 属性がついている場合のみ送信します。

http://example.com/ は前述の<URL>にあたります。

「yahooやGoogleのURLに存在するクロスサイトなリソース」というのは、どういうことなのでしょうか?

...結局答えが見つけられず。
おそらく知らず知らずのうちにyahooやGoogleへリクエストを送っていて、その際のCookieにSameSite=NoneとSecure属性が付いていないですよ、という警告なんだろうと思います。

Cookieについて図にまとめる

忘れそうなので調べたことを図にしてみました。

f:id:yokoyoko_115:20200712001704j:plain f:id:yokoyoko_115:20200712001721j:plain

※間違っている部分を発見したら修正します!

SameSite とは

SameSite 属性の目的は、
今開いているページのドメインから、別のドメインにリクエストを送る際に、クッキーをセットするかどうか
を制御することです。

HTTP クッキーをより安全にする SameSite 属性について (Same-site Cookies) | ラボラジアン

上の図では、あるページ内に別サイトの広告の表示をリクエストしている例ですが、サイトAからサイトBへページ遷移する際も、現在のドメインとは別のドメインへリクエストを送ることになります。

Secure属性とは

SSLというURLがHTTPSという暗号化された通信下でのみ読み取れるCookieの指定となります。

いまさら聞けないSameSite CookieとGoogle Chrome 80 | ecbeing

また、Cookieを発行するときに "secure" と指定されたクッキーのことをセキュアクッキーといいます。

ドメインでもCookieを送れるようにしますが、せめてSSL通信にしてください、というのが今回の警告です。

エラーの対処方法

そしてサイト運営側としてはどう対処すればいいのかというと、

自サイトに埋め込んだウィジェットや広告などから外部のドメインに送られるクッキーに関しては、こちらでコントロールできるものではないので何もすることはない。

最初に外部のサーバーからセットされたCookie(これがサードパーティCookie?)に対してはクライアントからは何もできない、SameSite=Noneの指定はできません、ということでしょうか。

ひとまずエラーに対しては一件落着です(具体的な対処は何もやっていない)。

余談

Cookieについて調べていたらあれこれ気になったのでメモします。

SameSite=NoneとSecure属性の警告は、CSRF対策のため?

クロスサイトリクエストフォージェリCSRF
ユーザーのCookieを利用して、あたかもユーザーが行ったかのような個人情報の設定などの処理をさせてしまう攻撃です。
攻撃者は罠を仕込んだ画像をユーザーに読み込ませたり、POSTでデータを送信させて攻撃します。 「forgery:偽造」という意味です。
リクエストの偽造ですね。

SameSite=NoneとSecureと規定すれば、HTTP通信の怪しい画像などの読み込み時のCookieの送信は防げる、ということでしょうか。

POST送信におけるCSRF対策について

Chrome 80が密かに呼び寄せる地獄 ~ SameSite属性のデフォルト変更を調べてみた - Qiita

SameSiteの設定値によって対策効果が変わってきます。
急に難しく感じました。

また、世間はプライバシーの侵害にもあたるサードパーティCookieを廃止しようという流れらしいです。

GoogleのChromeがサードパーティCookieを廃止。Webサイトへの影響は? | Webmedia

Cookieの確認方法

PCのChromeでは、アドレスバーにchrome://settings/siteData?search=Cookie と入れてアクセスすると「すべての Cookie とサイトデータ」という、ブラウザに保存されているCookieがサイトごとに確認できます。

結構な数があります。「ad」と付いているものは広告っぽいです。
そして結構どこにでも「_ga」と、AnalyticsのCookieがセットされています。

さらに!Chromeデベロッパーツールの Application > Storage > Cookies では、のページでセットされたCookieの一覧が送信先別で見れます(よく見たらアイコンがチョコチップのクッキーみたいですね)。
Secure指定があるかどうかも確認できます。

Google AnalyticsはファーストパーティCookieを利用している

どういうこと??と思いましたが、ga.js やgif画像をうまいことやり取りしているようです。

コラム - GoogleAnalyticsのCookieは、なぜサードパーティCookieではなく、ファーストパーティCookieなのか? | Nexal

AnalyticsはGoogleのサービスなので、どうなっても使えなくなることはなさそうですね。

最後に

Cookieをセットする方法まで調べたかったですが、来たる時が来るまでとっておきます。

本当はもう一つの黄色いエラーについても書こうと思っていました。
クッキーがここまで膨らむとは!