This is a JavaScript "module bundle" loader for Jenkins (NPM package) i.e. a loader for loading a JavaScript file that contains one or more
CommonJS/node.js style modules in a single HTTP request (i.e. a "bundle").

Usage

For the most part, you don't actually use js-modules directly (aside from installing the package). In general,
you use it via js-builder i.e. you use js-builder to build browser-loadable bundles, and those
bundles will use js-modules to load/"import" the modules/packages that they depend on, but do not contain
within their bundle.

After installing js-modules, your next step is to start using js-builder and, as stated above, that's
mostly all you'll ever need to know about js-modules because the rest of it happens under the hood via
js-builder.

That said, it's probably useful to have an understanding of how js-modules actually loads modules/packages.
For that, take a look at MODULE_LOADING.md.

Problem / Motivation

For the most part, the Jenkins GUI is constructed on the server side from Jelly files (Stapler etc). Client-side
JavaScript has not played a big part in the Jenkins GUI.

If the Jenkins GUI is to be modernized and improved (from a user experience perspective), client-side JavaScript
needs to be able to play a bigger part. If that's so, we need to modernize/improve the development patterns around how
JavaScript is currently used in Jenkins.

As we see it, the main issues today are:

Modularity: Jenkins currently has no concept of modularity when it comes to the JavaScript code used in the GUI. All of the JavaScript is concentrated mainly in a single JavaScript file i.e. hudson-behaviour.js.

Anti-Patterns: Too much JavaScript code is bound into the global scope, creating a litany of well known issues.

Testability: Not easy to write JavaScript unit tests. The only way JavaScript is tested is via JenkinsRule (HtmlUnit and it's WebClient).

Multiple versions of Framework Libraries: One version of Prototype/jQuery doesn’t fit all. We need a way of supporting multiple versions of the same library (e.g. jQuery) in a way that works in the browser, "detached" from the global scope. We need to be able to introduce new versions of libraries (and deprecate old versions) in an orderly fashion.

These are the problems that js-modules (this NPM package) is targeted at helping to solve.

It is hoped that js-modules will help those that are interested (see next section) in maintaining modular,
unit testable, evolvable (see note below) JavaScript code that runs in a more predictable/stable environment that
is more immune to plugin updates etc (e.g. an upgrade to the
jQuery plugin doesn't break the plugin GUI).
Using CommonJS style modularity also makes it possible to more easily leverage the growing set of publicly available
NPM/node.js packages, which is a huge benefit.

What do we mean by "evolvable"?: js-modules makes it possible to safely run multiple versions of core JavaScript Framework libs on the same page (jQuery, Bootstrap etc). This makes it possible for modular code (built on js-modules) to depend on an explicit version of a JS lib that is guaranteed to remain available on e.g. plugin upgrades. Conversely, the same modular code can upgrade the version of a lib it depends on without effecting other modular code that still depends on an older version.

Framework Libs (jenkinsci/js-libs)

As stated earlier, using CommonJS style modularity makes it possible to more easily leverage the growing set of publicly available
NPM/node.js packages. If you want to use some really cool NPM package that you just found, all you need to do is follow the
"standard" NPM package installation process, adding it to your "app" bundle e.g. npm install --save cool-new-lib.

This is great, but if followed all the way, your JavaScript "app" bundles will soon become quite heavy for the browser to
load because they will contain all JavaScript required by all the modules in the bundle.

The main feature of js-modules is it's ability to load module bundles that can export / import modules to/from
other modules bundles i.e. share common modules between bundles (see above slides). This means we can create js-modules style
module bundles for different versions of all of the major JavaScript Framework libs out there (jQuery, Bootstrap etc), making it possible for
"app" bundles to share common Framework libs and to not have them in their "app" bundle, making them considerably lighter for
browser load and helping to avoid the bundle bloat problem.

We have already created Framework lib bundles for a number of common JavaScript libs (jQuery, Bootstrap and more).