Motivation

Javascript platforms are highly adaptable to their deployment environment. Tools such as webpack exist to provide a way to assemble applications in javascript environments. These tools are highly flexible because the deployment requirements for an application are highly specific to the device and target state configuration that the application will be deployed into. In contrast, the jvm environment is much more standardized in both the packaging format as well as the deployment scenarios e.g. jar files and war files for web applications.

Some typical packaging and deployment configurations for javascript deployments are:

  • web:

    • Single application .js file to be loaded into the browser.

    • Multiple application .js files to be loaded the server

    • Multiple dependencies obtained through CDNs

    • Multiple dependencies loaded directly, unchanged in their package, from the local server

    • Multiple dependencies loaded directly, re-situated, from the local server e.g. you copy all of your dependencies into a single servable directory

  • nodejs

    • Single application file but all dependencies provided by npm and using node's module search path algorithm

    • Single application file with all dependencies bundled together

    • Dependency files dynamically retrieved e.g. URL fetching at runtime

    • Executable with all dependencies bundled together so there is no dependency on node, npm or any global/local state of node installation

Since nodejs can be used for deploying both web and command line applications, it has become quite popular to ensure that npm-install dependencies can be used in both environments. Not all npm modules allow you to do this, but many do. To use a npm module in web applications, a program is needed to assemble the content. webpack is an application that builds a dependency graph and outputs one or more artifacts (.js or .css, etc.) files for consumption by your application. The specific output is dependent on how you wish to deploy your application.

For example, you may create one giant css file and one giant .js file. Or you may to bundle everything together. When files of different types are bundled together, webpack inserts its own "module loader" infrastructure so that references to import a module using ES5 or CommonJS module syntax is resolved to internal references. Tools like webpack parse the js and css files and follow the "imports" so that it knows the entire set of assets to include. Obviously, you can tell webpack to treat some imports differently and assume that they "provided" in case you accessing your assets from CDNs or other locations that webpack should ignore.

A developer must be acutely aware of which dependency is coming from which source for this to work smoothly. Once you map out the dependencies and their sources, you can program webpack to assemble them using different mechanism e.g. concatenating files, uglifying them, using google closure compiler. webpack and its plugins have special ways to configure the graphing and assembly process e.g. using loaders and options to loaders. Configuration options to loaders can be specified in the webpack configuration file and in a source file (i.e. using the ! syntax to chain loaders). It's quite flexible but can be confusing.

Scalajs has a plugin scalajs-sbt that assembles and packages content together as well. sbt is a general purpose tool that can also perform additional steps. sbt support for "play framework" applications, for example, also allow converting sass files into css files.

So theoretically it is possible to use sbt to perform all assembly and packaging steps, however, it is not always convenient. Since js program dependencies can come from different sources such as nodejs npm modules, its clear that there should be some interaction between these environments so that the warts and points of view from one environment do not make it exceptionally difficult to execute in another environment. For javascript programs, its better to use multiple tools even for something as simple as a command line tool.

Developing nodejs CLI applications

CLI tools based on nodejs are becoming popular. A couple of posts on this topic include:

Last updated