To start with let's understand the necessary project structuring first.
We will need two different projects, for Scala.js (root/js/src/main/scala) and Scala JVM (root/jvm/src/main/scala), respectively, and a folder (root/shared/src/main/scala) that would maitain the code shared amongst these two ecosystems.
We then use the
Notice how settings common to both the ecosystems go under
settings builder method. This may include dependencies that are common to both the ecosystems. However, when defining common dependencies you must use
%%% instead of
%%. This allows sbt to automatically determine which ecosystem you are in, at compile time. Another thing to keep in mind when using
crossProject is to not include
enablePlugins(ScalaJSPlugin) in your
Shared Parser Library
Having layed out our basic project structure, let's now move our parser code we wrote in the last post to the shared folder. We will define our parser in
Parser.scala like so:
index-dev.html under root directory with a bootstrap container carrying our application's basic structure:
This would result into something like this:
The two main components to make note of here are "Editor" and "Result". Editor is a component where user can type strings from the language of our simple arithmetic expressions and results is a component where the validation success or failure results from the parser are displayed.
Now we have to implement our scala.js code that would essentially accept user input from the editor component, make use of the shared parser library to validate the user input and display the results in the result component. For this purpose we will create a
Validator.scala file that will house all this logic, like so:
There are couple of things to notice here:
- In order to make use of the shared parser code, all we need to do is to import it (at line: 1) and use it (line: 15) like so,
parser: P[_] => P[Any] = expr(_). Here we have defined
expras the default parser as an argument to the
- In our
build.sbt, we defined fastparse as a common dependency which is why we are able to make use of it here in our scala.js code
- To access dom elements, we can make use of imports from
org.scalajs.dompackage. This however, requires dependency on
- In our
build.sbt, as part of js settings, we have defined
true. This allows the
mainmethod from our
Compile & Test
In order to compile our scala.js code, all we have to do is to run
fastOptJS sbt task to generate executable js suitable for development environment and
fullOptJS sbt task suitable for the production environment:
The difference between the two executables is in the amount of optimization and the overall file size. This clearly is evident in the amount to time taken to generate either of the files.
Another thing to notice here is that the files are generated under
simple-arithmetic-parser-opt.js for developement and production environments, respectively.
Now since we have already included the generated js file in our html code, in order to test our application, all we have to do is to visit our
index-dev.html in chrome. You can try the working application here. If you were to deploy the application in production, you may probably want to create a similar