ふんばりフロントエンジニアのブログ

新米フロントエンジニアの備忘録です。ふんばり温泉タオル欲しい...

ReactNative + Expoでプッシュ通知が来ない!なぜだ!!

ただの戒めです。

サイレントマナーモード切りましょう。

最近ReactNativeを触っているのですが、とりあえずアプリなのでプッシュ通知試してみようということで、下記の記事など参考に実装してみたわけです。

qiita.com

で、デバッガーで見る限りリクエスト自体は成功しているようでした。

しかし、なぜかプッシュ通知のポップアップが表示されない...

基本的にサイレントマナーモードにしているので、そもそものスマホの仕様すら忘れていたという浅はかな原因でした...

二時間くらい費やしてしまった...

cssが重複?!scssの@importの挙動に注意しよう

久々に2年前くらいの自分のコードを改修してます。

フロントもバックエンドも両方、目も当てられない箇所が多々あったので、自分に対して「クソが...」と呟いてしまうこともありました。

ただ、逆に成長したんだなあとも感じました。

さて、タイトルの件ですがかなりのやらかしポイントで、scssの@importで変数定義のファイルなどを各ファイルの冒頭で読み込んでいた、というのが結論になります。

common.scssという変数定義や共通コンポーネントをまとめたscssファイルがあったとして、下記のような感じです。

  • _top.scss
@import "common";

// topページのスタイリング
  • _map.scss
@import "common";

// mapページのスタイリング


なぜこんなことをしたのか...自分でも謎ですが...(IDEの自動補完を当てにしたのかな??)

もちろん、このような記述をすると各ファイルに共通ファイルの記述が取り込まれるので、同じcssが重複して記述されることになります。
ファイルサイズがとんでもないことになっちゃってました。

style.cssなどの、ビルド用のファイルにだけ@importを記述して取り込めば問題ありません。順番は共通ファイルを先にするよう気をつけましょう。

  • style.scss
@import "variables";
@import "common";
@import "map";
@import "top";

ただ、style.scssの「@importがめちゃくちゃ多くて見通しが悪い」ということでしたら、パーツごとにscssファイルを切り分けて、各パーツのラッパーのscssに@importを記述してもいいと思います。
例えば、mapのパーツがめちゃくちゃ肥大化した場合。

map/
_map.scss
_map_layout.scss
_map_content.scss
_map_variables.scss

  • map.scss
@import "map_layout";
@import "map_content";
@import "map_variables";

このようにして、style.scssでmap.scssを読み込む的な。

そこまで必要になることないかもですが...

laravelからGoogleCloudStorageにno-cacheでオブジェクトを保存する【laravel-google-cloud-storage】

まず、laravel-google-cloud-storageを使う前提です。

filesystemにGoogleCloudStorageのプロバイダを追加する形で実装しています。
下記の記事がとてもわかりやすかったです。
qiita.com


で、タイトルの件ですが調べても公式に記載がなかったのですがissueから次の一文を見つけました。

github.com

metadataをkeyで渡せばいける、とのこと。

で、下記のように書きます。

$disk = \Storage::disk('gcs');
$thumb_path = "shops/$request->phone/thumb/thumb.$ext";
$disk->put($thumb_path, (string) $thumbResized->encode(), ['metadata' => ['cacheControl' => 'no-cache']]);

まんま第3引数にmetadataをkeyとした連想配列を渡す感じです。

これでno-cacheでオブジェクトを保存できました。以上です。

サブネットの重複?範囲内にしろ?VPCのサブネットの切り方についての備忘録

今回はAWSの中でもなんかとっつきにくいVPCの話です。

私もネットワーク系弱いので、結構しんどいのですがなんだかんだ理解できたようなので備忘録として残します。

VPCとかサブネットとかそもそも意味がわからん、という方は下記の記事がとてもよく理解できると思います。
avinton.com


では、サブネットの切り方について。
まず、VPCのネットワークアドレスを設定してみましょう。

10.0.0.0/16

サブネットの計算はhttps://note.cman.jp/network/subnetmask.cgiが便利です。

このように設定すると、

ネットワークアドレス: 10.0.0.0
ホストアドレス: 10.0.0.1~10.0.255.254

となります。
ホストアドレスというのは実際に割り当てることのできるIPアドレスのことを指します。

さて、肝心のサブネットは次の二つの要件を満たす必要があります。

1. VPCのホストアドレス範囲内であること(10.0.0.1~10.0.255.254)
2. サブネット同士でホストアドレス範囲が重複しないこと

では、早速1を満たすためにサブネットを設定してみましょう。

// サブネットA
10.0.0.0/16

ホストアドレスは「10.0.0.1~10.0.255.254」となります。
当然、VPCのホストアドレスと同じ範囲なので作成自体は成功します。(わかる方はもうアカンとわかる)
では、もう一つサブネットを作成する場合はどうなるか...

// サブネットB
10.0.1.0/24

ホストアドレスは「10.0.1.1~10.0.1.254」となります。
そして、ここで作成は失敗します。
なぜなら、2の条件である「サブネット同士でIPアドレス範囲が重複しないこと」という条件を満たしていないため。
上記を見比べてみるとわかるのですが、サブネットBの範囲ってサブネットAの範囲に含まれちゃっていますよね。

上記の失敗原因は、まず「最初の段階でVPC内の利用可能なホストアドレスを全て占有してしまっている」ことが原因です。
なので、サブネットは重複しないようにあらかじめある程度のゆとりを持たせることが大事だと思います。

上記を踏まえて、サブネットを作成する場合は、下記のようにすると1,2の条件を満たすことができます。

//サブネットA
10.0.1.0/24
→ 10.0.1.1~10.0.1.254
//サブネットB
10.0.2.0/24
→ 10.0.2.1~10.0.2.254

上記のように第三オクテットを固定にすれば、検証はしてませんが最大で255個までサブネットを作成することができると思います。

なんだかイマイチ勉強しにくいネットワーク部分ですが、ともに頑張りましょう!

〜余談〜

IPアドレスとは?

構成としては、ネットワークアドレス + ホストアドレス。

192.168.1.4

上記のIPアドレスだと「192.168.1」までがネットワークアドレス、「4」がホストアドレスとなる。
つまり、「192.168.1」まで分かればどこのネットワークに属しているかがわかる。
二進数で表すと、下記のような8bitのオクテット4つで表示される。

11000000.10101000.00000001.00000000	
サブネットマスクとは

サブネットマスクとは、そのIPで、いくつのIPアドレスを発行するかを決めるもの。

192.168.1.0/24

上記のような表示を「プレフィクス表示」という。
最後の「/24」はどこから範囲を許容するかを表しており、「/24」の場合は下記となる。

192.168.1.1 〜 192.168.1.255

つまり、/24は「192.168.1」までは固定で、残り8ビット(0〜255)までの範囲を許容している。
よくIP制限をかける際に、下記のような表記を見かける。

192.168.1.1/32

これはIPアドレスの完全一致を表すことになる。(余っているビットがないので)

Basic認証とssl通信がセットで無料デプロイできる、そうHerokuならね。

というわけで今更ながらHeroku使ってみたわけです。

いつも静的サイトのテストURLとか発行する時とかはNetlifyをメインで使っていたのですが、今回はBasic認証かけとかないと怖いなーという案件だったんですね。

で、Netlifyは有料プランしかBasic認証かけられないわけです。

ということで探していたらHerokuがどうやら無料でBasic認証かけられるみたいで、使ってみました。

というわけで参考にしたのはこちらのサイト。
たったの10分!Basic認証つきの静的サイトを「Heroku」にアップしよう! | SiTest (サイテスト) ブログ


流れ的にはNetlifyとは違い、全てGUIで済ませられるというわけではないのですが、Git普通に使ったことがある人なら全然簡単な流れでした。


デフォルトでSSL化されているのも嬉しいですよね。

Geolocation APIとかSSL化されていないと動かない標準APIが結構あったりするので、その辺無料でテストデプロイできるのはとてもよいです。

これからはHeroku積極的に使っていこうと思います。

GSAPを久々に使ってみたらバージョン3になっていい感じになってた話

GSAPの記事は以前にも出していたのですが、それはバージョン3以前の話でした。

久々にアニメーション案件があったので、せっかくだからバージョン3を触ってみよう、ということで触った所感と使い方を羅列します。

まず、簡単に。

import { gsap } from 'gsap';

const animEl = document.querySelector('#anim');

gsap.from(animEl, { opacity: 0 })

<||

こちら透明度を0から1に上げるだけのアニメーションですが、書き方が簡素です。
というより、importがかなり明瞭になりました。

以前はTweenLiteなのかTweenMaxなのか、それともTimeLineMaxなのかインポートを明記しないといけない(しかもなぜか読み込みエラー起きたり)感じだったのですが、バージョン3からは統合されて、基本的にはgsapだけをインポートすればよい仕様になっています。

今まで使っていた人からすれば逆に「こんなに記述量少なくていいの?」て感じですよね。

で、TimeLineとかも進化しておりましてこんな感じで書けるようになりました。

>|javascript|
const animsTl = gsap.timeline({
        defaults: {
            duration: 2,
            ease: "Linear.easeInOut"
        }
    })


animsTl
        .to(anim1, { opacity: 1 })
        .to(anim1, { opacity: 0 }, 5)
        .to(anim2, { opacity: 1, duration: 3 }, 5)
<||

まず、タイムラインの引数にdefaultsというオブジェクトを渡せるようになりました。
ここで指定できるのは、durationとeaseの二つなのですが、長いタイムラインを作るときにはこのdurationのデフォルト値がかなりありがたい...


上記コードの最終行で指定してますが、もちろんオーバーライドも可能で、durationを渡してあげると上書き可能です。
タイムライン作成する場合は基本的に秒数が一定なことが多いですが、メインレイヤーとかは秒数長くするとかあると思うので、これ使うとめっちゃいいです。


あと、イージングですがこれも確か以前までは別でインポートしないといけなかった気がする...

バージョン3でも別で読み込みができるらしいですが、このように文字だけで指定できるのは楽ですよね。

LaravelでPostgreSQLでもコネクションプーリングする方法

最近めっちゃLaravel使ってます。

で、Laravelのコネクションプーリングの話です。

コネクションプーリングとは、DBとの接続を永続化させること。

フレームワークによっては、これがデフォルトで永続化されているものもあるようですが、Laravelの場合はデフォルトで永続化がオフになっています。

DBとの接続の永続化、というと語弊があるかもしれないので補足しておくとPDOオブジェクトのインスタンス化時の接続をキャッシュしておく、といったほうが良いでしょうか。

これによって、毎回クエリ実行時に接続をする必要がなくなるのでオーバーヘッドが短縮され、高速化される、というわけですね。

あまり必要に感じる場面には出くわさないかもしれませんが...笑

で、Laravelでコネクションプーリングを有効にする設定が下記です。

 'pgsql' => [
            'driver' => 'pgsql',
            'url' => env('DATABASE_URL'),
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '5432'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'charset' => 'utf8',
            'prefix' => '',
            'prefix_indexes' => true,
            'schema' => 'public',
            'sslmode' => 'prefer',
            'options' => [
                PDO::ATTR_PERSISTENT => true,
            ],
        ],

デフォルトとの変更点は、optionsの部分です。

「PDO::ATTR_PERSISTENT」を追加することで、接続を永続化することができます。

mysqlの例しかなかったので、PostgreSQLではできないのかと思っていましたが、そんなことはなかったですね。

永続化できているかどうかの確認は、下記手順で確認できます。

  1. php artisan tinker
  2. DB::connection()->getPdo();

出力結果の「PERSISTENT」がtrueになっていれば永続化できています。

余談

コードを追っていただくとわかるのですが、「src/Illuminate/Database/Connectors/Connector.php」がコネクションを作成しているクラスになっています。

その中に、下記のような記述があります。

/**
     * Create a new PDO connection instance.
     *
     * @param  string  $dsn
     * @param  string  $username
     * @param  string  $password
     * @param  array  $options
     * @return \PDO
     */
    protected function createPdoConnection($dsn, $username, $password, $options)
    {
        if (class_exists(PDOConnection::class) && ! $this->isPersistentConnection($options)) {
            return new PDOConnection($dsn, $username, $password, $options);
        }

        return new PDO($dsn, $username, $password, $options);
    }

    /**
     * Determine if the connection is persistent.
     *
     * @param  array  $options
     * @return bool
     */
    protected function isPersistentConnection($options)
    {
        return isset($options[PDO::ATTR_PERSISTENT]) &&
               $options[PDO::ATTR_PERSISTENT];
    }


まあ、見ての通りなのですがoptionsのkeyにPDO::ATTR_PERSISTENTがセットされていれば、永続化されるようになっています。

公式ドキュメントには記載されていない部分ですが、同じ場面に出くわした時助けになれば嬉しいです。