Do I really need to learn all this "new" stuff?
What is the difference between a "module" and a "bundle"?
Do we really need bundles?
Couldn't I just use Gulp and Browserify?
What does "module loading" mean?
Why not use RequireJS/AMD or ES6 modules for module/bundle loading?
How do I create a bundle?
One concern that has been raised about new JavaScript approaches that might involve new technologies (new to the Jenkins tool-chain) is the fear that it would add to the learning curve for new and existing Jenkins plugin developers. We added this section to this README specifically to alleviate that concern.
The use of js-modules
for plugin GUI development is totally optional! If you want to continue developing
your plugin's GUI using the same technologies you've always used (Jelly etc), then that is not a problem. You can
happily ignore everything here; nothing new is being forced on anyone!
js-modules
is designed to help where the maintainer is interested in using "newer" JavaScript technologies
to build a richer plugin GUI that has more maintainable JavaScript code (more modular, better unit testing etc) that
can be more easily evolved over time (can safely move to newer versions of "Framework" libraries such as jQuery etc).
Again, if none of this interests you at the moment, then that is not a problem. You can continue building your plugin GUI using the same techniques and technologies as before (server-side, Jelly etc).
A "bundle" is a single JavaScript file that contains 1 or more CommonJS "modules". We use Browserify to handle the creation of these bundles. It
handles the process of making sure all the module require
calls are resolvable within the "bundle" i.e. that the bundle
has everything it needs to execute properly.
In theory "no", but bundles provide 2 big benefits (and probably more):
- Bundles allow us to load a suite of tightly related CommonJS modules (an "app") in a single request Vs loading them all individually (ala RequireJS/AMD).
- Bundles make modularized "app" coding a lot nicer/cleaner because they allows us to use the synchronous
require
programming model made popular by node.js. The bundling makes this possible because it removes the need for the asynchronous module loading (ala RequireJS/AMD - ugly anonymous callbacks etc) that would be required if the browser needed to load each module individually.
Yes, you could build modularized JS (and use it in your plugin) using Gulp and Browserify only. In fact, that was what
we did before creating js-modules
.
However, the problem with that approach is that it means every app bundle will contain all the code for every JS Framework lib it depends on. That might not seem like a problem when a page has just one of these "apps", but if it has multiple "apps" from different plugins, all using jQuery (and maybe some other libs e.g. Bootstrap), then you have a situation where all of these libraries are being loaded multiple times. This is something we would like to avoid.
One of the main things that js-modules
is trying provide is the ability to create slimmed down "app" bundles
that only contain the "app" JS modules i.e. no framework libs. The framework libs are bundled separately
(in their own bundles) and "linked" into "app" bundles that need them via the export
/ import
mechanism.
See Framework libs.
js-modules
is a "module bundle" loader.
Read:
Two module loading patterns are "relevant" with js-modules
:
- Intra-bundle module loading. The loading of CommonJS style modules within a bundle e.g. module
A
loading moduleB
, where both modules are within the same bundle. - Inter-bundle module loading. The loading of CommonJS style modules across bundle "boundaries" e.g. module
A
loading moduleB
, where both modules are in different bundles.
Browserify handles #1
nicely, but it doesn't really handle #2
in a way that works nicely for Jenkins. This is why js-modules
exists. Of course, one could just build self contained bundles using Gulp and Browserify (and so stick with #1
), but that's not
a scalable solution (see link below).
Read:
One could debate the pros and cons of different module loading systems ad nauseam.
Read:
We went with the Browserify + js-modules
approach for a few reasons:
- Browserify lets us use CommonJS style modules in browser code i.e. synchronous
require
of modules for intra-bundle module loading. Asynchronous module loading patterns (ala Require/AMD) is something we wanted to avoid as we were not fans of the async AMD loading patterns involved (anonymous callbacks etc). - Browserify lets us bundle all the CommonJS modules for an "app" into a single JavaScript file, allowing them all to be loaded in a single request Vs loading each module to the browser one at a time ala RequireJS.
- Using RequireJS to perform the loading of the Browserify generated bundles is something we considered (and experimented with). A number of problems were encountered here, but the main one (that seems insurmountable) was the fact that Browserify and RequireJS have difficulty living alongside each other on the same page due to the fact that RequireJS defines a
require
function in the global scope. - We felt that using a simple name-based module loader (ala
js-modules
- "does a module of this name exist, yes/no?" - no funky module path resolution algorithms etc) for inter-bundle module loading would be less likely to result in strange unforeseen things happening.
See jenkins-js-builder.