サクサク読めて、アプリ限定の機能も多数!
トップへ戻る
Wikipedia
zenn.dev/catnose99
個人的に「Webサービスの公開前チェックリスト」を作っていたのですが、けっこう育ってきたので公開します。このリストは、過去に自分がミスしたときや、情報収集する中で「明日は我が身…」と思ったときなどに個人的にメモしてきたものをまとめた内容になります。 セキュリティ 認証に関わるCookieの属性 HttpOnly属性が設定されていること XSSの緩和策 SameSite属性がLaxもしくはStrictになっていること 主にCSRF対策のため。Laxの場合、GETリクエストで更新処理を行っているエンドポイントがないか合わせて確認 Secure属性が設定されていること HTTPS通信でのみCookieが送られるように Domain属性が適切に設定されていること サブドメインにもCookieが送られる設定の場合、他のサブドメインのサイトに脆弱性があるとそこからインシデントに繋がるリスクを理解してお
2022年10月にHashnode(英語圏では人気のある技術ブログ作成サービス)に脆弱性を報告したのですが、最近になって修正されたようなので記事にしておきます。 Hashnode社の方には脆弱性について記事にすることの許可をもらっています[1]。 Hashnodeのカスタムドメイン設定機能について Hashnodeの目玉機能として、ユーザーごとにブログを作成し、そのブログにカスタムドメインを紐づけられる機能があります。カスタムドメインのブログであっても、LikeやフォローといったHashnodeの認証が絡む機能を使うことができます。 カスタムドメインが設定されたブログでもフォローなどの機能が使える hashnode.comにログインしていれば、ユーザーのブログ(example.com)を開いたときにもログイン状態が保持されているというわけです。 クロスドメインでログイン状態を保持するのはめ
iOSのブラウザ(Safari、Chromeなどなど)で体験の良いWYSIWYGエディタを作るのは無理ゲーである。色々と理由はあるが、いちばん辛いのはバーチャルキーボード(オンスクリーンキーボード)を表示したときの挙動だと思っている。 キーボードが表示されているときにposition: fixedが効かない WYSIWYGエディタではテキストの装飾や画像挿入などのボタンを画面のどこかに固定したくなることが多い。 しかし、iOS Safariではキーボードが表示されているときにposition: fixedなどのCSSだけで画面上に何かを固定させることが難しい。 position: fixedとbottom: 0 やtop: 0を使っても要素が画面に固定されない仕様となっている(これはposition: stickyにしても同じ)。 ワークアラウンドも上手く動かない noteやscrapbo
こんなWebサービスをリリースしたので、技術的な話をまとめておこうと思います。 元々このサービスは、趣味の延長線のような感じで開発を始めました。競合にあたるnoteやはてなブログなどのサービスが確固たる地位を築いているということもあり、「お金にはならないだろうけど、自分の趣味を詰め込んだものにしよう」というゆるい気持ちで開発を続けています(楽しい)。 選定の方針 趣味と言っても文章投稿サービスなので、ユーザーが少数であったとしても長期間運営しなければなりません。そのため、ユーザー数が少なければランニングコストが数千円/月以下、ユーザー数が増えたときは段階的にコストが上がるように選定を行いました。 アプリケーション フルスタックNext.jsアプリケーションをCloud Runにデプロイしています。各APIエンドポイントはNext.jsのAPI Routesで生やしています。 Next.js
Webサービスのステージング環境をアクセス制限をCloudflare Zero Trustでやってみたところ、とても手軽でちょうど良かった。特に必要な知識はなかったが、今後同じことをやりたくなったときのために設定内容をメモしておく。 やったこと Cloudflare Zero Trustで「特定のメールアドレスの所有者」にだけWebサイトへのアクセスを許可する(ここでは例としてhttps://app.example.com/*へのアクセスを制限する) 前提 ドメインをCloudflareで管理しており、DNS設定でプロキシモードが有効になっていること 設定その1: ログイン方法を追加しておく Cloudflareにログインした状態でZero Trustを開く Settings → Authentication → Login methodsでOne-time PINを追加しておく 指定した
今見てるWebページのOG画像をチェックしたくなるときがある。ソースコードを開いて画像のURLをコピペするのは面倒だし、ブラウザ拡張機能は本当に信頼できるものしか入れたくない。というわけで、ちょっとしたコードを書いて使い回せるようにしてみる。 1. ページ遷移で開く location.href = document.querySelector('meta[property="og:image"]').content
主な使用サービス/ライブラリは以下です。 Next.js …アプリケーションのフレームワーク Vercel …デプロイ先 PlanetScale …サーバーレスDB(MySQL)。ORMにはPrismaを使用 Upstash …サーバーレスでRedisを使えるやつ Cloudflare R2 …画像のアップロード先 Open AI API ここに落ち着くまでに紆余曲折あったので、少し詳しく説明しておきます。 Next.js on Vercel 利用しているフレームワークはNext.jsです。クライアントからのデータの取得・更新リクエストはAPI Routesから受け付けるようにしています。 アプリケーションのデプロイ先はVercelにしました。最初はNext.js on Cloudflare Workersをやろうとしたのですが、辛い部分が多くて断念しました。 余談)なぜNext.jsをC
先日だれでもAIメーカーというWebサービスをリリースしました。このサービスは例によってOpenAI APIを使っており、トークンの使用量がランニングコストに大きく影響します。 また、気軽に使ってもらえるよう未ログインでも使用できる仕様にしているため、気をつけないと悪意のある人に大量にトークンを使用されてしまう可能性があります。 ノーガードだとどうなるか 例えば、POST /api/askという「リクエストbodyのpromptの値を取り出し、OpenAI APIのChat Completionsに投げる」という単純なエンドポイントを作ったとします。 「未ログインでも使ってもらいたいから」と認証を一切しなかった場合どうなるでしょうか? 悪意のある攻撃者に見つかれば、promptを上限ギリギリの長さの文章に設定したうえで、/api/askに対してDoS攻撃するかもしれません。 トークンを大量
調査結果まとめ 日本の真ん中あたりから東京リージョンのCloudRunにアクセスしたときのTTFB(Time To First Byte)のざっくり計測結果。詳細は後述。 Cloud Runのデフォルトドメインに直接アクセスした場合: 28msくらい Cloud Runにカスタムドメインをマッピングした場合: 99msくらい さらにCloudflareからCNAMEで指した場合: 114msくらい Cloudflare WorkersでCloud Runのデフォルトドメインをプロキシした場合: 44msくらい Cloud Run + Cloud Load Balancing(CDNなし): 31msくらい Cloud Runの東京リージョンで「カスタムドメインのマッピング」を利用するとレイテンシが発生する 2023年1月現在、Cloud Runのドキュメントの既知の問題には以下の記載があり
OSSのnpmパッケージにおいて、第三者によるPRでyarn.lockやpackage-lock.jsonなどのロックファイルに変更が加えられている場合、すべての変更を徹底してチェックしなければならない。 なぜなら、パッケージの参照元となるyarnやnpmのレジストリのURLをしれっと改ざんされてしまうリスクがあるため。 例えば以下の画像のようにyarn.lockに定義されたパッケージのresolvedがhttps://registry.yarnpkg.com/...からhttps://malicious.example/...に書き換えられてしまうかもしれない。 lockfile-lint このリスクを軽減するのにlockfile-lintが便利。 例えば👆のコマンドではyarn.lockの中で npmとyarnのレジストリ以外のURLが参照されていないか すべてhttpsのURLにな
コンテンツ投稿系のWebサービスでは「ユーザーのページに好きな独自ドメインを登録できる」という機能をつけたくなることがあります。ユーザーからすると「コンテンツが自分自身の所有物であること」を感じやすいですし、コンテンツのポータビリティが上がりますし、とても夢がありますよね。僕もいつか実装してみたい機能のひとつです。 しかし、この機能を提供するには、以下のようなハードルがあります。 料金 ベンダーロックイン 複雑な実装(とくに認証) (1)の料金についてはデプロイ先によります。例えばVercelであればProプラン以上であれば無制限に独自ドメインを登録できます(Unlimited custom domains for all Pro teams)。 Google Cloudの場合にはCertificate Managerで独自ドメインごとの証明書を管理するのに「ひとつあたり○USD」という感
Googleスプレッドシートを操作するための準備 サービスアカウントの設定 GCPコンソールでGoogle Sheets APIを有効にする GCPコンソールのサービスアカウント設定でサービスアカウントを作成する。ロールは特に指定しなくてOK。ここでサービスアカウントのkeyとなるJSONを取得する 操作したいスプレッドシートを開き、共有設定にサービスアカウントのアドレス(foo@bar.iam.gserviceaccount.com)を追加する。参考 環境変数の設定 以上の操作が完了したらプロジェクトの環境変数として以下の3つを追加する(ハードコードは避ける)。 SHEET_ID='foo' # スプレッドシートのURLに含まれる文字列 GOOGLE_SERVICE_ACCOUNT_EMAIL='foo@bar.iam.gserviceaccount.com' # サービスアカウントのア
2022年現在、CSSでテキストに蛍光ペン風の下線を引く方法をググるとだいたいlinear-gradientを使った記事がヒットします。しかし、いまどきはlinear-gradientを使わなくてもtext-decorationで同じような表現ができるので紹介しておきます。 結論: こういうCSSをあてる /* セレクタ名はてきとう */ .highlight { text-decoration: underline; /* 下線 */ text-decoration-thickness: 0.5em; /* 線の太さ */ text-decoration-color: rgba(255, 228, 0, 0.4); /* 線の色 */ text-underline-offset: -0.2em; /* 線の位置。テキストに重なるようにやや上部にする */ text-decoration-
ローカルにNode.jsがインストールされていれば、npxコマンドを使ってすぐに画像の最適化ができます。 例えばexample.pngをWebPに変換したいときは以下のコマンドを実行します。 npx @squoosh/cli --webp auto example.png # ✅ Squoosh results: # example.png: 24.85KB # └ example.webp → 8.74KB (35.2%)
メインコンテンツの高さが足りなくてもフッターが中途半端な位置に来ないようにしたい Webアプリケーションのレイアウトで、①ヘッダー②メインコンテンツ③フッターの3つで構成するというパターンはよくあると思うんですが、 👇 こんな感じでフッターの下に中途半端な隙間を作りたくないですよね。 これは困る 👇 メインコンテンツの高さが短くても、フッターがぴったりビューポートの下にくっつくようにしたいですよね。 良いね 👇 ただ、フッターが常に下に固定されているのではなくて、メインコンテンツがビューポートより高くなったときには、フッターは下にずれていってほしいんですよね。 良いね gridを使うと簡単 自分はこれをずっとflexで実現していたのですが、(メインコンテンツの)孫要素の高さを100%にしたいときなんかに色々ややこしくて、gridを使うのがいちばん楽だなーという結論に至りました。gri
以前、Webページでスクロール位置に応じて要素のスタイルを変えたいようなケースがありました。 上の例では、最初は60pxですが、現在の位置より上にスクロールされると少しずつサイズが小さくなり、ビューポート上部に達したときに20pxになるように実装されています。 これをReactで雑に実装したので備忘録として残しておきます。 1. 要素の位置を取得するカスタムフックを作る まずビューポート内の要素の位置を取得する必要があります。複数の要素に対して同じことをやりたくなったときのために、要素の位置を取得する処理はカスタムフックに切り出しておきます。 import React, { useEffect, useState, useCallback } from "react"; export function useOffsetTop(ref?: React.RefObject<HTMLEleme
ググってもあまり日本語の記事がヒットしないので簡単に説明を載せておきます。まれにpackage.jsonでoptionalDependenciesというものにパッケージ名が指定されていることがあります。 "dependencies": { ... }, "devDependencies": { ... } "optionalDependencies": { "sharp": "0.26.3" } optionalDependenciesとは optionalDependenciesは利用可能であればインストールされるが、利用不可であっても他の処理を止めたくない場合に使用します。 以下npm公式ドキュメントの引用です。 If a dependency can be used, but you would like npm to proceed if it cannot be found or
M1 MacのNode.jsで FATAL ERROR: wasm code commit Allocation failed - process out of memory が出る場合の対処法 <--- Last few GCs ---> [85561:0x128008000] 3569 ms: Scavenge 167.1 (187.8) -> 157.3 (189.3) MB, 6.9 / 0.0 ms (average mu = 0.975, current mu = 0.953) task [85561:0x128008000] 3606 ms: Mark-sweep 157.5 (189.3) -> 137.5 (190.0) MB, 5.6 / 0.0 ms (+ 28.2 ms in 439 steps since start of marking, biggest ste
Google Cloud大好きなんですけどね、Cloud CDNだけ辛いんです。何が辛いかってキャッシュのパージ(無効化)が辛いんです。 パージのリクエストが1分間に1回しかできない 無効化の頻度には制限があります。1 分間に実行��きる無効化は 1 回だけです。ただし、無効化する対象のサイズに制限はありません。/images/fred.png の無効化は 1 回と計算されます。/images/*の無効化も 1 回と計算されます。 キャッシュ無効化の制限事項 動的なページをキャッシュしておき、データが更新されたらキャッシュを自動パージするみたいなことは現実的ではありません。 パスを指定するときのワイルドカードの制限がキツイ *は、/に続く最後の文字として使用できますが、それ以外の場所では使用できません。 キャッシュ無効化のパスパターン つまり/posts/*とすることで/posts/から始ま
iOSでwindow.innerHeightがキーボードの高さを考慮してくれない(キーボードの表示有無に関わらず同じ値を返す)のでちょっと困っていたんですが、 iOS13からvisualViewport.heightを使うことでキーボードを除いた高さを取得できるようになったんですね。 👇 このツイートの動画がわかりやすい。 AndroidでもiOSと同じようにキーボードを除いた高さを返してくれるっぽい。 visualViewportのブラウザ対応 モダンブラウザはすべて対応してる。IEは未対応。
2022/12/04 追記 RemixをCloudflare Pagesで動かせるようになりました。 詳しくは Deploy a Remix siteをチェックするのがおすすめです。 前回の記事 この記事ではRemixをCloudflare Workersにデプロイしつつ、Workers KVで外部APIから取得したデータをキャッシュしてみたいと思います。 Remixをローカルで開発
Next.jsの対抗馬となりそうなReactのフレームワークでRemixのv1.0がリリースされました。 個人的にRemixでいちばん魅力を感じているのはCloudflare WorkersでSSRができるという点です(現状ではNext.jsをCloudflare Workers上でSSRするのは難しい)。これがなぜ嬉しいのかと言うと、パフォーマンスを出しつつ、低コストで運用でき、大量のアクセスに対しても低コストでスケールできそうだからです。 そもそもSSRをする必要ある? ほとんどのWebサービスはSSRなしでSPAとしてビルドし、Cloudflare PagesやGitHub Pagesに静的ファイルをのせて動かせば十分だと思います。 例えば僕が先日作った個人開発のサービスもReact on Cloudflare Pagesの完全なSPAですが、SSRが必要な要素はまったくありません。
Cloudflare WorkersでNode.jsを動かすためのあれこれをスクラップに残していたのですが、ハマったポイントが多かったのでこちらに整理しておきます。 今回やろうとしたのは、Zennのマークダウン→HTML変換のAPIをCloudflare Workersで動かすというものです。試行錯誤の末に断念したのですが、以下でその理由をまとめておきます。 CPUやメモリ、ファイルサイズなどの制限が厳しめ 2023/07/25時点でのCloudflare Workersの制限一覧がこちら。 Limits - Cloudflare Workers CDNのエッジで動くので、パフォーマンスが良いぶん制限が厳しめです。 メモリ上限は128MB サイズ上限は無料プランだと圧縮後1MBまで 有料プランだと10MBの上限となるが、できるかぎり1MB以内に抑えたい(参考:Server Side Jav
Talewind CSSでローディング・アニメーションを表示したくなったのですが、ググってもちょうど良いサンプルが見つかりませんでした。 というわけでコピペで簡単に使えるサンプルコードをいくつか考えてみました。あまりクオリティが高いものではないですが「Tailwind CSSでとりあえず何かローディング中っぽい表示にしたい」という場合にご自由にコピペしてお使いください。 波紋が広がるアニメーション <div className="flex justify-center" aria-label="読み込み中"> <div className="animate-ping h-4 w-4 bg-blue-600 rounded-full"></div> </div> アレンジ Reactでない場合はclassNameをclassに置き換えてください(もしくはCodePenのコードをコピペ) bg
Zennで現状CloudFunctionsにデプロイしている一部のAPIを可能ならCloudflare Workersに移行してみたい。 CloudFunctionsでも問題なく動いているが コールドスタートの遅さを解消したい Cloud Functionsよりパフォーマンスが良さそう (おそらく)料金的にも安くなる などがCloudflare Workersへ移行するモチベーションになっている。
なんのキーを押してしまっているのかさえ分からないのだが、ときどきMacbookPro / MacbookAirでキーボードをうっているときにMusicアプリが勝手に立ち上がるときがある。 僕はYouTube Musicしか使わないのでMusicアプリごと削除したいのだが、それはできないらしい。仕方がないので、Musicアプリの自動起動だけを止めることにした。 ググってヒットしたAppleのフォーラムで紹介されていたコマンドで自動起動を止めることができた(1ヶ月くらい自動起動されていないので多分うまくいってる)。 具体的にはターミナルを開いて、以下のコマンドを実行した。
Next.jsでv12〜middlewareという機能が使えるようになりました。 middlewareに書いた処理はリクエストが完了する前に実行されます。Cookieの値に応じて��ーティングを振り分けたり、Basic認証を導入したり等など、幅広い用途で使えそうです。 VercelとNext.jsの組み合わせが強いのは、VercelにNext.jsをデプロイするとこのmiddleware部分をEdge Functionsで捌いてくれるという点です。つまり、静的なページに対するリクエストに対して、オリジンサーバーに触れことなくmiddlewareを実行できるということです。 Vercel以外のプラットフォームだとどうなのか ドキュメントには以下のような記載があります。 This works out of the box using next start, as well as on Edge
Zennではこれまで画像のリサイズやサムネイル生成の仕組みをImageMagickを使って自前で用意していた。以下の理由から、これからはすべてCloudinaryに頼ることにした。 セキュリティ: imagetragick、Deserialization on Railsなどが参考になる パフォーマンス: Cloudinaryなら配信する画像のフォーマットをUser-Agentに応じて最適化してくれる 利便性: アップロード時に複数のサイズの画像を生成しても、クライアントで表示するときに別のサイズが欲しくなったりする。このときバックエンドでリサイズの処理をかけ直すのは辛い Cloudinaryなら画像の最適化からリサイズ、合成までSDKを使って簡単に実現できる。 料金面でいうとCloudflare Imagesの方が安いかも?今後コストを抑えたくなったときには移行を検討するかもしれない。
【まとめ】Next.jsのrewritesは気軽に使わない方が良いかも 一つでもrewrites設定が書かれているとクライアントサイド含め色々な処理が発生する rewrites設定が一つでも書かれていると、rewritesのパターンにマッチしないページであっても再レンダリングが発生することがある JSのバンドルサイズが大きくなる可能性あり(next@v11.0.2 でrewriteをひとつ記述しnext buildしたところmain.jsが約4KB増えた)
次のページ
このページを最初にブックマークしてみませんか?
『catnoseさんの記事一覧』の新着エントリーを見る
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く