About bundlers
Bundlers are a key part of the BladeRunner framework, assembling the code of different blades into a single application when it is ready to run. This topic explains what they are and how they are used.
BladeRunner
The main purpose of BladeRunner is to split a monolithic web application into a set of independent, reusable HTML5 modules called blades. During development, all the software assets of a blade are kept within a single directory, with the JavaScript split further into a large number of .js files, each of which contains a single class. When an app is run, all the software assets of a particular type (for example: CSS, XML, JavaScript) are delivered in a single file. In a nut-shell: during development, all an application’s software components are kept separate, for ease of maintenance; but at runtime, they are assembled into one file per asset-type, for maximum efficiency.
Bundlers concatenate all the required code assets across a number of blades into asset-specific "bundle" files. Any dependencies from Caplin or third-party libraries are automatically included.
Assets
We use the generic word Assets to describe all of the different types of content that can comprise an application. There are six asset types, each of which has its own bundler.
-
JavaScript source
-
CSS stylesheets
-
CSS Resources (e.g. Images, Typefaces, etc
-
i18n (internationalisation) properties file
-
HTML templates
-
XML configuration
How Do Bundlers Work in Practice?
There are three basic scenarios in which you will run your application, and bundling works slightly differently in each of them:
-
Displaying in a browser during development
-
Running tests on your code
-
Building a deployable application
Scenario 1 – Displaying in a Browser during Development
During development, you would want to display a blade in a browser, either in isolation (in a workbench page, while you are working on it) or as part of the whole application, which you would do by viewing the index.html page of a particular aspect.
In either case, every time the browser requests a page, the bundlers run as servlets within BladeRunner’s embedded app server. They treat the requested page as a "seed" file and perform a recursive dependency analysis (which is to say that they check which resources are going to be needed to display the page, and then go and fetch them), before producing bundle files that contain all the code needed to run the application.
This means that any time a line of source code is changed, that affects any part of the page being displayed, the result can be seen just by refreshing your browser. The bundlers are written with performance in mind, and workbench pages typically take just a few tenths of a second to reload.
Scenario 2 – Running Tests on Your Code
As the diligent and conscientious developer that you no doubt are, you will be writing unit tests and acceptance tests as you develop your JavaScript code, and it’s fairly likely that you will be using Verifier to run them. Assuming that this is the case, test code is placed in the tests directory of the appropriate aspect, bladeset or blade (depending on exactly what you are testing at the time). Verifier uses Google js-test-driver to run tests, and the JsTestDriver.conf file – a copy of which resides in the tests folder being used at the time – determines which tests to run. To load the code assets that are needed to test the application, you need to add a bundler plugin to JsTestDriver.conf, as follows:
plugin: - name: "BundleInjector"
jar: ../../../sdk/libs/java/testRunner/js-test-driver-bundler-plugin.jar
module: com.caplin.jstestdriver.plugin.CutlassBundleInjectorPlugin
The path to the js-test-driver-bundler-plugin.jar file will of course vary, depending on the location of the JsTestDriver.conf file that contains the reference. The js-test-driver-bundler-plugin.jar file contains code that emulates all the bundlers; there are not separate jar files for each one. |
The bundlers are executed by js-test-driver every time tests are run.
Scenario 3 - Building a Deployable Application
When deploying an app, the bundlers run in "batch mode" and generate static bundle files which are included in the war file that is installed in the production system. Bundlers are not used in a production environment, as the pre-bundled files are served directly.
Scope and Scoping Rules
The modular structure and conventions that are the basis of BladeRunner, are enforced by the bundlers. This takes place in two ways:
Firstly, if the bundlers are to work, resource files must be kept in their designated places, or the bundlers will not be able to locate them. When the application is run therefore, the resource files will not be assembled properly, making it very likely that errors will occur.
Secondly, and in some respects more fundamentally, bundlers ensure that the modular hierarchy of a BladeRunner application is applied properly. What this means in practice is that code within a particular blade can only be used by that blade, whereas code within a bladeset’s resource folders can be used by any blade within that bladeset. Code that belongs to the wider application, including the Caplin libraries and any third-party libraries, can be used by any blades. The bundlers make sure that the scope of each blade is respected, so that scripts in one blade do not over-ride those of another.
These "scoping rules" vary, depending on the scenario from which you run the bundlers. These rules determine which input files are provided to the bundler in particular conditions. The bundlers for different asset-types have different rules, and each bundler concatenates these files, accordingly.
It should be noted that for some asset types the order in which files are included matters. For example CSS files from the higher levels, such as aspect, are always included after the CSS files from lower level blade directories. This ensures that common rules (background colour for instance) are set at the app level. These behaviours vary for each bundler.
See also: