unbundled #1
This is the simplest CLI model to implement. Our "bundled1" approach keeps all application authored content in the "src" folder and the application is bundled into a single output file using a webpack first build model.
Here are the main ingredients:
.scala files to bundled together using sbt
Other application .js source files, all of which will be bundled together.
External dependencies from npm (nodejs based) NOT bundled into our application.
scala
src/main/scala/app:
cli.app - main cli app that prints out the command line parameters and contains some small facades to access chalk and table
We use the npm versions of chalk and table.
Dependencies
scala:
scopt (scalajs version)
pure javascript:
src/main/resources/cli/ContentFormatting.js
src/main/resources/formatting.js
src/main/scala/app/messages.js
facades:
io.scalajs.nodejs - comprehensive nodejs facade
npm (left unbundled):
chalk - colorized terminal output
table - table output
Outputs
bin:
cli.js - output cli executable (shell script)
cli.js.map - source map
node_modules
chalk
table
Our core output cli.js will be built using webpack. webpack will take both the output of scalajs as well as the dependency*.js files and bundle them into a single output file.
Build config
This example requires both sbt and webpack to create the final outputs in the form we want. We could use sbt for some of the last processing steps but that would require some code and knowing more about sbt vs webpack configuration. Granted, both sbt programming and webpack configuration are complex topics, but we want to show how webpack fits into the overall build especially when there are alot of moving parts.
In the end, the build will be a webpack led build cycle.
Here's our cli.webpack.config.js
:
There's alot here so lets take it in pieces.
// // Based on lifecycle, optimize some outputs. // webpack -p already adds webkpace.DefinePlugin(...NODE_ENV="production") // so we do not add it here. Instead of uglify we could also use GCC // but the core scala has already gone through uglify if fullOptJS was used. //
Imports
Since the webpack config file is a nodejs module, we can require what we need at the top.
Specify start of webpack graph
This specifies that webpack should assume the cli.scala file is the entry point for our CLI program. The output will be an index.js file in the root directory. Our target build is "node" which tells webpack not to bundle in nodejs standard libraries like "os" or "fs".
However, we need to specify the loader that translates .scala files into nodejs artifacts in the webpack graph.
Webpack loaders
This is the loader for .scala files. The scalajs-loader
npm module provides a webpack loader that shells out to sbt to build. Hence, we need a build.sbt file which is
Our project/* files are:
and
Notice that we only declare one jsDependencies, 'bundleme.js' that should be bundled into the core sbt-scalajs output file. This is for illustration purposes only. You could skip bundling any js files in, and in fact, its probably better to keep then unbundled.
Plugins
This last webpack config says to add the shebang line to the output, index.js. Then, an inline webpack module is specified which changes the execution mode and final name of the CLI program.
package.json
We never really specified our package.json file, which we need to do because need to declare our dependencies and ensure that when nodejs installs our CLI it knows how to do that. Also, package.json holds toplevel "scripts" to execute to run the build:
The dependencies were declared saved using npm install --save-dev <dependency>
or npm install --save <dependency>
as appropriate.
Last updated