shimotsu tech

仕事をしていて学んだこと、気づいたことなどを書いていきます。主にJavaScript。

Next.js でクライアントから環境変数が読み込めない

Next.js で今個人的に作っているアプリケーションにおいて、クライアント(ブラウザ)から環境変数(.env.*)が読めないという事象に遭遇したので、その原因と解決法をメモしておきます。

やりたいことは、ページコンポーネント上で、アクセス時に毎回 Firebase の匿名認証を実行するというもの。

useEffect(() => {
    // 匿名ログイン実行
    async function initFirebase() {
      firebase.auth().onAuthStateChanged(async (user) => {
        if (!user) {
          await firebase.auth().signInAnonymously()
        } else {
          console.log(user)
        }
      })
    }

    initFirebase()
  }, [])

この実行時に "auth/invalid-api-key" というエラーが出てしまいました。

ずばり原因としては、.env ファイルで設定した環境変数に問題があり、Firebase の 設定用ファイルにおいて、それを正しく読み込めていませんでした。

本来、Next.js でブラウザから環境変数を呼ぶ際は、以下のように 'NEXT_PUBLIC_****' と命名しなければいけないのですが、

NEXT_PUBLIC_FIREBASE_PUBLIC_API_KEY=xxxxxxx
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=xxxxxxx
NEXT_PUBLIC_FIREBASE_PROJECT_ID=xxxxxxx
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=xxxxxxx
NEXT_PUBLIC_FIREBASE_APP_ID=xxxxxxx

以下のようにしてしまっておりました。

FIREBASE_PUBLIC_API_KEY=xxxxxxx
FIREBASE_AUTH_DOMAIN=xxxxxxx
FIREBASE_PROJECT_ID=xxxxxxx
FIREBASE_MESSAGING_SENDER_ID=xxxxxxx
FIREBASE_APP_ID=xxxxxxx

上記のように環境変数名を変更すると、無事読み込むことができました。めでたしめでたし。

Stripe で 開発者用モード(テストモード)に切り替えたい

【前提】Stripe のビジネスアカウントを持っていることが前提です。

Stripe で開発者用モード(テストモード)に切り替えるには、ダッシュボード画面の左カラムにある「テストデータの表示中」のトグルをオンにすればOK。

f:id:zuboriradio:20210607113744j:plain

また、「開発者 > APIキー」のタブをクリックしてページ遷移すると、「公開可能キー」と「シークレットキー」が表示されるので、トークンはこちらを利用すれば、そのままテストモードのリクエストが可能となる。

f:id:zuboriradio:20210607113735j:plain

パフォーマンスをモニタリングする「stats.js」を使う

CanvasPixi.js)でアニメーションを描画しているページにおいて、パフォーマンスをモニタリングしたくなったので「stats.js」を使ってみました。

「stats.js」とはFPSレンダリングにかかった時間、使用メモリをリアルタイムで表示してくれるパフォーマンスモニタのライブラリです。
github.com

僕自身使ったことはないのですが、WebGLを使ったブラウザゲームなど重い処理が必要な開発においてよく見る気がします。公開されたのは2010年頃のようですが、パフォーマンスモニタのツールとしてはほぼデファクトスタンダードのポジションを獲得しているんじゃないでしょうか(想像)。

使い方

使い方はとてもシンプル。
まず、パッケージをインストールします。

npm install stats.js

使いたいコンポーネント、ページで読み込み、あとは初期化処理をすればOK。 `stats.showPanel(0)` で、表示モードを指定できます。今回はFPSが見たかったので `0` に設定。今回の例はNuxtでの使用例です。

import Stats from 'stats.js'

mounted() {
    this.setStats()
  },
  methods: {
    setStats() {
      const stats = new Stats()
      stats.showPanel(0) // 0: fps, 1: ms, 2: mb, 3+: custom
      document.body.appendChild(stats.dom)
      stats.domElement.style.position = 'absolute'
      stats.domElement.style.top = '0px'
      stats.domElement.style.left = '0px'

      function animate() {
        stats.begin()
        // monitored code goes here
        stats.end()
        requestAnimationFrame(animate)
      }
      requestAnimationFrame(animate)
    }
  }

ブラウザで確認すると、ちゃんと指定通り表示されました。めでたし。

f:id:zuboriradio:20191210184104j:plain
画面は見せられないのでアップで。

【Nuxt】new PIXI.Container()で生成した要素の位置を動的に変える

PIXI.Container()で生成した要素の位置を動的に変えるときの方法です。

API自体はこちらに用意されていて、基本はそこにアクセスして値を書き換えれば大丈夫かと思います。
位置を制御するため、x,yの値にアクセスすることができます。

PixiJS API Documentation

// コンテナを生成
const sampleContainer = new PIXI.Container()

// コンテナを生成
sampleContainer.y = 0 (任意の値)

これを、new PIXI.Application() で生成したcanvasに追加することで表示されるかと思います。

要素の位置を動的に変える

ボタンをクリックしたら、上記で生成したコンテナの位置を変更する場合を考えてみます。

methodでボタンのクリックイベントを設定し、それに応じてsampleContainerの値を書き換えます。

<button v-on:click="UpDown(50)">+</button>

で、このときコンポーネントのscript内で定義されたmethodから、別で生成されたcanvasの値を直接参照できないので、コンテナ生成時にいったんdataに格納しておくとよさそうです。

data() {
    return {
      sampleCanvas: null
    }
  }

このあと、コンテナ生成時にそれをdataに格納します。

      // コンテナを生成
      const sampleContainer = new PIXI.Container()
      // dataに格納
      thiss.sampleCanvas = sampleContainer

すると、methodからdataを参照すればいいので、動的に値を書き換えることができるようになります。

methods: {
 UpDown(value) {
      // 位置を調整する
      this.PosY += value

      // 再設定
      this.sampleCanvas.y = this.PosY
 }
}

【Nuxt】Pixi.jsで画像を読み込む際の注意点

NuxtでPixi.jsを使った2Dアニメーションの描画をする際に、アセットの読み込みで詰まったのでメモ。

PixiのPIXI.mesh.Ropeというメソッドで複数のポイントを持つテクスチャを描画したい場面があり、components内で以下のように変数stripeを定義していました。

  // <script>内での定義
  const strip = new PIXI.mesh.Rope(PIXI.Texture.fromImage('/assets/img/img.png'), points)

これで、img.pngからテクスチャが生成されるかと思いきや、うまく読み込まれず…。開発者ツールからNetworkを見ても、404になってるし、Content Typeが謎に`GIF`になってるし、なんかおかしい。

解決策: 画像アセットはimportして使う

結論、画像をimportして使うことで無事読み込まれるようになりました。

  import Image from '~/assets/img/img.png'

  // <script>内での定義
  const strip = new PIXI.mesh.Rope(PIXI.Texture.fromImage(Image), points)

こういう読み込ませ方はPixi.jsを使う場合以外でもやると思いますが、Pixi.jsにおいてインスタンスを生成する際にアセットを渡すときはimportしておいたほうがいいかもしれません。

NetlifyでデプロイしたサイトのAuth0のソーシャルログインが動かない

今月からアサインされるプロジェクトでAuth0を使った認証を使う感じになりそうだったので事前に試してみたのですが、ちょっとつまずいたところがあったのでメモ。

以下の記事を参照にNuxtのSPAでAuth0を導入してみました。

steady.daas.co.jp

▼ 動いてるやつ

f:id:zuboriradio:20191201125749g:plain

NuxtではAuth Moduleを使えばAuth0によるソーシャルログインが超あっさりと実装できるんですね。よく見るログイン画面が現れ、指示通りにログイン処理を行うと、用意しておいたプロフィールページで自分の情報が表示されたのでちょっと感動しました。

Netlifyにデプロイすると動かない

Auth0のデフォルトではGoogleアカウントによる認証が用意されているのですが、その他にもFacebookやLINEのアカウントによる認証を試してみたいと思い、ひとまずローカルではなくWebにアップしようと思い、いつもとおりNetlifyでデプロイしてみました。

すると、動かない……。うーん、なんでだろ。
本来、このcallbackがちらっと表示されて、その後スムースにプロフィールが表示されるページへ遷移するはずなのですが、callbackの時点で止まってしまう。

f:id:zuboriradio:20191201130312g:plain

開発者ツールを見てもJWTを付与したリクエストは問題なく行われてるっぽい。

f:id:zuboriradio:20191201130656j:plain

結論:NetlifyではJWTの利用は有料

原因が特定できず1時間くらい唸っていたのですが、結論をいうとNetlifyではJWTを使った認証は有料プランしか使えないとのこと。

Netlifyの管理画面 > Settings > Access control で確認できます。
f:id:zuboriradio:20191201131116j:plain

たぶんここでAuth0で入手できるClient Secretを入力すればいいんだと思います。

終了。おつかれさまでした。

Retina対応しても画像がぼやけるときの対処法

結構悩んだのですがどこにも解決策がなかったので書いておきます。

一般的にRetina対応をする際、psdなどから画像を切り出す際、表示させるサイズの2倍で書き出し、1/2のサイズで表示させることが多いかと思います。

参考:
Retina対応がイマイチ分からない人向けの簡単ガイド【初心者Webデザイナー向け】|34さん|note

それでたいていの場合、Retinaディスプレイで確認しても画像がぼやけて表示されることはなくなるのですが、同様に対処しても画像がぼやけてしまうケースがありました。

2倍のサイズで書き出してもぼやけてしまうケース

そのpsdの横幅サイズは1280pxで、そのままのサイズでマークアップし画像を書き出していたのですが、よくよく突き詰めるとこのサイズが原因になってるようでした。

つまり、そもそもpsdで作っているサイズが小さいため、いくら画像を大きく切り出しても解像度は荒いまま……、ということみたいなのです。psdはラスターイメージなので、そもそも制作されているデータのサイズが影響するということなのかもしれません(勝手な解釈)。

参考:
ラスターイメージ(Photoshop)ベクターイメージ(Illustrator)と変換方法 | イラレ屋


結局、psd自体を200%の大きさで作ってもらい(カンバスサイズを200%の大きさにする)、一般的な対応と同様に画像を書き出すと無事くっきり表示されました。

まとめ

このケースは初めてだったのでどう対処すればいいのか悩みましたが、もとのpsdを大きくしてみるというシンプルな対応で解決されました。

もし、Retina対応しても画像がぼやけてしまうという場合は、一度psd自体のカンバスサイズを大きくしてみて試してみるといいかもしれません。