Chromeデベロッパツール js、tsデバッグのちょっと便利な使い方

Chromeの開発者ツール、Web系の開発をしている方なら一度は触ったことがあると思います。

今回は、普通の使い方はもう知ってるよという人向けに、私が個人的に気に入っててちょっと便利な使い方を書いておきます。

①ブレークポイントを一時的に無効にする

サンプルスクリプトは下記です。

    const dog = {name: 'dog', age: 0}
    const monkey = {name: 'monkey', age: 1}
    const cat = {name: 'cat', age: 5}
    const animals = [dog, monkey, cat]
    animals.forEach(animal => {
      if(animal.name === 'monkey') {
        console.log('ウキー')
      }
    })

例えば、下記のような場所にブレークポイントを置いたとして

リロードのたびに実行されるのがなんかイヤだな…ってことがあると思います。

そういう時は、右クリックすると、次のようなメニューが出ますので

Disable breakpoint を選択すると、Enableにするまでこのブレークポイントで止まりません。

私は結構これを使います。

なんで使うかっていうと、ページのリロードって弊社では例えばVue使ってるんですが、コードの更新ごとにリロード走って結構頻繁に起こるんですよね。そのたびにブレークポイントで止まってるとかが面倒だからです。

あとは普通にループの中で、ループの1回目はブレークしたいけど、後はもういいよ…という場合などに使います。

「ブレークポイント自体もう一度クリックしたら消えるじゃん」

という声も聞こえますが、そうすると、またコード直して同じところにブレークポイントを付けたい、という場合にちょっと手間が発生します。

ちょっとの手間、惜しんでいきましょう!!

②ブレークポイントに条件を設定する

ループの中の例えばループの10回目以降だけ発言する不具合がある、などの場合にポチポチステップ実行を押していませんか?

ブレークポイントに条件を設定することができます。

ブレークしたい場所を右クリックしてください。

「Add conditional breacpoint」を選択します。

animal の age が 2より大きい時だけブレークするように設定します。

黄色いクエスチョンマークのブレークポイントができたらOKです。

これで、age > 2のcat の場合のみブレークするようになります。

③すべてのブレークポイントを一時的に無効にする

①で紹介したブレークポイントを一時的に無効にする、ですが、多くのブレークポイントがある場合に、いちいちDisableにしていくのは面倒だと思います。

そんな時に、一度に無効にできる方法があります。

下記の開発者ツールの右のほうにある電池のようなマークをクリックしてください。そうすると、ブレークポイントが一気に一時的に無効にできます。

また一気に有効にしたい場合は、同じマークをクリックすると、一気に有効になります。

後は、便利な使い方がもっとあると思いますが、公式サイトにも情報がいっぱいあるので、ぜひ見てみてください。

ブレークポイントでコードを一時停止する

TypeScript IDEの型推論がまだ適当なのかもしれない

最近TypeScriptを触り始めた私です。

ちょっとわかりづらかったことがあったのでメモ的に書いておきます。

私はIDEはPHPStormを使っていて、バージョンはPhpStorm 2023.2.4です。
PHPStormで設定しているTypeScriptのバージョンは5.1.3です。
Nodeのtscのバージョンは5.0.4です。

さてさて、次のようなTypeScriptがあるときに

    class Person {
      constructor(public name: string, public ramen?:string) { }
      talk() {
        console.log('最近どうですか?')
      }
      setRamen(ramen: string) : Person{
        this.ramen = ramen
        return this
      }
      build():Person {
        return this
      }
    }

    class Kyushujin extends Person {
      talk() {
        console.log('最近はなんばしよっとね?')
      }
      build():Kyushujin {
        return this
      }
    }

    const kyushujin =  new Kyushujin('太郎')
        .setRamen('とんこつ')
        .build()

    if(kyushujin instanceof Kyushujin) {
      console.log('九州人です')
    }

    kyushujin.talk()

実行結果は下記の通りです。

ちゃんとインスタンスkyusyujinは”Kyushujin”として認識されていますが、new Kyushujin の部分でIDEがしてくれる型推論は 下記のスクショのようにスーパータイプのPersonなんですよね。

PHPStormのスクショ① const kyushujin:Personとなっている

エッ ってなりましたね。TypeはKyushujinとして表示されるべきだと思ったからです。

これ、setRamen() で 戻り値の型が Personになってるからみたいで setRamen()をコメントアウトすると、Kyushujinとして推論してくれます。

PHPStormのスクショ② const kyushujin:Kyushujin となっている

実行結果は上記と一緒です。

一瞬、あれ?サブタイプにちゃんとなってないじゃん!って思って焦りました。

あんまりまだわかってないことが多いので、まだまだ勉強中です。(´ω`)

ちなみに余談で、弊社ではGithub Copilot 使ってますが、下記までタイプしたところで

    const kyushujin =  new Kyushujin('太郎')
        .setRamen(
 .setRamen('とんこつ')

って勝手にコパイロットくんが入れてくれたんですよ!!!

すごくないですか???Σ(゚Д゚)スゲェ!!

九州人のラーメンは ‘とんこつ’ を set する

を生成できるところまで来てるんですね。(`・ω・´)

【PHP】S3に置いているファイルを署名付きURLを発行してダウンロードする

S3にあるオブジェクトURLを直接叩くと「Access Denied」と表示される場合があります。
それはそのオブジェクトのアクセス権限の全員(パブリックアクセス)の部分に適切な許可がないためになります。
誰がいつ見てもいいファイルとかならここの権限をちょちょいと変更してパブリックアクセスに変更することもある思うのですが、そうしたくない場合も多いと思います。

そういうときのために、「署名付きURLを発行してそのURLが発行から有効な時間範囲内であれば見れるようにする」ということを行います。
URLの有効期限があって「なんとか日以降は見れなくなります。」みたいな文言ってよくありますよね。
あれです。

PHP SDK を利用しています。

まずは公式を参考に

公式ドキュメント

ほぼコピペでいけました。
署名だの有効期限だの難しそうなことが簡単で嬉しいです。

$s3Client = new Aws\S3\S3Client([
    'credentials' => [
        'key' => [アクセスキー],
        'secret' => [シークレットアクセスキー]
    ],
    'region' => 'ap-northeast-1',
    'version' => 'latest'
]);

$cmd = $s3Client->getCommand('GetObject', [
    'Bucket' => [バケット名],
    'Key' => [バケット名以降のパス],
]);

$request = $s3Client->createPresignedRequest($cmd, '+20 minutes'); // 20分間有効

こちらでリクエストにアクセスしたら確認が出来ました。
ただし、今回はアクセス時にPCにダウンロードしてほしかったので、コマンドにメタデータをセットします。

メタデータのセット

新しいファイル名を指定してセットします。

$new_filename = urlencode('ほげほげ.pdf'); // ほげほげ.pdfとしてダウンロードされます

$cmd = $s3client->getCommand('GetObject', [
    'Bucket' => [バケット名],
    'Key' => [バケット名以降のパス],
    'ResponseContentDisposition' => "attachment; filename=\"{$new_filename}\""
]);

無事にダウンロードできました。
ブラウザは Chrome でしかやってないので他のブラウザはどうかはちょっとわからないです…。

他の方がやっているのを見たので発見できましたが、いつも見ているような日本語のページでは見つけられませんでした。

ここならありました。

PHP SDK ドキュメント

【参考サイト】

Amazon S3の署名付きURL発行の際に別名でファイルをダウンロードさせるようにする

プログラミング学習として使うChat GPT

プログラマ歴約6年になりますが、関数型プログラミングが出来る人に憧れております。
理由はなんかかっこいいからです。

しかし、残念ながら私は非関数型プログラミングしか書けません。
どう学ぶの? Haskell やってみるか?などの選択肢を頭に浮かべてはやらないという不毛な日々を過ごしていました。

そこでふと思いつきました。

ChatGPTに問題出してもらおう

これは結構、良い考えなのでは…自分天才では…
(似たようなことをやっている人調べたら、たくさん居ました。みんな天才でした)

実際にやってみました。

いいですね…。一発目で初心者にちょうど良さそうな問題を出してくれました。
自分なりに書いてみました。

// numbers が与えられた配列
const result = numbers.map(num => {if (num % 2 === 0) return num * 2; else return num}); 

書いたコードを載せると…

そして、もっといいなと思うのが他の書き方を聞いた時に答えてくれるんですよね

書籍とかだと、「こう書いているけどこの書き方はダメなのかなあ」と感じることがよくあります。
そういうことも確認できるので凄いですね。

こうやって新たな使い方を発見すると、また楽しくなります。

PHPでS3にあるファイルをSplFileObjectを使ってあれやこれやしようとすると Fatal Error

下記のようなエラーが発生しました。

① Fatal error: Uncaught RuntimeException: SplFileObject::__construct(): Unable to find the wrapper

② Fatal error: Uncaught RuntimeException: Cannot rewind file

なんぞこれ…って感じでしたが、対処法は公式ドキュメントに載ってましたね、有難い…。
AWSはドキュメントがしっかりしてて好きです。

公式ドキュメント

① の 対処法ですが、ドキュメントの上の方にあるように

Amazon S3 ストリームラッパーにより、組み込み PHP 関数 file_get_contents、fopen、copy、rename、unlink、mkdir、rmdir などを使用して Amazon S3 に対してデータの保存および取得ができます。使用するために Amazon S3 ストリームラッパーを登録する必要があります。


AWS SDK for PHPバージョン 3 の Amazon S3 ストリームラッパー

とあります。

なので、 $s3Client に対してこちらを追加します。

 $s3Client->registerStreamWrapper(); 

①は出なくなりました。
そしてファイル操作をしようとすると②のエラーが出ました。

こちらも同じページ書いてありました。有難い…。

「r」モードで開いたストリームは、ストリームからデータを読み取ることのみ可能です。さらに、デフォルトではシーク可能ではありません。これは、真にストリーミング方式でデータを Amazon S3 からダウンロードできるようにするためです。ここで、事前読み取りバイトをメモリにバッファする必要はありません。ストリームをシーク可能にする必要がある場合は、seekable を関数のストリームコンテキストオプションに渡すことができます。


シーク可能なストリームを開く

公式の通りにやってみましょう。
公式は fopen() 関数を例にしてサンプルを置いてくれていますが、SplFileObjectも同様です。

$context = stream_context_create(array(
        's3' => array(
            'seekable' => true
        )
    ));

$file = new SplFileObject($s3_path, 'r', false, $context);

他にもこの辺の関数も同様に使えるので file_exists() なんかを使って存在チェックなどもした方が良いかと思います。