年間ブックマークランキングジェネレーター で作ってみた。手軽に1年を振り返れて便利。8位は去年に投稿した記事だけど何故かランキングに入っている。まあ気にしないことにします。
mizdra's blogの2020年ブックマークランキングベスト8(累計600ブックマーク)
generated by 年間ブックマークランキングジェネレーター
年間ブックマークランキングジェネレーター で作ってみた。手軽に1年を振り返れて便利。8位は去年に投稿した記事だけど何故かランキングに入っている。まあ気にしないことにします。
generated by 年間ブックマークランキングジェネレーター
この記事はゆゆ式 Advent Calendar 2020 13日目の記事です。12日目はセレーノ (@haidorenzia) さんの尻尾ファンタジアでした。
私事ですが最近COMIC FUZできららを定期購読するようになりました。以前は一気に読んだときの充実感が味わえない点、いちいち書店に足を運ぶのが面倒な点が嫌で単行本派だったのですが、意外と不満なく過ごせています。何よりゆゆ式が月に1回読めるのが最高です。ゆゆ式は話単位で読んでもちゃんと充実感がある。後々刊行される単行本を読んだ時に、本誌で既に読んでいたことで充実感が味わえなくなってしまうのではないか、という不安があったのですが、全然そんな事なかったです。単行本めっちゃ充実感あった… ゆゆ式の圧倒的面白さが不安を吹き飛ばしてくれました。月イチでゆゆ式が楽しめて、単行本でまた楽しめる。定期購読して本当によかった。
さて今年のゆゆ式 Advent Calendarのテーマは「日向縁さんの笑い声」です。ゆゆ式の登場人物の中でも日向縁さんは本当によく笑います。見ているとほんわかします。日向縁さんはゆゆ式の登場人物の中でも屈指の癒やしキャラですが、笑いがその癒やしを成り立たせていると言っても過言ではないと思っています。
そしてその笑い声も多彩です。「アハハッ」と普通に笑うこともあれば「アッハハハハハ!!!」と大笑いすることもあるし、「クフフッ…」みたいな笑い声もある… 本当に色々な笑い声をされるので、それを見ているだけでも楽しめます。僕は「おっ、ここではこういう笑い声なのか〜」と眺めてはなるほどと言っています。多分僕だけじゃないはず。
という訳で今回は僕が好きな日向縁さんの笑い声10選を紹介します。ちなみに訳あって集計対象は1〜10巻までです。
初めは最もメジャーな笑い方、大笑いです。よくゆずこのボケを受けてこの大笑いをしてくれます。
こっちはちょっと堪えつつ大笑い。「酒のみてえ」の回です。唯さんが「そんなに…」というくらいの元気な笑いです。
なま言ってんじゃねえの回から2コマセットで紹介。笑いを堪える縁さんに対し、ゆずこがトドメを指すシーンです。堪えてからの笑いっぷりがお気に入りです。ちゃんと縁さんの顔もいかにも「ぷはっ」と笑っていそうな感じで素敵ですよね。三上小又先生は笑い顔を書くのが上手いなあとつくづく思います。
超巨大スペイン回から。頑張って体全体でうずくまって笑いを堪えているシーンです。かわいい。
海回の1コマです。堪え笑い…というよりは笑いすぎて死にそうになっている様子です。大変元気でよろしい。
お米だいすき回より「はひぃ〜〜〜...」です。涙が出るくらいの笑い、こちらも良い笑いっぷりですね。
どっちが先に寝るか選手権より1コマ。これはもっと大胆な笑いっぷりで、床で笑い転げています。あの日向縁さんなのだから床で笑い転げるくらい得意技だろう、と思っていたのですが、意外にもこのコマしかないんですよね。つまりレアです。
こちらは2巻、初期のゆゆ式の1コマです。実は日向縁さんが声を出して笑うのは2巻のこのコマが初めてなんですよね。意外にも1巻では笑顔になったりニンマリすることはあれど、声を出して笑うことはないのです。皆さんもこういった普段と異なる視点でゆゆ式を読み返して見ると面白いかもしれません。
最後はポンコツ料理ロボの回の1コマです。同じく堪え笑いでも、ネタを振りながらの堪え笑いです。笑いつつもちゃんとネタを振っててえらい。ゆゆ式の中でもかなり好きなコマの1つです。
かなりマニアックな話題だったと思うのですが、いかがでしたでしょうか。あ〜これこれと言いながら眺めてもらえていたら嬉しいです。他にももっと素敵な笑い声あるよ!こういう笑い声もオススメだよ!とかあれば是非教えて下さい。
余談ですが好きな笑い声のコマを集める作業は、日向縁さんが登場するコマ一覧を眺めるアプリを自作してやっていました。自炊した単行本のデータを id:esuji5 さんの yonkoma2data に与えて作りました。id:esuji5 さん、いつもありがとうございます *1。お世話になりすぎているので何かしらの形でフィードバックしたい…!
欲しいやつできた pic.twitter.com/QqNWPq5rsc
— mizdra (@mizdra) 2020年12月12日
明日の担当は id:esuji5 さんです!
この記事ははてなエンジニア Advent Calendar 2020 5日目の記事です。4日目は id:syou6162 さんで、数字のバラ付きを考慮して意思決定する技術でした。
こんにちは、id:mizdra です。今年新卒としてはてなに入社し、WebアプリケーションエンジニアとしてGigaViewerというマンガビューワーを作っています。
最近のはてな社内では「tech-future」という、様々な技術を見つめ直すワーキンググループを運営しています。この会では、ある技術についての要点をまとめるだけでなく、その技術にまつわる歴史を紐解いて整理し、その上で全体を俯瞰して将来その技術がどういう方向に向かうのかを議論し、未来を予測する手がかりを作る、といった挑戦的な取り組みをしています。既に弊社のエンジニアから「tech-future」の取り組みの一部が公開されてますので、是非読んでみて下さい。
この記事では「(Web) Frontend-Ops」をテーマとして開催された回の内、polyfill に関する説明を切り出したものです。 最初は Frontend-Ops 全体をテーマとしてまとめて記事にしようと考えたのですが、polyfill だけでも色々と面白い話が出てきたので、今回は polyfill をピックアップして紹介しようと思います。
polyfill とは、仕様で策定されている機能や Proposal *1 を、それがサポートされていない環境でエミュレートするためのライブラリです。これにより、モダンブラウザでしか実装されてない機能が古いブラウザ(IE11など)でも動かせるようになります。例えば String#startsWith
のpolyfillは以下のようになります。
// https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith#Polyfill より if (!String.prototype.startsWith) { Object.defineProperty(String.prototype, 'startsWith', { value: function(search, rawPos) { var pos = rawPos > 0 ? rawPos|0 : 0; return this.substring(pos, pos + search.length) === search; } }); }
このように、その環境にあるAPIを組み合わせて、実装されていないAPIと互換性のあるものを作ることで、古いブラウザでも String#startsWith
を呼び出せるようになります。
実は polyfill という言葉は元々あったものではなく、2009年に Remy Sharp 氏 (nodemonの作者) によって生み出された造語です。いくつもの(poly)テクニックを使用して足りない穴を埋める(fill)ことから「polyfill」と命名したとのことです。まさにピッタリの語ですね。元々 Introducing HTML5 という書籍を書くにあたって生み出された造語で、書籍を通じて次第に世の中に広まっていったとされています。当時の経緯については氏のブログで紹介されています。
polyfill と同じように、仕様で策定されている機能やProposalをエミュレートする技術に「トランスパイラ」があります。一見すると polyfill と同じように見えますが、ちゃんと違いがあります。
a ?? b
を(a !== undefined && a !== null) ? a : b
に変換したり具体例を挙げると requestidlecallback や core-js が polyfill、babel や tsc (TypeScript のコンパイラ) がトランスパイラに相当します。
また同様に polyfill と同じように使われる言葉として「shim」というのがありますが、これもまたpolyfillとは違いがあります *2。
str.startsWith('prefix')
と書いたら、それが古いブラウザでも同じように動く、みたいなstr.startsWithByPolyfill('prefix')
みたいにpolyfillのことを意識して書く必要がない<img src"..." loading="lazy">
が使えるけど、古いブラウザだとJSで動的にスクロール位置を判定して実現しないといけない<img data-src"..." class="lazyload">
で遅延ロードできるようにするというのが lazysizes の仕事<img src"..." loading="lazy">
から微妙にAPIが変わってしまっているrequestIdleCallback
の polyfill である requestidlecallback を例に挙げてみます。requestIdleCallback
は CPU の Idle time に渡されたコールバックを実行するための API ですが、この API は Safari や IE11 では実装されていません。そのため、そうしたブラウザでもrequestIdleCallback
を使ったアプリケーションを実行するには、requestidlecallback を読み込む必要があります。しかし、この polyfill は完全にrequestIdleCallback
の仕様に準拠している訳ではありません。というのも、polyfill というものは実行環境にあるAPIを組み合わせて、実装されていないAPIと互換性のあるものを作る、というアプローチを取っています。そのため、実行環境のAPIで表現しきれないような挙動を実現することができません。例えば、requestIdleCallback
ではCPUが idle になっているかを知るAPIがSafariやIE11に存在しないため、requestIdleCallback
の仕様通りに動くpolyfillを作ることができません。そこでこうしたpolyfillでは多くの場合、可能な範囲で互換性を保ち、それっぽく動くよう設計されます。requestidlecallback ではsetTimeout
を用いてコールバックが非同期で実行されるという性質は維持しつつ、idle time でコールバックが実行されるという性質は諦めるような設計となっています。
このようにpolyfillが完全に仕様に準拠しているかは、そのpolyfillがエミュレーションしようとしている機能と、ターゲットとしている実行環境によって変わってきます。polyfillがあるからと言って必ずしも全てのブラウザで同じような挙動をする訳ではない、という点を抑えておきましょう。
Promise
/Map
/Set
などbabel-polyfill
/ @babel/@polyfill
と名前を変えていく
@babel/@polyfill
が非推奨になり、core-jsを使ってpolyfillを挿入することが推奨されるように
useBuiltIns
で必要なpolyfillのみがbundleされるようにfetch
とか
昔と比べてブラウザの自動アップデートが当たり前になり、仕様の標準化が進んでブラウザの差異は解消されつつありますが、全てのユーザに最新のバージョンのブラウザの利用を強制するのが困難なこと、またChrome/Safari/Firefoxのようにブラウザが複数存在し、それぞれの実装に差異があることを考えると、今後もcore-jsを使っていくことになるでしょう。以前と変わらず、必要に応じてcore-jsでサポートされていない部分のpolyfillを入れていくようにしましょう。
近年 Web Vitals などの文脈で、Webでもパフォーマンスが重視されつつありますが、この話は polyfill にも関わってきます。というのも、polyfill はバンドルに含めてユーザに配信するため、polyfill を導入することでバンドルサイズが増えてしまうからです。IE11でしか使われないpolyfillがChromeやFirefoxなどでもダウンロードされてしまう、といったように、本来polyfillを必要としていないブラウザで、余計なオーバヘッドが掛かってしまう恐れがあります。
そうした問題を解決するため、次のような対策が取られることがあります。
useBuiltIns
で必要なpolyfillのみがbundleされるように<script type="module">
/ <script nomodule>
でエントリポイントを分け、nomodule側にのみpolyfillを仕込む
<script type="module">
をサポートするブラウザの中で更に分岐させてpolyfillを出し分ける、といったことまではできないpolyfill の概要の説明から始まり、 閑話休題も挟みつつ、polyfill の今と昔、それから未来について見てきました。polyfill という小さなトピックを取り上げましたが、色々な話が出てきて面白かったですね。そのうち Hatena Developper Blog でも Frontend-Ops をテーマとした記事が色々と出てくると思うので、良かったらそちらもご覧になって下さい。
そうそう、面白い話というと近々弊社のイベントで登壇して、チームにおけるフロントエンドの属人化を頑張って解消していく話をする予定です。近々告知が出る予定ですので、良かったらそちらもご覧になって下さい。 => 告知でました! (2020/12/12 追記)
明日は id:stefafafan さんです。
*1:標準化される前の提案段階の機能のこと。代表的なものとして、ECMAScript の top-level await などがあります: https://github.com/tc39/proposal-top-level-await
*2:こちらも先程紹介した Remy Sharp 氏の記事 が出典です。
この記事はPokémon RNG Advent Calendar 2020 1日目の記事です。
皆さんお元気でしょうか。楽しみにされていた方は大変お待たせしました。Pokémon RNG Advent Calendar、2年振りの開催となります。去年はとある問題により開催を渋々見送らさせて貰っていたのですが、今年は何とか開催に漕ぎ着けることができました。めでたい!!!また様々なメンバーによる、ユニークなコンテンツを見れると思うと楽しみですね。クリスマスまで楽しんでいきましょう。
さて、今年のオープニングは「ポケモン乱数調整Wiki」についてです。
乱数調整は、個体値のポケモンを出したい、色違いポケモンを狙って出したい、珍しいアイテムを手に入れたい、などなど誰もが抱くであろう願いを実現するために編み出されました。そしてその有用性や応用性が明らかになるにつれ、乱数調整の手法も発展していきました。今日では単に珍しいポケモンやアイテムを入手するための手段としてだけでなく、乱数調整を行うこと自体に楽しさを見出し、面白おかしな乱数調整を探求する人も現れるなど、乱数調整は多くの人に、様々な角度から楽しまれています。インターネット上ではそうした人々によるコミュニティが形成され、コミュニティから日々乱数調整に関する記事やツールが多く公開されています。
しかしながら、乱数調整について何も知らない状態から乱数調整に挑戦するのは非常に難しい、という話題があります。これは単に乱数調整に関する入門資料がない、というだけでなく、インターネット上に存在する記事の多くで誤解を招く説明や正確でない説明がなされている、というのも一因として挙げられます。よく考えてみるとこれは自然なことで、乱数調整というものはコンピュータの性質 *1 を逆手に取って成り立っているので、どうしても丁寧に説明しようとすると計算機科学などへの理解が求められます。これを理解するのは多少計算機の知識がある人ならまだしも、そうでない人からしたら本当に大変なことです。加えて正確で明瞭な用語を選んで、できるだけ誤解されないような説明をするのも、高度なスキルを要求される非常に難しい作業です。そうしたことを踏まえると、インターネット上に乱数調整の入門の取っ掛かりとなる良い資料が無い、というのは仕方のないこと言えるでしょう。
とはいえ仕方がないといっても乱数調整に入門したい人からしたら困ったままです。加えて、これは乱数調整に慣れている人にとっても深刻な問題です。多少知識があったとしても、不正確な表現がどれであるのかを見抜き、自信を持ってこれは違う!と言える人は僅かです。誤った理解をしてしまい、それを元に誤った記事を書き、また誤った理解が伝播していく…というように誤解はどんどん伝播していきます。事実、インターネット上ではこうした記事が溢れてしまっているのが現状です。
さてこれは困った、ということでコミュニティ内でも話し合いが行われ、様々な意見やアイデアが出ました。その中で良さそうなのでやってみよう、ということで動き出しているのが「ポケモン乱数調整Wiki」という取り組みです。
これはポケモンの乱数調整に関する情報を集約した、コミュニティベースによって運営されるwikiを作る、という取り組みです。様々な工夫があるのですが、ここがポイントというのをいくつか書いてみます。
今の所査読者をやってもらえそうな人や記事を書いてくれそうな人に声掛けしたり、Wikiの基盤を作ったり…という感じでまだ1コンテンツもない状態なのですが、少しずつ進めております…!Wikiを立ち上げて、査読のフローを整備して、お試しでお手本となる記事を用意して、一般のコミュニティメンバーに記事を寄稿してもらえる体制を作って…というようにまだまだやることは沢山あるのですが、今暫くお待ち下さい。また続報があればブログ等でお知らせしようと思います。その時にまたWikiを見てフィードバックを頂けたり、Wikiの立ち上げにご協力いただけると助かります。あ、もちろん記事の執筆者や査読者も募集中です!我こそはという方は是非お声がけ下さい。お待ちしてます :)
という訳でポケモン乱数調整Wikiという取り組みについてご紹介しました。本当は今頃には皆さんから記事の寄稿を受け付けられる状態にしたかったのですが、全然作業が進んでいなくて申し訳ない!すみませんすみません… 中々まとまって作業する時間取れなくて今暫くお待ち下さい。
Pokémon RNG Advent Calendarですが2日目は担当者不在なので、次は3日目の @sub_827 さんかな? 楽しみですね。あ、もちろん2日目書きたい人がいらしたら今すぐ投稿されても良いんですよ…?
今年もPokémon RNG Advent Calendar楽しんでいきましょう!
noreferrer
が自動的に付与されつつある、という説明をしていましたが、正しくは noopener
の間違いでした。失礼しました。既に記事の方は修正済みです。追記終わり。
target="_blank"
は新しいタブでリンク先を開くためのオプションですwindow
オブジェクトにアクセスできるという、ちょっと癖のある挙動がありますtarget="_blank"
な <a>
タグには noopener
を指定することが推奨されています
window
にアクセスできなくなります (window.opener
が undefined
になる)noopener
を付けると互いのページが別々のプロセスで実行されるようになり、リンク先のページからリンク元のページのメモリ上のデータを推測することが不可能になりますwindow
オブジェクトの保護」 + 「リンク元のページのメモリ上に展開されているデータの保護」が noopener
の役割target="_blank"
な <a>
タグ全てに問答無用で付けなければならないのか、という疑問が当然出てくると思いますが、実はそうでもないですwindow
オブジェクトの保護や、リンク元のページのメモリ上に展開されているデータの保護が不要な時はなくても問題ありませんwindow.opener
を参照されるのは困るけど、same-origin なら所有者は我々であり、悪意のあるコードはないはずなので、 window.opener
を参照されても問題ない、という発想window.opener
をどうしても参照したい時
window.opener
使いたいんだったら noopener
付けたら駄目でしょ、という当たり前の話window.opener
を使わないほうが良いですMessageChannel
という代替技術を使うのが推奨されています
target="_blank"
な <a>
タグ全てに noopener
を付けておく、という規約を導入するというのが個人的にはオススメです
noopener
付いていない <a>
タグをコピペしてきて、 フィッシング詐欺に発展してしまう、みたいなことも防げるnoopener
いちいち付けなくても、same-origin 以外では window.opener
を制限する、みたいなことができるtarget="_blank"
な <a>
タグにブラウザがデフォルトで noopener
を付与するようになっていますnoopener
を付けていくのが当たり前になりつつある訳ですねtarget="_blank"
な <a>
タグに指定できるオプションとして noreferrer
というものがあり、これも noopener
と合わせて使われることがあります
noreferrer
は <a>
タグのリンク先からリンク元の情報を取得できないよう制限するオプションです<a>
タグのリンク先に遷移する際に、遷移元の URL がリクエストの Referer
ヘッダに載らなくなりますwindow.opener
から遷移元の情報が取れてしまうので、noreferrer
を付けるとこれも undefined
になります
noopener
の役割」 + 「Referer
header の除外」が noreferrer
の役割noreferrer
が noopener
と一緒に使われるのは、古いブラウザで window.opener
を undefined
にするため
window.opener
が問題視され始めた当時は、noopener
をサポートしていたブラウザには限りがあったため
noreferrer
は noopener
よりも古くからあるオプションで、 IE11 でもサポートされている (ただし win10 の IE11 のみ / win7〜8.1 の IE11 ではサポートしてない)
noopener
の fallback として、noreferrer
が使われることが多かったはず (はず、というのは僕が当時の Web の状況に詳しくないから)noreferrer
には副作用があります
Referer
header が無くなるので、リンク先からどこからユーザが流入してきたのか追えなくなってしまう?utm_campaign=...
みたいなクエリを URL につけておくとかReferer
header があることでどれくらいできることが広がるのか、というのはよく分かっていないnoreferrer
を付けないと IE11 ユーザを危険な状態に晒すことになるので、慎重に検討しましょうnoopener
の fallback として使いたい場合...
noopener
サポートされているので、IE11 サポートしていないサービスでは noreferrer
付けなくて良いはずnoreferrer
を付けておくと安全
*1:では noopener 付けていないページは今危険な状態に晒されているのか、というとそうでもないです。というのも、Spectre を成立させるにはメモリを覗きたいページが同一プロセスに載っていること、高精度のタイマー API が利用可能であること、という 2 つの条件がどちらも成り立っていなければなりません。Spectre が発見されてすぐにブラウザはこの後者の API を JS で無効にしていて、原理的に Spectre を成立しないようにしています。じゃあ Spectre 成立しないなら noopener 付けなくて良いじゃん、というとそうでもなくて、window.opener があることで高精度のタイマー API をブラウザが提供することができなくなってしまいます。他にも、window.opener のセキュリティ上の懸念で実装できない API が今後出てくるかもしれません。そうした API をブロックしてしまわないよう、noopener を付けていく / window.opener を無効にする、というのが今後ますます重要になってきます。要は付けないと Web の進化に置いてかれます。
超軽量で strictly-typed な (強く型付けされた) Event Emitter を作りました。
従来 Event Emitter は ブラウザでは EventTarget
として、Node.js では EventEmitter
として、それぞれ独自に実装されていました。これらは機能的には変わりがありませんが、インターフェイスの互換性がありません。そのため、両方の環境で同じ API で動作する universal な Event Emitter が欲しければ、eventemitter3
のようなライブラリを利用する他ありませんでした。しかし、最近になってブラウザで実装されている EventTarget
が Node.js に実装され始め *1*2、EventTarget
が Universal な Event Emitter としての地位を確立しつつあります。
EventTarget
はネイティブな API であるため、eventemitter3
のような 3rd-party ライブラリと比較してサイズが小さい *3 という利点があります。しかし、一方で EventTarget
は eventemitter3
のように dispatch するイベントの種類を制限したり、addEventListener
に渡したイベント名からリスナーで受け取れるイベントの値の型を推論することができません。そのため、予期せぬ種類のイベントが dispatch される可能性を考慮してコードを記述する必要があったり、明示的に型チェックを行わなければならないといった問題がありました。
@mizdra/strictly-typed-event-target
の紹介そこで、@mizdra/strictly-typed-event-target
というライブラリを作りました。EventTarget
と CustomEvent
をベースに作られているため、とても軽量です。ES Module 形式と UMD 形式の2つのビルドが用意されていて、この内 ES Module 形式はなんとたったの 150 B (厳密にいうと 152 B) で構成されています。
FooEventMap
のようなインターフェイスにイベント名とイベントの値の型のリストを記述し、createSTEventTarget
に型パラメータとして渡すと、強く型付けされた CustomEvent
と EventTarget
が返り値で得られます。簡単ですね。eventemitter3
を触ったことのある人なら分かると思うのですが、EventMap
インターフェイスを渡して型付けする部分は eventemitter3
を真似てます。
import { createSTEventTarget } from '@mizdra/strictly-typed-event-target'; interface FooEventMap { onmessage: string; onerror: Error; oninstall: undefined; } const [FooCustomEvent, FooEventTarget] = createSTEventTarget<FooEventMap>();
FooCustomEvent
/ FooEventTarget
はネイティブのものと同じ API が生えていて、全く同じように使えます。ただし、FooCustomEvent
の detail
フィールドが EventMap
に応じて型付けされていたり、EventMap
で定義されていないイベントの dispatch が禁止されていたりと、より強く型付けされた APIとなっています。
const fooEventTarget = new FooEventTarget(); /** `addEventListener` */ // error: Argument of type '"invalid-event"' is not assignable // to parameter of type '"onmessage" | "onerror" | "oninstall"'. fooEventTarget.addEventListener('invalid-event', () => {}); fooEventTarget.addEventListener('onmessage', (event) => { // `event.detail` is infered `string` type. }); fooEventTarget.addEventListener('onerror', (event) => { // `event.detail` is infered `Error` type. }); /** `dispatchEvent` */ fooEventTarget.dispatchEvent( new FooCustomEvent('onmessage', { detail: 'hello' }) ); // error: Type 'Error' is not assignable to type 'string'. fooEventTarget.dispatchEvent( new FooCustomEvent('onmessage', { detail: new Error() }), ); fooEventTarget.dispatchEvent(new FooCustomEvent('oninstall'));
実装をよく見てもらえると分かるのですが、ライブラリの大部分は型情報で、JS にトランスパイルされた時に残る部分は createSTEventTarget
の実装部分だけです。createSTEventTarget
も本当に素朴なことしかしていなくて、ネイティブの CustomEvent
/ EventTarget
をただ strictly-typed な CustomEvent
/ EventTarget
へと type assertion しているだけです。ズルいですね。
export function createSTEventTarget<EventMap extends {}>() { const STCustomEvent = (CustomEvent as unknown) as STCustomEvent<EventMap>; const STEventTarget = EventTarget as STEventTarget<EventMap>; return [STCustomEvent, STEventTarget] as const; }
そしてこれをトランスパイルし、ES Modules 形式で出力したものが以下になります。これで丁度 152 B です。
export function createSTEventTarget() { var STCustomEvent = CustomEvent; var STEventTarget = EventTarget; return [STCustomEvent, STEventTarget]; } //# sourceMappingURL=index.js.map
ちなみにより踏み込んだ話をするなら、minify すればもっと小さくなりますし、何なら以下のように型定義だけ使えば、トランスパイル時に型定義が削除されて 0 B になります。まあたった 152 B を嫌って長ったらしい型注釈を書きたい人は居ないはずなので、ただの面白テクニックという感じですが。
import { STCustomEvent, STEventTarget, } from '@mizdra/strictly-typed-event-target'; interface FooEventMap { onmessage: string; onerror: Error; oninstall: undefined; } const FooCustomEvent = (CustomEvent as unknown) as STCustomEvent<FooEventMap>; const FooEventTarget = EventTarget as STEventTarget<FooEventMap>;
EventTarget
が型安全ではないという説明がなされていましたが、これは誤りでした。実際には EventTarget
は型安全であり、本ライブラリはそれをより強く型付けしたライブラリという位置づけです。そこでそれを反映すべくライブラリを strictly-typed-event-target
から strictly-typed-event-target
に rename しました。*1:2020/09 現在ではまだ一般ユーザに公開されていない、internal で実験的な機能です。
*2:IE11及びSafariでは一部のAPIがサポートされていません。
*3:むしろ一切バンドル不要なので、実質 0 B
ポートフォリオに載っけられるよう、学んだ知見はできるだけ何らかの形にしてオープンインターネットに放流しているので色々ある。何が言いたいかと言うと挑戦した結果をついでにアウトプットしておくと武器になってお得ということです。
ポケットモンスター・ポケモン・Pokémon・は任天堂・クリーチャーズ・ゲームフリークの登録商標です.
当ブログは @mizdra 個人により運営されており, 株式会社ポケモン及びその関連会社とは一切関係ありません.