Lambdaカクテル

京都在住Webエンジニアの日記です

Invite link for Scalaわいわいランド

Scala.jsで環境変数を呼び出したいときはsys.envではなくjs.Dynamicを利用する

Scala.jsをNode環境で動作させるときに環境変数を取得したかったけどうまく動かずにハマったのでメモ。

tl;dr

val env = js.Dynamic.global.process.env.asInstanceOf[js.Dictionary[String]].toMap

Scala.jsと環境変数

通常Scalaで環境変数にアクセスするにはsys.envを利用するが、もともとJavascript(ECMAScript)はブラウザ上で動作するためのスクリプトであるため、環境変数の概念がない。 Node.jsを利用すると普通に環境変数を利用できるが、これはあくまでNode.jsという言語処理系が特別にモジュールを用意してくれているというだけの話で、Node限定の話だ*1

nodejs.org

このためか、忠実にJavascriptにコードを変換するScala.jsでは、sys.envを利用しても環境変数を得られない。Node.jsを前提にしてしまうことは避けたいのだろう。

stackoverflow.com

実行環境としてNode.jsを前提にしてよいのであれば、グローバルオブジェクトを経由して以下のように環境変数をMapの形で取り出すことができる:

val env = js.Dynamic.global.process.env.asInstanceOf[js.Dictionary[String]].toMap

要するにNode.jsの機能を直接呼び出しているだけだ。

Cats Effect 3の場合

ちなみにCats Effect 3はEnvという環境変数を扱うための組込みのモジュールを提供している。

typelevel.org

こちらは実行環境ごとに正しく環境変数を取得するためのコードが仕込まれていて、Scala.jsでも正しく動作する:

//> using scala 3.3.3
//> using dep "org.typelevel::cats-effect::3.5.4"

import cats.effect.IO
import cats.effect.std.Env

object App extends cats.effect.IOApp.Simple {
  def run: IO[Unit] = for {
    e <- Env[IO].get("HOME")
    _ <- IO.println(e)
  } yield ()
}

github.com

最初からCats Effectを使うのであればこれを使うのがよいだろう。

*1:といってもBunなどでは同じAPIで環境変数を取得できるようになっている

★記事をRTしてもらえると喜びます
Webアプリケーション開発関連の記事を投稿しています.読者になってみませんか?