明るい海中にフグとナスオモリを配置したナスオモリ沈下シミュレーターの紹介画像

ナスオモリの沈み方を見比べるWebアプリを作りました

ナスオモリの重さや素材を変えると、底につくまでの時間はどれくらい変わるのでしょうか。 釣り場では、なんとなく「重い方が速い」「タングステンは小さいから沈みやすそう」と考えています。ただ、その差を数字や動きで見比べようとすると、頭の中だけでは整理しにくいです。 そこで、ナスオモリの沈み方を見比べるための小さなWebアプリを作りました。 ナスオモリ沈下シミュレーター 重さ・金属・水深で着底時間を比較 開く アプリ: ナスオモリ沈下シミュレーター 計算根拠: ナスオモリの沈み方をどう計算しているか この記事では、アプリでできることと、釣り場でどう使うとよさそうかをまとめます。 作った理由 最近、ゴロタ浜やサーフで底を探る釣りをすることが増えました。 底の石に当たる感触、根掛かりしにくさ、アタリの出方。こういうものは、シンカーの形や浮力でかなり変わります。フロートシンカーは根掛かりには強いですが、底からの情報は少なくなります。逆に普通のオモリは底の情報が出やすいものの、場所によっては根掛かりが怖いです。 その中で、ふと気になったのが「沈む時間」でした。 同じ1oz前後でも、鉛、タングステン、ブラス、鉄では体積が違います。重くすれば速く沈みますが、体積も大きくなって水の抵抗も増えます。仕掛けやラインまで含めると、さらに単純な話ではなくなります。 もちろん、実際の海では潮流、糸ふけ、エサ、仕掛けの姿勢で結果が変わります。ですから、このアプリは正解を出すためのものではありません。条件を変えたときに、沈み方の傾向を見比べるための道具として作りました。 このアプリでできること アプリでは、4つのナスオモリを同時に並べて沈められます。 それぞれのオモリについて、素材と重さを変えられます。素材は鉛、タングステン、ブラス、鉄です。重さは1gから120gまでの範囲で指定できます。 鉛 タングステン ブラス 鉄 水の条件も変えられます。 水深:1mから100m 水質:真水、海水 水の抵抗:0.10から4.00 画面には、代表オモリの着底時間、終端速度、水の密度、実際に沈む距離が表示されます。アニメーションを止めたり、タイムラインを動かしたりしながら、同じ条件で沈み方の差を見られるようにしました。 たとえば、鉛の10g、14g、21g、28gを並べれば、一般的な号数違いの感覚へ近づきます。素材だけを変えれば、同じ30gでもタングステンの方が小さく、ブラスや鉄の方が大きくなることも見えやすいです。 まずは基本条件で見比べる 最初は、初期値のまま眺めるのが分かりやすいです。 初期状態では、海水、水深5m、水の抵抗2.00で、鉛の10g、14g、21g、28gを並べています。アプリ上の沈下距離は、オモリの見た目サイズを考慮して、水深より少し短くなります。 オモリ 素材 沈下距離の目安 終端速度の目安 着底時間の目安 10g 鉛 4.37m 0.88m/s 5.0秒 14g 鉛 4.30m 0.94m/s 4.7秒 21g 鉛 4.19m 1.00m/s 4.3秒 28g 鉛 4.11m 1.05m/s 4.0秒 このくらいの浅い水深では、違いは数秒単位ではなく小数秒として出ます。釣りをしている最中に正確に感じ分けるのは難しいかもしれませんが、「重さを上げるほど速くなる。ただし倍の重さでも半分の時間にはならない」という傾向は見えます。 もう少し差を見たいときは、水深を20mや50mへ上げると分かりやすいです。水深が深くなるほど、終端速度に近い状態で進む時間が長くなり、素材や抵抗の違いが表に出やすくなります。 同じ30g、水深20m、海水、水の抵抗2.00で素材だけを変えると、おおよそ次のようになります。 素材 終端速度の目安 着底時間の目安 鉛 1.06m/s 18.1秒 タングステン 1.29m/s 14.9秒 ブラス 0.95m/s 20.2秒 鉄 0.92m/s 20.8秒 同じ重さなら、密度が高いタングステンは体積が小さくなり、水の抵抗を受ける面積も小さくなります。そのため、このモデルでは鉛より速く沈みます。ブラスや鉄は鉛より体積が大きくなり、少し遅く沈みます。 ...

公開: 2026年4月29日 · Toshihiko Arai
PlaywrightでReact + ViteフォームのUI確認を自動化するイメージ

Playwright入門。リリース前のUI確認を自動化するメリットと導入手順

Playwrightを触ってみて、これはかなり使えるのではないかと思いました。 UIテストの道具として便利なのはもちろんですが、AIにコードを書かせる機会が増えるほど、意図していない場所が壊れていないかを機械的に確認する仕組みが欲しくなります。 特に個人開発では、リリース前に毎回ブラウザを開いて、 トップページが開くか フォームを送信できるか 検索やフィルタが動くか 登録、編集、削除の主要な流れが壊れていないか AIに直してもらった場所以外が壊れていないか といった確認を手でやりがちです。最初は数分でも、画面や機能が増えると抜け漏れが出ます。 Playwrightは、この「毎回ブラウザでやっている確認」をコードにして、同じ条件で繰り返し実行できるE2Eテストの道具です。スクリーンショットや動画も残せるので、テストだけでなく、YouTubeや記事用に動作説明の素材を作る用途にも使えそうです。 この記事では、React + Viteで作った問い合わせフォーム を例に、Playwrightを入れてフォーム操作を自動確認するところまでを書きます。 全体像は、手動確認をテストコードに置き換え、ブラウザで自動実行し、失敗時はレポートやtraceで原因を追う流れです。 Playwrightとは Playwrightは、ブラウザを自動操作してWebアプリの動きを確認できるE2Eテストフレームワークです。 E2EはEnd to Endの略で、ユーザーが実際に画面を開いて操作する流れに近い形でテストします。たとえば、次のような操作をコードで書けます。 ページを開く 入力欄に文字を入れる ボタンを押す 検索結果が表示されることを確認する フォーム送信後のメッセージを確認する 単体テストが関数や部品単位の確認に向いているのに対して、Playwrightは「画面上で主要な操作が最後まで通るか」を確認する用途に向いています。 PlaywrightはChromium、Firefox、WebKitを扱えます。ただし、初めて導入する段階では、いきなり全ブラウザを対象にしなくても大丈夫です。まずはChromiumだけで、リリース前に毎回手で確認している重要な操作を1つ自動化するところから始めると進めやすいです。 触って便利だと感じたところ まだ深く使い込んでいるわけではありませんが、触ってすぐ便利だと感じたのは次のあたりです。 クリックや入力の前に、要素が操作可能になるまで待ってくれる expect を使って画面上の見出し、ボタン、メッセージを確認できる 失敗時のスクリーンショット、動画、trace、HTMLレポートを残せる UI Modeで、ブラウザの動きを見ながらテストを書ける 開発サーバーの起動を webServer でまとめられる Chromium、Firefox、WebKitを同じテストで確認できる AIにコードを直してもらったあと、「指示した箇所は直ったが、別のフォームが壊れた」ということは普通に起きます。Playwrightで主要フローだけでも自動確認しておけば、その手戻りに気づきやすくなります。 最初はフォーム送信だけでもよい Playwrightを入れると、つい全画面を自動化したくなります。ただ、最初から広げるとテストを書くこと自体が重くなります。 まずは、今回の問い合わせフォームのように、壊れると困る操作を1つだけ選ぶくらいでよさそうです。 ページが開ける フォームへ入力できる 送信後の結果が表示される これだけでも、リリース前に毎回手で確認していた作業を1つ減らせます。慣れてきたら、検索、登録、編集などに広げれば十分だと思います。 React + ViteフォームにPlaywrightを入れる 今回は、React + Viteで作った小さな問い合わせフォームを例にします。 以降のコマンドは、React + Viteフォームアプリのプロジェクト直下で実行する前提です。 まず、Playwright Testを開発依存として追加します。 npm install -D @playwright/test 初回はブラウザも入れます。まずはChromiumだけで十分です。 npx playwright install chromium 新規プロジェクトでひな形ごと作りたい場合は、公式の npm init playwright@latest から始めてもよいです。この記事では、既存のReact + Viteアプリへ手で追加する流れにします。 ...

公開: 2026年4月28日 · Toshihiko Arai

React + Viteの初歩的な理解を深める。

Reactと合わせてよく見かける、Viteって何だろう。Next.jsとは何が違うんだろう。 そんなところで少し疑問に思ったので、さらっと学習してみました。 AIによって生成されたアーキテクチャやソースコードで意味が分からないままだと、あとで自分で直したいときに困ったことになります。 AIに改修を任せる場合でも、レビューは必要ですから、最低限の知識は入れておきたいですよね。 さて今回は、React + Viteで小さな問い合わせフォームを作りながら、React、Vite、Next.jsの役割を整理してみました。 まずReact、Vite、Next.jsの役割を整理 最初に混乱しやすいのは、React、Vite、Next.jsがどの部分を扱っているのかよく分からないこと。 実際には、担当している範囲が違います。 ざっくり分けると、次のようになります。 名前 役割 この記事での見方 React UIを作るライブラリ 画面をコンポーネントとして作る Vite 開発サーバーとビルドの道具 Reactアプリを快適に開発し、公開用ファイルへまとめる Next.js Reactベースのフレームワーク ルーティング、SSR / SSG、サーバー側処理なども含めてアプリを作る なるほど、Next.jsはReactを元に増強したフレームワークなのですね。一方でViteはビルドなどやりやすいようにしてくれる、開発支援ツールといったところでしょうか? もちろんReactは、画面を部品として組み立てるためのライブラリです。コンポーネント、JSX、state、イベント処理といった考え方が中心になります。 Viteは、Reactアプリを開発するときの開発サーバーや、本番公開用のビルドを担当する道具です。ちなみに Vite は「ヴィート」と読みます。保存した変更を素早くブラウザに反映するHMR (ホット・モジュール・リプレイスメント)も、Viteのありがたさを感じやすい部分です。とはいえ、今時この手のツールは当たり前すぎて、あまり意識していなかったようです。 Next.jsは、Reactを土台にしたフレームワークです。ファイルベースのルーティング、SSR、SSG、Route Handlersなど、アプリ全体を作るための機能をまとめて持っています。SSR、つまりサーバーサイドレンダリングですが、ここら辺が Next.js の魅力といったところでしょうか。 さて今回は、学習用に小さなフォームアプリをReact + Viteで作ってみます。SPA(シングルページアプリケーション)ですが、ペラ1のめちゃ簡単なUIのみで、メールサーバーも何もないのであしからず。 React + Viteプロジェクトを作る それではプロジェクトを作成して実装していきましょう。 Vite公式のGetting Startedでは、npm create vite@latest からプロジェクトを作れます。 Vite 8系ではNode.js 20.19+ または 22.12+ が必要です。古いNode.jsを使っている場合は、先に更新しておきます。 まずはNode.jsのバージョンを確認します。 node -v 次に、Reactテンプレートでプロジェクトを作ります。 npm create vite@latest react-vite-form-app -- --template react cd react-vite-form-app npm install npm run dev 対話形式で進める場合は、次のように選びます。 ...

公開: 2026年4月28日 · Toshihiko Arai
Shell Stash と Quake Radar を斜めに並べたアイキャッチ画像

公開中のWebアプリまとめ

公開中のWebアプリをまとめていくページです。 今後Webアプリが増えたら、このページに追記していきます。まずは、シェルコマンドを管理する Shell Stash - シェル手帖 と、地震情報を地図と時間軸で見られる Quake Radar を公開しています。 Shell Stash - シェル手帖 Shell Stash - シェル手帖 は、よく使うシェルコマンドを保存し、検索して、必要に応じて値を差し替えてコピーできるWebアプリです。 サーバー作業や開発作業をしていると、便利だったワンライナーや、あとでまた使いたいコマンドがいろいろな場所に散らばりがちです。Shell Stash は、それらを一か所にまとめて、あとから再利用しやすくするために作りました。 主な機能は次のとおりです。 コマンドと短いメモを保存できる #タグ 付きのメモを検索できる 検索結果からすぐにコピーできる $APP や $ENV のようなプレースホルダーを検出できる プレースホルダーごとにプリセット値を登録できる JSONのエクスポート、インポートができる Google Driveへ手動バックアップできる ローカルのターミナル環境を便利にするツールとは違い、Shell Stash はブラウザで開いて使います。ステージング環境や本番サーバーに余計なプラグインを入れず、必要なコマンドだけを探してコピーしたいときに使いやすい形を目指しています。 Shell Stash - シェル手帖 CLIコマンドを保存・検索・再利用 開く Quake Radar Quake Radar は、日本の地震情報を地図と時間軸で見られるWebアプリです。 最近の地震を一覧で追うだけでなく、地図上の分布や時間の流れとして見られるようにしています。文字だけでは掴みにくい、どの地域で揺れが続いているのか、どのくらいの規模の地震がどの順番で起きているのかを、少し直感的に見られるようにしたアプリです。 主な用途は次のとおりです。 最近の地震を地図と時間軸でまとめて見る 最大震度やマグニチュードの違いを視覚的に確認する 東日本大震災や熊本地震の流れを地図上で見直す 地震活動を見ながら、日頃の備えを考えるきっかけにする Quake Radar は、気象庁などの公開データをもとに再表示しているアプリです。公式発表そのものではないため、避難判断や安全確保の判断には、必ず気象庁などの公式情報を優先してください。 Quake Radar 日本の地震情報を地図と時間軸で確認 開く 紹介記事: 日本の地震情報を地図と時間軸で見られる Quake Radar を公開しました 今後の更新方針 Webアプリを新しく公開したら、このページに概要、アプリURL、紹介記事へのリンクを追記していきます。 ...

公開: 2026年4月25日 · 更新: 2026年4月27日 · Toshihiko Arai
Quake Radar の画面

日本の地震情報を地図と時間軸で見られる Quake Radar を公開しました

日本の地震情報を、地図と時間軸で視覚的に見られる Web アプリ Quake Radar を公開しました。 Quake Radar 日本の地震情報を地図と時間軸で確認 開く このアプリでできることを先にまとめると、次の3つです。 最近の地震を、地図と時間軸でまとめて見る 東日本大震災や熊本地震の流れを、一覧ではなく分布で見直す 文字の羅列だけでは掴みにくい揺れの連続性を、視覚的に追う 「とりあえず今どこで揺れが続いているのか見たい」ときや、過去の大地震を地図ベースで見直したいときの入口 として作っています。 地震情報は普段から文字や一覧で目にすることが多いですが、実際に地図上へ並べて、時間の流れと一緒に見てみると、見え方がかなり変わります。 どこで揺れが続いているのか、どのくらいの規模の地震がどの順番で起きたのか、一覧だけでは掴みにくい流れが少し直感的に見えてきます。 もともと私は、CLI で地震情報を確認するための簡単な仕組み を手元で使っていました。 ただ、数字や地名を追うだけでは分かりにくい場面もあり、地図やタイムラインで見られた方が理解しやすいのではないかと思い、この形にしてみました。 Quake Radar でできること Quake Radar では、最近の地震を地図上にプロットして、時間軸に沿って再生できます。 色は最大震度、円の大きさはマグニチュードに対応していて、地震の規模や揺れの強さがひと目で分かるようにしています。 また、最新の地震情報だけでなく、東日本大震災や熊本地震のような過去の大きな地震も、当時の流れをたどれる形で表示できます。 現時点では、東日本大震災と熊本地震を切り替えて表示できます。 文字だけで読んでいた時には見えにくかった流れも、地図と時間軸に載せるとかなり掴みやすくなります。 同じ地域で続いている地震、少し時間を空けて起きる大きな揺れ、広い範囲での分布などが、一覧よりも掴みやすくなります。 過去の大地震を見直すと印象が変わる 特に東日本大震災のデータを見ていると、本震だけを単独で捉えるのではなく、その前に大きめの地震があり、その後に本震へつながっていく流れが視覚的に残ります。 普段のニュースやテキスト中心の情報では、どうしても「大きな地震が起きた」という一点で記憶されがちですが、時系列で並べてみると、災害の見え方が少し変わります。 熊本地震のように、比較的限られた地域で強い揺れが連続するケースも、一覧ではなく地図で見ると特徴がかなり掴みやすくなります。 同じ「大きな地震」でも、揺れの広がり方や続き方に違いが見えてきます。 もちろん、過去のデータを見たからといって将来を予測できるわけではありません。 ただ、災害を単なる過去の出来事として忘れてしまわず、改めて備えを考えるきっかけにはなるのではないかと思っています。 このアプリを公開した理由 最初は、手元の地震情報を少し見やすくしたいという延長で作り始めたものでした。 ただ、実際に形になってくると、単なる自分用のツールとして閉じておくより、公開しておいた方が少しでも役に立つかもしれないと思うようになりました。 災害は、意識していないと日常の中ですぐ遠のいてしまいます。 大きな地震の記憶も、時間が経つとどうしても薄れていきます。 Quake Radar が、日々の地震活動を見たり、過去の大きな災害を見直したりする小さなきっかけになればと思っています。 データについて Quake Radar は、気象庁などの公開データをもとに再表示しているアプリです。 最近の地震は API 経由で取得し、過去の大きな地震については表示用に整理したデータを使っています。 公式発表そのものではないため、実際の避難判断や安全確保の判断は、必ず気象庁などの公式情報を優先してください。 関連記事 CLI で地震情報を確認するための簡単な仕組み おわりに 災害への備えは、何か大きな出来事があった直後だけ意識して、しばらくすると薄れてしまいがちです。 Quake Radar は、そんな時に少し立ち止まって地震の流れを見直し、災害を忘れないためのきっかけになればと思って公開しました。 もしよければ、実際に触ってみてください。 https://quake.apppppp.com/

公開: 2026年4月19日 · 更新: 2026年4月25日 · Toshihiko Arai

Amazonの領収書のPDF保存をラクにする自作JS

個人事業主・フリーランスの方は、確定申告の時期になりましたね。私はAmazonで購入することが多く、領収書を電子保存しておく必要があります。ところが、これまで使っていたChrome拡張(Amazon領収書一括印刷系)が動かなくなってしまいました。 そこで仕方なく、Amazonの注文履歴から「領収書等」→「印刷可能な注文概要」を開き、黄色の「印刷」ボタンを押してPDF保存……という作業をひたすら繰り返していました。 さらに困るのが、PDF保存時のファイル名がデフォルトで「注文の詳細.pdf」などになってしまう点です。注文番号(例:XXX-XXXXXXX-XXXXXX)をファイル名にしたいので、毎回注文番号をコピーしてファイル名に貼り付けてから保存していました。これが地味に面倒でした。 「注文番号をDOMから拾って、印刷まで自動化できそうだな」と思い、ChatGPTに相談して作ったのが以下のブックマークレットです。 (ブックマークのURL欄に javascript: から始まるコードを貼り付けて実行する、あのやつです。) javascript:(()=>{const old=document.title;const re=/\b(?:\d{3}|[A-Z]\d{2})-\d{7}-\d{7}\b/;const m=document.body&&document.body.innerText&&document.body.innerText.match(re);const id=(m&&m[0])||prompt("注文番号(例: 250-3207065-8648623 / D01-5274236-7074631)");if(!id)return;document.title=id;window.addEventListener("afterprint",()=>{document.title=old},{once:true});window.print();})(); Note ブックマークは「ページを保存する場所」ではなく、実は“自分だけのショートカットキー”にもできます。 URL欄に javascript: を入れるだけで、ページ上の定型作業をワンクリックで実行可能。 拡張機能みたいにストア審査もアップデート追従も不要で、壊れにくいのが強みです。 必要なページでだけ動くので、普段のブラウジングを汚さないのも地味に便利。 小さな自動化を積み上げると、ブラウザが“作業ツール”に変わります。 使い方 Chromeのブックマークに「新しいブックマーク」を追加します ※図① 名前は適当に付けて、URL欄に上のコードをそのまま貼り付けます Amazonの領収書(印刷可能な注文概要)ページを開いた状態で、そのブックマークを実行します 印刷画面が開くので「PDFとして保存」を選ぶと、ファイル名に注文番号が入った状態になっているはずです ※図② これなら、手作業で1年分の領収書を保存する場合でも、そこまで苦にならないと思います。 参考になればうれしいです。 追記:注文日も拾って YYYYMMDD_注文番号 で保存する PDFのファイル名を注文番号だけでなく、注文日も付けて 20251231_503-1737382-0797449 のようにすると、Finderでソートしやすく後から探すのがさらにラクになります。 印刷ページ内の「注文日 2025年12月31日」をパースして、ファイル名の先頭に付ける版はこちらです。 javascript:(()=>{const old=document.title;const orderRe=/\b(?:\d{3}|[A-Z]\d{2})-\d{7}-\d{7}\b/;const dateNearRe=/注文日[\s\S]{0,80}?(\d{4})年(\d{1,2})月(\d{1,2})日/;const dateRe=/(\d{4})年(\d{1,2})月(\d{1,2})日/;const t=document.body&&document.body.innerText||"";const om=t.match(orderRe);const dm=t.match(dateNearRe)||t.match(dateRe);const orderId=om?.[0]||prompt("注文番号(例: 250-3207065-8648623 / D01-5274236-7074631)");if(!orderId)return;const y=dm?.[1],m=dm?.[2],d=dm?.[3];const pad=n=>String(n).padStart(2,"0");const prefix=(y&&m&&d)?`${y}${pad(m)}${pad(d)}_`:"";document.title=`${prefix}${orderId}`;window.addEventListener("afterprint",()=>{document.title=old},{once:true});window.print();})(); これで、保存ダイアログを開いた時点でファイル名が YYYYMMDD_注文番号 になっているはずです。注文日が見つからないページでも、注文番号だけで動くようにしてあります。 ちなみに上のコードを整形すると次のようになります。 javascript:(() => { const old = document.title; const orderRe = /\b(?:\d{3}|[A-Z]\d{2})-\d{7}-\d{7}\b/; const dateNearRe = /注文日[\s\S]{0,80}?(\d{4})年(\d{1,2})月(\d{1,2})日/; const dateRe = /(\d{4})年(\d{1,2})月(\d{1,2})日/; const t = document.body && document.body.innerText || ""; const om = t.match(orderRe); const dm = t.match(dateNearRe) || t.match(dateRe); const orderId = om?.[0] || prompt("注文番号(例: 250-3207065-8648623 / D01-5274236-7074631)"); if (!orderId) return; const y = dm?.[1], m = dm?.[2], d = dm?.[3]; const pad = n => String(n).padStart(2, "0"); const prefix = (y && m && d) ? `${y}${pad(m)}${pad(d)}_` : ""; document.title = `${prefix}${orderId}`; window.addEventListener("afterprint", () => { document.title = old }, {once: true}); window.print(); })(); 注意点 Amazon側のページ構成やリンク文言(「領収書」「領収書等」など)は変更されることがあります。ブックマークレットが動かなくなったら、まず実際のページ表記を確認してください。 一度に大量の注文を処理するとタブやダイアログが増えるので、数件ずつ実行するのが安全です。 関連記事 C++でOpenCVをはじめる|撮影したレシートを自動でトリミング … 紙のレシートを撮影して自動でトリミング・補正する画像処理の例 バニラJSのモダンな書き方・チートシート … ブックマークレットを書くときのJavaScript逆引きに Cloudflare Workerでサーバーレスな受付口を作る … 静的サイトに小さな処理を足したいとき 関連商品をAmazonで探す 確定申告ソフトをAmazonで探す ドキュメントスキャナーをAmazonで探す JavaScript入門書をAmazonで探す

公開: 2026年1月6日 · 更新: 2026年5月30日 · Toshihiko Arai

Webプッシュについて調査忘備録

Web Push API を使うと、ブラウザを開いていないユーザーにも通知を届けられます。仕事で実装する機会があり、調べた内容を忘備録としてまとめておきます。Service Worker・VAPID・Push サービスの 3 つが連携する仕組みを理解すれば、あとはライブラリが面倒な暗号化処理を代わりにやってくれます。サーバーサイドの実装は PHP(minishlink/web-push)で試す手順を紹介します。 Webプッシュのざっくり概要 Web プッシュは、ブラウザと OS の通知機能を使って「ブラウザを開いていなくても」通知を届ける仕組みです。 ユーザーがブラウザで「通知を許可」する ブラウザが Push サービス(FCM / APNs など)とやり取りして 購読情報(Subscription) を発行 サーバー側は、その購読情報(endpoint / p256dh / auth)を DB に保存 通知を送りたいときは、サーバーアプリケーションで Push サービスへリクエストを投げる Push サービス → OS の通知チャネル → Service Worker → 通知表示 という流れになります。 Service Worker が Web Push API の橋渡しを担います。Service Worker は JS で実装されたプログラムで、ブラウザにインストールされ、メインスレッドとは別スレッドで動作します。また、Service Worker を登録するページおよび Service Worker スクリプトは HTTPS で配信されている必要がある点に注意してください(ただし localhost は例外的に http でも動作します)。 もう少し詳しく もう少し詳しく説明すると、Web プッシュでは購読された時点でブラウザ側で一意のエンドポイントが発行されます。 このエンドポイントはブラウザベンダーごとに異なり、Google Chrome なら FCM(https://fcm.googleapis.com/...)、Safari / iOS なら APNs 経由のエンドポイントという形になります。 ...

公開: 2025年11月30日 · 更新: 2026年5月23日 · Toshihiko Arai

バニラJSのモダンな書き方・チートシート

React や Vue などのフレームワークを使わず、ブラウザ標準のJavaScriptだけで書くとき(いわゆるバニラJS)に毎回調べがちな構文をまとめました。非同期処理・配列操作・オブジェクトコピー・DOM操作・ストレージなど、実務でよく使うパターンを用途別に整理しています。Node.js でも動く構文は多いですが、主にブラウザ環境を想定しています。 ストレージ — sessionStorage / localStorage sessionStorage.setItem('myData', '保存したい内容'); // 保存 const savedData = sessionStorage.getItem('myData'); // 読み出す sessionStorage.removeItem('myData'); // 削除 sessionStorage.clear(); // 全て削除 sessionStorage は同一タブ内でのみ保持され、タブを閉じると破棄されます。最大容量はブラウザによりますがおおむね5MB。保存形式は文字列のみなので、オブジェクトを保存したい場合は JSON.stringify() で変換が必要です。 sessionStorage を localStorage に書き換えるとデータを永続化できます。 オブジェクトの凍結 — Object.freeze const Trial = { ok: true, ng: false }; Object.freeze(Trial); // オブジェクトを凍結 Trial.ok = false; // 非 strict mode ではエラーにならないが値は変わらない(strict mode では TypeError) console.log(Trial.ok); // true const ではプロパティの書き換えを防げません。Object.freeze() はトップレベルのプロパティ変更を防ぎますが、浅い凍結なので入れ子のオブジェクトは変更できます。JS で Enum を表現したいときに便利です。 非同期処理 — fetch / async / await async function fetchUser(userId) { const response = await fetch(`/api/user/${userId}`); if (!response.ok) throw new Error("通信エラー"); const data = await response.json(); return data; } fetchUser(1).then(user => { console.log(user.name); }).catch(err => { console.error(err); }); fetch() はブラウザ組み込みのHTTP通信APIです。await で非同期処理の完了を待てるため、Promise のチェーンよりも読みやすくなります。await を使う関数は async で宣言する必要があります。 ...

公開: 2025年9月3日 · 更新: 2026年5月24日 · Toshihiko Arai

【JetBrains系IDE】 IntelliJ IDEA の便利な設定(WebStorm・PhpStorm)

この記事は、IntelliJ IDEA / WebStorm / PhpStorm を毎日の開発で使っている人向けに、自分が実際に使っていて効果が大きかった4つの設定(File Watchers での SCSS 自動コンパイル、分割 JS の自動結合、フォントとサイズ、Markdown の Run gutter icon)を忘備録としてまとめたものです。全部を一度に入れる必要はなく、気になったものから1つずつ試して、合わなかったら戻せばOKです。JetBrains 系で UI が共通なので、PhpStorm や GoLand でも同じ手順で設定できます。 ショートカット系の設定や使い方は別記事に分けています。あわせて読むと作業効率がさらに上がります。 【macOS】IntelliJ IDEA ショートカット チートシート Clion x PlatformIOでESP32(Arduino)開発 はじめての Spring Boot 〜 JavaでWebアプリケーション 私は多くの言語でJetBrains系IDEのお世話になってます。もちろん、JetBrains All Products Pack を購入してます。 言語 IDE Java・JSP・Spring Boot IntelliJ IDEA JS・HTML WebStorm PHP・Laravel PhpStorm C++・Arduino・ESP32 CLion PostgreSQL・MySQL・SQLite DataGrip Python PyCharm GO言語 GoLand Android Android Studio こんな具合に、よく使う言語のほとんどが JetBrains からIDEがリリースされています。インターフェースや操作感も統一されているので、一度慣れてしまうとJetBrains以外のIDEで開発したくなくなります。以前はiOSアプリ開発のためにXCodeをよく使ってましたが、使い勝手が違いすぎて触りたくありません(笑)。 VS Codeもすっかり出番が少なくなりましたねぇ。 さて、そんな JetBrains系IDEの便利な設定を忘備録として残します。IntelliJ IDEA や WebStorm で使う設定が中心ですが、JetBrains系で他のIDEでも応用できる設定だと思います。ご参考ください。 ...

公開: 2025年9月2日 · 更新: 2026年5月30日 · Toshihiko Arai

文章AとBの類似率を数値化するJaccard係数をシェル・sqlite・mecabで実現してみた

はじめに このブログの記事Aと記事Bがどれだけ類似しているかを検出して、関連記事を自動化したいと思った。そこで簡単に思いつく方法は、それぞれの記事のキーワードを抽出し、お互いどれだけ共通のキーワードを持っているか調べれば良さそう。 そこでJaccard係数という手法を見つけた。 Jaccard係数とは Jaccard係数は、2つの集合 ( A ) と ( B ) の類似度を測る数学的なアプローチ。 $$ J(A,B)=\frac{|A\cap B|}{|A\cup B|} $$ 記事Aと記事Bのキーワードに当てはめて集合を考えると、 重複を取り除いた記事Aと記事Bのキーワードの合計が分母 重複する部分のキーワードだけを抽出したのが分子 となる。そしてこの割り算の結果をJaccard係数とし、 係数が大きいほど類似度が高いことを意味する。 Jaccard係数はsqliteで簡単に計算できる 次は、実際にこのブログサイトで関連記事を作成するために使っているSQLである。 全ての記事に対してJaccard係数を計算し、係数が0.1以上のものを関連記事として抽出する処理をさせている。 WITH target_words AS ( SELECT word FROM keywords WHERE filename = '__FILENAME__' ), intersections AS ( SELECT k.filename, COUNT(*) AS intersect_count FROM keywords k JOIN target_words t ON k.word = t.word WHERE k.filename != '__FILENAME__' GROUP BY k.filename ), unions AS ( SELECT k.filename, COUNT(DISTINCT k.word) + (SELECT COUNT(DISTINCT word) FROM target_words) - COUNT(DISTINCT CASE WHEN k.word IN (SELECT word FROM target_words) THEN k.word END) AS union_count FROM keywords k WHERE k.filename != '__FILENAME__' GROUP BY k.filename ) SELECT i.filename, CAST(i.intersect_count AS REAL) / u.union_count AS jaccard FROM intersections i JOIN unions u ON i.filename = u.filename WHERE CAST(i.intersect_count AS REAL) / u.union_count >= 0.1 ORDER BY jaccard DESC; 複雑に入り組んでいて読みにくいが、Jaccard係数を計算するために共通部分の要素を求めるintersectionsと、キーワードの和集合を求めるunionsがポイントである。 ...

公開: 2025年4月3日 · 更新: 2026年3月25日 · Toshihiko Arai