ScalaJSBundlerPlugin sbt plugin automatically enables
ScalaJSPlugin on the project. It configures
the kind of output of the project to be
ModuleKind.CommonJSModule. Finally, it also configures its
execution environment so that npm packages are fetched (by running the
npm update command in the
project’s target directory) before the project is
It is also possible to bundle the application and its dependencies into a single .js file by using
webpack task scoped to a Scala.js stage (
webpack task returns a list of artifacts produced by the bundling process.
To define the npm packages your project depends on, use the
You can also scope dependencies to
Last but not least, the
.js files that are in your classpath and in the
jsSourceDirectories are automatically
copied to the working directory of the
node command. This means that you can also
@JSImport these modules from
your Scala facades (you can see an example
If your tests execution environment require the DOM, add the following line to your build:
ScalaJSBundlerPlugin will automatically download jsdom and bundle the tests before
their execution so that they can be loaded by jsdom.
You can find an example of project requiring the DOM for its tests here.
npm is used to fetch the dependencies but you can use Yarn by setting the
useYarn key to
If your sbt (sub-)project directory contains a
yarn.lock, it will be used. Else, a new one will be created. You should check
yarn.lock into source control.
Yarn 0.22.0+ must be available on your machine.
Each time you change something in your application source code and compile the project, Scala.js emits a new .js
file that can weigh several MBs if your application is large. Scalajs-bundler provides
a few different options with respect to handling this large output file, controlled by setting the optional
webpackBundlingMode key and can be scoped to a Scala.js stage (
webpackBundlingMode := BundlingMode.Application generates a webpack config that simply processes the Scala.js output file as an
entrypoint. This means that webpack loaders, plugins, etc will work as usual. It also means that webpack will
have to process a very large Scala.Js output file.
Turning this CommonJS module into code executable by web browsers takes time, often upwards of a minute.
Nonetheless, this is identical to what you'd get if were to duplicate your workflow outside scalajs-bundler, so it remains the default.
You can get a much faster “change source and reload application” workflow by setting the
webpackBundlingMode := BundlingMode.LibraryOnly() key. This bundling mode avoids having webpack process the entire
and any changes to the
webpack.config.js). This is accomplished by setting the webpack
output.libraryTarget keys in the webpack.config. By default, this generates a global variable named
ScalaJSBundlerLibrary, but if needed, that variable name can be overridden via the
parameter provided to
The drawback of this mode is that because the output of Scala.js is not processed by Webpack, it is still a CommonJS module that is not directly executable by web browsers. This problem is addressed by including a special “loader” before including the Scala.js module.
The inclusion of a CommonJS module in the web browser is not guaranteed to work. In particular, in
fullOptJSmode the name mangler might produce names that could clash with other existing global names. For this reason, we don’t recommend using the
LibraryOnlybundling mode in
fullOptJS, or in production.
In order to use this mode, instead of including
yourapp-bundle.js in your page, you will need to include
yourapp-library.js (which contains all the application libraries bundled into a single file),
yourapp-loader.js (which contains a hack to make the application work), and
yourapp-opt.js (which contains the output of Scala.js, that is a CommonJS module). If you're using Play
Framework, you could use a twirl template similar to this one:
The default variable global for the library is
ScalaJsBundlerDependencies. Should you need to change it,
you can provide a new variable name to the configuration, such as
webpackBundlingMode := BundlingMode.LibrariesOnly("myLib").
By avoiding processing the entire Scala.js output file, webpack times from 10's of seconds to minutes to
a couple of seconds, depending on how many dependencies webpack has to resolve. In addition, since the
module references are all still managed by webpack, any custom loaders such as the
will work as usual. Other webpack configuration such as external modules also work out of the box.
By splitting the output into a separate library and Scala.js app we are able to leverage browser caching for most reloads, since it's seldom that both .js assets and Scala.js assets change at the same time.
By avoiding any post-processing of the Scala.js output, we leave the sourcemap generated by the Scala.js compiler entirely intact. This means we avoid any translation or lookup errors introduced by webpack, and also means we save a bunch more processing time even if sourcemaps are enabled.
access to the Scala.Js compiler internals. By leveraging these, we can generate a fake
entrypoint.js file that
represents all the
@JSImports from a Scala.JS project. We can use this entrypoint to generate a library file
that provides access to all those imports without webpack having to ever process the entire Scala.js output.
entrypoint.js file we also provide a trivial
require implementation that provides access to the
modules which were imported.
All that remains is to provide an
exports variable with a reference to the
for the Scala.js out to hang onto, which is what the loader provides.
bundlingMode := BundlingMode.LibraryAndApplication() builds on
BundlingMode.LibraryOnly and attempts to
produce only one artifact (like the
Application bundling mode) without the overhead processing the entire
Scala.js output file.
It uses the same library file generation process as
BundlingMode.LibraryOnly. It then bundles that library,
the loader, and the Scala.js output into a
yourapp-bundle file by concatenating them. If
enableSourceMaps := true,
it will attempt to use the node.js
concat-with-sourcemaps module to combine the sourcemaps as well.
If you need interoperability with the full
Application mode or somehow can't handle the two files generated
LibraryOnly() mode, this mode may be useful for you. However, it relies on post-processing and eliminates
some of the benefits of the
LibraryOnly mode, so consider carefully if you really need it before turning it on.
The tasks and settings that control the plugin are documented in the API documentation of the ScalaJSBundlerPlugin.
WebScalaJSBundlerPlugin provides integration with sbt-web-scalajs.
Enable this plugin on JVM projects that need to use .js artifacts produced by Scala.js projects (ie in places
where you used to enable
The plugin tunes the
scalaJSPipeline to use the bundles produced by webpack rather than the direct
output of the Scala.js compilation.
Some NPM packages also contain static assets (e.g. fonts, stylesheets, images, etc.). You can make them available as sbt-web assets as follows:
Note: for older sbt versions use
(nodeModules / "font-awesome").***instead.
client is the identifier of an sbt project that uses the
ScalaJSBundlerPlugin. The above configuration
makes all the files within the
font-awesome package available as sbt-web assets.
These assets keep their path prefix relative to the
node_modules directory: for instance the asset path of the
css/font-awesome.min.css resource is
The tasks and settings that control the plugin are documented in the API documentation of the WebScalaJSBundlerPlugin.