ハトネコエ Web がくしゅうちょう

プログラミングやサーバー・Web制作、チームマネジメントなど得た技術のまとめ

materialize-css のJSライブラリを TypeScript + React 環境で読み込む

Materialize 、モダンっぽい Web サイトを作れるので、
個人的には Bootstrap よりは最近使うようになりつつあります。

「Bootstrap より軽いし……」と書こうとして実際にいま測ってみたらそうでもなかったですが(笑)

1. Bootstrap vs. Materialize (ファイルサイズ比較)

1-1. Bootstrap

  • bootstrap.min.js (v4.1.3) : 20.56KB
  • bootstrap.min.js (v4.1.3) : 13.76KB
  • jquery-3.3.1.slim.min.js : 23.47KB
  • popper.min.js (v1.14.3) : 6.8KB

Total: 64.59KB

1-2. Materialize

Total: 59.53KB

Materialize の JavaScriptjQuery を内包しているので、そのぶん大きくなっていますね。
読み込むファイル数は少ないので、そのぶんコストは低いですが、思ったより容量に差はなかったです。

閑話休題。本題にいきましょう。

2. Materialize の JavaScript ライブラリを TypeScript で使いたい

例えば materialize-cssNavbar Component の Dropdown を使いたいときには、
Dropdown のドキュメントにある通り、

// ドキュメント通りに dropdown-trigger class を設定し、以下の script を末尾などに記述
document.addEventListener('DOMContentLoaded', function() {
  var elems = document.querySelectorAll('.dropdown-trigger');
  M.Dropdown.init(elems, {});
});

// jQuery を呼び出している場合は以下の 1 行で済む
$('.dropdown-trigger').dropdown();

上のどちらかの方法でドロップダウンをアクティブにしなくてはいけません。

HTML の最後に script タグを使って、

<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<script>
  document.addEventListener('DOMContentLoaded', function() {
    var elems = document.querySelectorAll('.dropdown-trigger');
    M.Dropdown.init(elems, options);
  });
</script>

こんな感じで書いてあげてもいいわけですが、
せっかくなら ts ファイルや tsx ファイル内で呼び出してあげたい。その方法です。

3. 答え

3-1. npm install -D @types/materialize-css

前置きが長くなりましたが、以下のようにライブラリをダウンロードすればOKです。

npm i -S materialize-css
npm i -D @types/materialize-css

materialize-css だけでなく、
@types/materialize-css を入れているのが一番のポイントです。
これがないと TypeScript でのコンパイルに失敗してしまいます。

なお、古い記事だと npm i -S materialize-css@next で入れている記事がありますが、
2019年5月現在では、 npm i -S materialize-css で入るのは 1.0.0 、
npm i -S materialize-css@next で入るのは 1.0.0-rc.2 と、
next を付けるほうがむしろ古いバージョンが入ってしまうのでお気をつけください。

f:id:nekonenene:20190506005825p:plain
https://www.npmjs.com/package/materialize-css?activeTab=versions より

3-2. import M from 'materialize-css'

あとはいつも通りに、 tsx ファイルや ts ファイルの先頭で import してあげれば OK です。

import M from 'materialize-css';

2. の項で書いた例のように、

var elems = document.querySelectorAll('.dropdown-trigger');
M.Dropdown.init(elems, {});

を適当な場所で書くことにより Dropdown の初期化をおこなうこともできますが、
ドキュメントの例にあるようなクラス名(dropdown-trigger)をそのまま使う場合でしたら、

M.AutoInit();

でカンタンに済ませることも可能です。(参考: https://materializecss.com/auto-init.html

どのコンポーネント、そして class 名だと初期化されるかは元のコードを読むといいでしょう。

https://github.com/Dogfalo/materialize/blob/efa0aee/js/global.js#L106-L135

3-3. React で扱う場合の Tips

M.AutoInit();componentDidMount 内で呼び出すと良いでしょう。
(※ constructor 内で呼び出すと失敗します。constructor は HTML render がおこなわれる前に走るためです)

public componentDidMount(): void {
  M.AutoInit();
}

M.AutoInit(); は便利ですが、すべてのコンポーネントに関する init がおこなわれるわけではありません。
例えば M.updateTextFields(); もその一つです。(参考: 『Text Inputs』 の『Prefilling Text Inputs』の項)
これは、Text Input Form にすでに文字が入力されている場合には、ラベルを上に移動しておいてくれるメソッドです。

https://github.com/Dogfalo/materialize/blob/efa0aee/js/forms.js#L3-L21

使用しないとこうなる:

f:id:nekonenene:20190506021047p:plain

使用するとページ表示時にこうなってくれる:

f:id:nekonenene:20190506021123p:plain

これは M.AutoInit(); から呼び出されないことがコードからわかりますので
入力フォームのあるページでは M.updateTextFields(); を使ってあげるといいです。

私の書いているコードでは、input フォームの defaultValue を非同期通信で取ってくるために
render のされ直しが発生してしまうため、
componentDidMount 内ではなく componentDidUpdate 内で呼び出してあげています。

public componentDidUpdate(): void {
  M.updateTextFields();
}

4. おしまい

React を今まで避けて生きてきたんですが、
かんたんな Go (Gin) + React のアプリケーションを作ってみようとさわってみたら
ちょっとずつわかってきました。

Redux には触れていないですが、今のところバケツリレーも大規模になっていないので、
今回は使わないでもいけそうです。

ついでに TypeScript も導入し、数年ぶりにさわっていますが、
慣れていない Go + 慣れていない React + 慣れていない TypeScript の組み合わせでちょこちょこ苦しんでいます(笑)
型チェックのために書く量は増えるし、参考資料そのままで書けない場合もあり大変です。

とても勉強になっているので、もう少しがんばってみます!

セッションと Cookie について今さら理解する

Webサイトのログインで必要な考えとなる
セッション周りを全然わかっていなかったので、いろいろ自分用にメモ。

1. 動機

今まで Rails や周辺ライブラリがよしなにやってくれていたものを、
Go言語で Web アプリを作ろうとしたら自分でちゃんと実装しないとだったので、
ログイン機構(特に devise の current_user メソッド)を作るためにセッションを理解する。

2. 役立つ記事

この 3 つを読んでおけば、セッションと、そのための Cookie について理解が整う。

3. Tips

3-1. net/http が SetCookie メソッドを持つ

Go言語の場合は net/http パッケージが SetCookie 関数を持つのでそれを使うと楽。

なお第一引数には、HTTP Response を組み立てる ResponseWriter 構造体を用いる。
Cookie をクライアント(Webブラウザ)に Set するのは、 HTTP Response の Header を使っておこなうため。

3-2. Value に入れる値は URL Encode されたもの?

今使っている Web フレームワーク gin のここのコードで、

Value: url.QueryEscape(value),

となっていたため、 URL Encode が必要なのか確認してみました。
stackoverflow のこの回答では、「そうだよ。すべきだ」って回答が一番上に来てますが、他の回答も見ると議論の余地があることがわかります。

There is some confusion over encoding of a cookie value. The commonly held belief is that cookie values must be URL-encoded, but this is a fallacy even though it is the de facto implementation. The original specification indicates that only three types of characters must be encoded: semicolon, comma, and white space. The specification indicates that URL encoding may be used but stops short of requiring it. The RFC makes no mention of encoding whatsoever. Still, almost all implementations perform some sort of URL encoding on cookie values. In the case of name=value formats, the name and value are typically encoded separately while the equals sign is left as is.

(『HTTP cookies explained』の『Cookie encoding』の項より引用)

日本語に訳すと、『CookieValueエンコードについてはいくらかの混乱が起こっています。一般的に Value は URL-encoded が必要と信じられていますが、実際の実装でそうなっている物はあれどこれは誤解です。元の仕様では、セミコロン、カンマ、および空白の3種類の文字のみをエンコードする必要があることが示されています。これは URL Encode を使用できることは示しますが、要求しているわけではありません。RFCでもエンコーディングについて一切言及していません。(以下略)』

そして他の回答では

RFC6265:           "for example Base64"
PHP:               URL encode
Go:                raw
Node.js + Express: URL encode

と、各言語によって実装が異なることを示してくれていました。

PHP を例に取ると、PHP の setcookie 関数は、
Value として与えられた引数を URL Encode して実際は保存します。
PHP 5 以降で実装された setrawcookie 関数を使うと、URL Encode をおこなわず保存します。
(参考: https://www.php.net/manual/ja/function.setcookie.php

RFC6265 内では

To maximize compatibility with user agents, servers that wish to store arbitrary data in a cookie-value SHOULD encode that data, for example, using Base64 [RFC4648].

と書かれてはいますが、たしかにエンコードすべきと言っているまでで、Base64 は例示してるだけですね。
(なんでユーザーエージェント文字列との互換性を持ちたいのかはわからない……)

3-3. SameSite の設定はデフォルトでいいかも

Go言語 v1.11 以降は SameSite ってパラメーターを Cookie に設定できるんですけど、
「厳しいほうがいいだろう」と思って SameSite: http.SameSiteStrictMode に設定したら、OAuth でコールバックを受け取ってからの Cookie 読み込みができない罠にハマりそうだったので、
SameSite: http.SameSiteDefaultMode でとりあえずは良さそうです。

実装がどう違うかはいつか読みます……。

4. おわりに

忘れないように書いておきたかった内容なのでゴチャゴチャしていますが、
セッションへの理解がだいぶ進んで、まともな Web プログラマーに近付けた気がします。

作ってる練習用Webアプリのセッション管理部分はこんな感じ ↓ になりましたー。

https://github.com/nekonenene/gin_quiz_app/tree/master/session

同人イベントスタッフ用語集!

ゴールデンウィークですね!!

ゴールデンウィークといえば、各種イベント! 同人イベントですね!

最近は同人イベントにサークル参加することはあってもスタッフ参加をなかなかしない私ですが、
「今後スタッフ参加する方のための記事がないな〜」と、ふと思ったので書いてみました。

同人イベントスタッフ用語集!!

同人イベントスタッフ用語集

これであなたも「コミケ」や「M3」や「コミティア」のスタッフになっても困らない!
・・・かもしれません。

私がやったことあるのはM3スタッフだけなので、
もしかすると他イベントでは使われない言葉があるかもしれませんが、たぶんだいたい共通です。

1. 一般用語編

スタッフ参加だけでなく、一般参加やサークル参加においても使うであろう言葉や知識です。

1-1. 「お客様はいない」

同人イベント鉄の掟です。
同人イベントは全員が参加者で、みんなで作るお祭りです。
(参加形態に応じて、一般参加者サークル参加者スタッフ参加者と呼び分けます)

コミケくらいの規模になると、扱うお金の大きさの問題から法人化はしていますが、
どの同人イベントも基本的に非営利目的でおこなわれています。

イベントスタッフもボランティアです。(意外と知られていない)

この仕組みを悪用して、営利目的でイベントを開催しているのに、
イベントスタッフはボランティア扱い(弁当+2000〜3000円の謝礼)で多数の同人イベントを開催している会社があり、
同人イベント慣れしている人々からは煙たがられています。(「ゆーちゃん」や「貴様ちゃん」と呼ばれている)
とはいえ、あの会社がないと地方の同人イベントがほぼ無くなるので難しいところです……。

1-2. 頒布(はんぷ)

「配布」とほとんど同じ意味です。

「お客様がいない」という基本概念をもとに、
商売っぽさが出るのを避けるため、同人イベントではよく使われる言葉です。

私も「サークルさんからCDを買う」でなく「CDを手に入れる」とか「ゲットする」とか言うように気を付けてはいますが、
とはいえ、『同人誌即売会』なんだし、「売る」「買う」って言い方はしてもいいような気もします……(笑)

1-3. てぃあ

「コミティア」 のことです。
1984年11月18日から始まる長い歴史を持ち、
東京だけでなく新潟や名古屋、大阪などの地方支部の開催も活発です。

1-4. こみいち

「COMIC1」(「こみっくいち」と読む)のことです。
「こみわん」と言う人もいます。

1-5. サンクリ

「サンシャインクリエイション」 のことです。
池袋サンシャインシティで年3回開催されています。

1-6. ぼます

「THE VOC@LOiD M@STER」 のことです。
VOCALOIDオンリーイベントの中では古株です。
「ボーマス」が正式の略称ですが、発音としては「ぼます」と言う人が多いです。

主催の「ケットコム」は、同人イベントの主催もしていますが、
元々は同人イベント情報を扱うポータルサイトで、古くから同人イベントの世界を支えています。

1-7. ぴお

大田区産業プラザPiO のことです。
同人イベントがよく開催されています。

実は、同人イベントが開催できるホールはそんなに多くありません。
「オタク=不潔、気持ち悪い」というイメージの影響だったり、
ホールの周りで徹夜して過ごす人や、イベント当日の行列による近隣からの苦情だったりで、
同人イベントはNG、となってしまっているホールが多いのです。

ありがたいことに PiO はいまだに同人イベントの開催を許可してくれていますが、
都産貿(とさんぼう。東京都立産業貿易センター)TRC(東京流通センター) などとは異なり、
住宅街の中にあるため、会場外に行列ができてしまうと近隣住民からの苦情につながりやすいです。

苦情が増えて同人イベント開催がNGに変わってしまわないよう、
主催者が苦情防止のために細心の注意を払う必要のある、難易度の高いホールであるとも言えます。

2. スタッフ用語編

一般参加だとあまり使わなそうな言葉を並べてみました。

2-1. ようじょう

養生(ようじょう)テープ のことです。
転じて「幼女」と呼ぶこともあります。

f:id:nekonenene:20190427170051j:plain

ガムテ(ガムテープ)と違って、貼ってもあとが残りにくいので、
会場の床や机や扉などなど、いろいろな場所で活躍します!

ちなみに「マステ(マスキングテープ)」と「養生テープ」の違いは、
紙で出来ているのがマステ、ポリエチレンで出来ているのが養生テープだそうです。へぇ〜。
サークル参加さんだと、マステを持参してくる方は多いのではないでしょうか?

2-2. バミる

演劇などが好きな方はご存知の言葉かと思いますが、
位置を示すためにテープを床に貼り付けることです。

同人イベントスタッフは、サークル参加者さんが来る前に、
イベント開始前に長机を立てて配置しておく必要があります。

机同士がしっかり連なって、ひとつの島になる(大きな四角形をなす)ように配置しなくてはならないので、
あらかじめ机を置く予定の位置を養生テープでバミっておく必要があります。

このバミる作業をおこなう方々を測量班
机を運んで配置していく方々を設営班、と言ったりすることもありますが、
設営についてはみんなでやるので班って感じでもないですね。

2-3. そとけい

「外警」と書いて「そとけい」と読みます。
開場前の、ホール外にできた列の整理をおこなう方々です。

1-7. で書きましたが、ホール外に人が溜まっていると苦情につながり、
次回のイベントをそのホールで開催できなくなる危険があります。
しかもそのイベントだけでなく、他の同人イベントまでNGになる危険性があります。

そとけいは、ホール外に迷惑が起こらないよう、
外に溜まっている人を列に案内し、行列を圧縮して大きく広がらないようにし、
みんなをホール内まで案内する非常に大切なお仕事です。

同人イベントスタッフの花形と言えるかもしれません。

2-4. こんたい

「混対」と書いて「こんたい」です。混雑対応ですね。
最近は「館内(かんない)」という言い方をすることも増えてきました。
混雑対応以外の館内対応も多いので、こっちの言い方のほうが自然かもですね。

「そとけい」との対比で、単純に「なか」と言うときもあります。

役目としては、ホール内の人の流れがスムーズになるよう声かけをおこなうものです。
例えばサークルさんの前で集団で話し込んでいて、通路の進行の妨(さまた)げになっている場合にお声がけしたり、
あとはホール内をスタッフ腕章をつけて巡回していますので、道案内を受けたり、落とし物を渡されて受付に届けに行ったり、といろいろやります。

イベントの空気を感じやすく、人助けをできる機会が多いのが楽しい部署です。

2-5. かたはん

「カタログ販売」の略です。

M3デジゲー博 などのイベントでは、
一般参加は1人1部カタログを購入し、入り口でスタッフに見せるように掲(かか)げて入る必要があります。

カタログは事前に同人ショップなどで購入することができますし、
当日イベント会場で購入することも可能です。
そのカタログを販売するのが、カタ販のお仕事です。

やることとしてはふつうのお会計ですが、同人イベントならではの注意点は、
スタッフ参加者=店員、一般参加者=お客さんという関係性ではないので、そうならない会話」というところですね。

「いらっしゃいませ」「(購入後)ありがとうございましたー」だと店員っぽいので、
「こんにちはー!」「(購入後)いってらっしゃい!」っていう会話で、同じイベントに来た同志感を出そうとしてたりします。

カタログ販売だけでなく、販売所に並ぶ人の列整理をやったりもします。

2-6. ゲート

サークル通行証を持っているかや、入場に必要なカタログを持っているかなどをチェックする、
入り口の番人です。

サークル入場開始、サークル入場停止、一般入場開始の
それぞれのタイミングで通してよい人が変わるので注意します。

なお、サークル入場停止から一般入場開始の時間(一時的にサークル参加者も一般参加者も入場がおこなえなくなる時間)を
「館閉鎖(かんへいさ)」と呼びます。

参加者みんなが通る場所にいるため、道を聞かれることが一番多い部署かもしれません(笑)

2-7. でんせつ

「電気設営」の略です。

映像系や同人ゲームが多いイベント、楽器の演奏がおこなわれる同人イベントなど、
ごく一部の同人イベントでは、サークルさんに電源供給をおこなうために、ホール内の配線設計を考えます。

これ、 M3 以外でも存在する部署なんですかね…?

2-8. トラヤ

「トラックヤード」の略です。
トラックの荷物の積み下ろしをするエリア のことを指します。

同人イベントではイベント前日にサークルさんの荷物がホールへ搬入され、
また、イベント当日も、サークルさんが自宅へ直接送れるよう宅急便受付をするので、
クロネコヤマトさんなどと連携する担当の人は、トラヤの位置をしっかり覚えておきます。

f:id:nekonenene:20190427170752p:plain

また、充分なスペースがあるため、トラックのいない時間を利用し、
入場待機列を並べる場所として使われることも多いです。

3. 質問コーナー

用語集はこんなところですが、最後に、同人イベントスタッフに関して疑問に思われそうなところを書きます。

3-1. 同人イベントスタッフになるには?

まずは一度は同人イベントに一般参加してみるといいと思います。
「楽しかったなー」と思ったら、ホームページを見て、スタッフ募集ページから応募してみてください。

あとはイベントスタッフに直接聞いてみるのも手です。歓迎してくれると思います。

このような議論が Twitter に上がりましたが、
「スタッフに直接聞くのは正攻法でしょ!」という意見が多かったですし、私もそう思います。

顔なじみができていると、スタッフ集会への心理的なハードルも下がりますし。

親切そうな人に声をかけてみましょう!
スタッフも同じオタクなので、コミュニケーションをミスしたりはあると思います。許して……)

3-2. 同人イベントスタッフって何が楽しいの?

イベントに参加しているみんなの、楽しそうな顔を見られるのが良いところです。
道案内などして「ありがとうございます!」って言ってもらえると、とても幸せになります。

あとは、同人イベントスタッフで友達ができるのもおもしろいです。
イベントスタッフをしている方、なんでか知らないですけど社会人として優秀な方が多いですので、
大きな刺激を受けることができます。

私が最初に同人イベントスタッフをしたのは高校生の時だったのですが、
周囲の方々にとてもお世話になりましたし、間違いなく私の人生に大きな影響を与えていると感じます。

人の役に立ってみたい、オタク仲間を作りたい、という方にはおすすめです。

3-3. 逆につらいことは?

ふだん運動しないタイプのオタクなので設営がけっこう疲れます・・・(笑)
イベント翌日は休みじゃないと体力がつらいです。よわよわです。

3-4. スタッフ参加とサークル参加は両立できる?

スタッフの忙しい時間は基本的にどの部署も
サークル入場開始前から、一般入場開始後1時間経つくらいまでなので、
1人サークルでない場合は、最初の1時間だけ仲間にサークルにいてもらうことにより両立が可能です。

1人サークルの場合は、
例えばイベント開始前の設営とイベント後の撤収だけのお手伝いとかいうのもできます。
「今回はサークル参加なのであまりお手伝いできませんが…」という会話はスタッフ間でよくあります。お気になさらず。

4. おわりに

最初にスタッフ参加したときは、みんながわからない言葉でやり取りしていて戸惑ったことを覚えています。
いま新しくスタッフ参加された方も、同じような戸惑いを感じてしまったら
それは申し訳ないなと思い、この記事を書き上げました。

「この言葉足りてないぞ〜!」がありましたら、コメント欄なりTwitterなりでご意見ください。
間違いのご指摘も。

同人イベントが楽しいと思ったら、ぜひ一度はスタッフ参加も経験してみてください!

美少女同人作家と若頭 (REXコミックス)

美少女同人作家と若頭 (REXコミックス)