LoginSignup
1
0

More than 5 years have passed since last update.

Scala.js で CommonJSモジュールを使う

Last updated at Posted at 2019-03-29

Scala.jsでCommonJS形式のモジュールを使ってみる。ES modulesでないのは、単に他の設定が不要でNodeJSが使えるからである。ES modulesでも大差なく使えるでしょう。

読み込みするファイルを用意

console.logを吐くだけのものを二種類用意した。

foo.js
module.exports = (obj) => console.log(obj);
bar.js
module.exports = {
  bar: (obj) => console.log(obj)
};

これらのファイルはNODE_PATH通さなくてもいいようにnode_modulesに置いて使う。

設定

sbtの設定で必要なのはscalaJSLinkerConfig.moduleKindの設定。
この設定をしておくことで、CommonJS形式でコードが出力されるので、NodeJSで実行できる。

scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) },

補足

scalaJSLinkerConfig.moduleKind
デフォルトはNoModuleESModuleも用意されている。

Facadeを用意する

Scalaから使えるようにFacadeを定義する。
平たく言うと、使おうとするjsのインターフェースをかく。

import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport

@js.native
@JSImport("foo.js", JSImport.Default)
object Foo extends js.Object {
  def apply(obj: js.Any): Unit = js.native
}
import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport

@js.native
@JSImport("bar.js", JSImport.Namespace)
object Bar extends js.Object {
  def bar(obj: js.Any): Unit = js.native
}

このobjectを利用すればrequireが生成されるJSに挿入される感じ。
@JSImportの部分が肝でここに基づいてコードが生成される。

foo.jsはdefault exportしているので、JSImport.Defaultにしている。
applyメソッドが自動的にマッピングされる模様。ソースは確認していない。
bar.jsはどちらでもよいがNamespaceにした。

補足

https://github.com/scala-js/scala-js/blob/v0.6.26/library/src/main/scala/scala/scalajs/js/annotation/JSImport.scala#L82
JSImport.Default"default"になってるだけ。

使う

object Main extends App {
  Foo("Hello, Foo")
  Bar.bar("Hello, Bar")
}

結果

$ sbt run
Hello, Foo
Hello, Bar
$ sbt fastOptJS fullOptJS
$ node target/scala-2.12/scalajs-use-cjs-fastopt.js
Hello, Foo
Hello, Bar
$ node target/scala-2.12/scalajs-use-cjs-opt.js
Hello, Foo
Hello, Bar
$ grep require target/scala-2.12/scalajs-use-cjs-fastopt.js
var $i_bar$002ejs = require("bar.js");
var $i_foo$002ejs = require("foo.js");
$ grep 002ejs target/scala-2.12/scalajs-use-cjs-fastopt.js
var $i_bar$002ejs = require("bar.js");
var $i_foo$002ejs = require("foo.js");
  $moduleDefault($i_foo$002ejs)("Hello, Foo");
  $i_bar$002ejs.bar("Hello, Bar")

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0