Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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に置いて使う。

https://github.com/eiel-sample-code/scalajs-use-cjs/tree/master/node_modules

設定

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

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

https://github.com/eiel-sample-code/scalajs-use-cjs/blob/master/build.sbt#L12

補足

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

https://github.com/scala-js/scala-js/blob/v0.6.26/tools/shared/src/main/scala/org/scalajs/core/tools/linker/backend/ModuleKind.scala#L18-L54

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/eiel-sample-code/scalajs-use-cjs/blob/master/src/main/scala/Main.scala#L11-L21

補足

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")
}

https://github.com/eiel-sample-code/scalajs-use-cjs/blob/master/src/main/scala/Main.scala#L4-L7

結果

$ 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")

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした