How to use scalajs-bundler with client only app

2019-08-05 13:49发布

问题:

In another question I was advised to use ScalaJS bundler to import NPM dependencies.

I would like to use some Javascript NPM packages in a simple client-only web application. There is an example called static which shows this. My changes to the example:

Add into build.sbt:

npmDependencies in Compile += "esprima" -> "3.1.3"

Add into Main.scala:

import Esprima._
import JsonToString._
val code = "answer = 42"
val tokens = tokenize(code)
val tokensStr = tokens.json

Change in Main.scala: "This is bold" into s"This is bold $tokensStr"

Facade (a bit simplified, for full a version see GitHub):

import scala.scalajs.js
import scala.scalajs.js.annotation.JSName

@JSName("esprima")
@js.native
object Esprima extends js.Object {

  def tokenize(input: String, config: js.Any = js.native, delegate: String => String = js.native): js.Array[js.Any] = js.native

  def parse(input: String, config: js.Any = js.native): js.Dynamic = js.native
}

When running the html generated with fastOptJS::webpack the error is:

Uncaught TypeError: Cannot read property 'tokenize' of undefined

Inspecting the static-fastopt-bundle.js shows esprima is used, but its js is not bundled.

What other steps are needed to add dependencies into a client-only web page?

回答1:

As described in this part of the documentation, you have to use @JSImport in your facade definition:

@JSImport("esprima", JSImport.Namespace)

For reference, @JSName defines a facade bound to a global name, while @JSImport defines a facade bound to a required JavaScript module.