-
Notifications
You must be signed in to change notification settings - Fork 36
BladeRunnerJS Plugin Development Guide
BladeRunnerJS supports the following plug-in interfaces:
-
ModelObserverPlugin
(observe events on the model) -
CommandPlugin
(run commands through 'brjs') -
ContentPlugin
&BundlerContentPlugin
(serve browser requests) -
TagHandlerPlugin
&BundlerTagHandlerPlugin
(replace logical page tags) -
AssetPlugin
(support new asset file types, e.g. Node.js classes) -
AssetLocationPlugin
(support new asset directory structures, e.g. Node.js directory structure) -
MinifierPlugin
(source-map friendly minifier support) -
TestPlugin
(support new test runners -- not yet available)
Plug-ins can be accessed directly via BRJS.plugins()
, or indirectly using one of the many methods that makes use of plug-ins under the convers, for example:
BRJS.runCommand(String... args)
BundlableNode.getSourceModule(String requirePath)
BundlableNode.getBundleSet()
Here are some of the more interesting plug-ins that will be available with the 1.0 release:
- In-built Jetty web server (
CommandPlugin
) - Flat-file export support (
CommandPlugin
) - WAR export support (
CommandPlugin
) - Templated project and blade creation (
CommandPlugin
) - BladeRunnerJS Thirdparty Library Support (
AssetLocationPlugin
,AssetPlugin
,BundlerContentPlugin
&BundlerTagHandlerPlugin
) - Node.js Thirdparty Library Support (
AssetLocationPlugin
,AssetPlugin
,BundlerContentPlugin
&BundlerTagHandlerPlugin
) - BladeRunnerJS Conformant Library Support (
AssetLocationPlugin
-- class & asset support is dependent on other plug-ins) - Node.js style class support (
AssetPlugin
,BundlerContentPlugin
&BundlerTagHandlerPlugin
) - Namespaced style class support (
AssetPlugin
,BundlerContentPlugin
&BundlerTagHandlerPlugin
) - CSS bundling (
AssetPlugin
,BundlerContentPlugin
&BundlerTagHandlerPlugin
) - HTML template bundling (
AssetPlugin
&BundlerContentPlugin
) - XML config bundling (
AssetPlugin
&BundlerContentPlugin
) - I18N internatiionalization support (
AssetPlugin
,BundlerContentPlugin
&BundlerTagHandlerPlugin
) - Composite Javascript Bundling (
BundlerContentPlugin
&BundlerTagHandlerPlugin
) - Composite CSS Bundling (
BundlerContentPlugin
&BundlerTagHandlerPlugin
) - Fast concatenating minification (
MinifierPlugin
) - Closure Compiler minification with single-level source map support (
MinifierPlugin
) - Aliasing IoC mechanism (
ContentPlugin
&AssetPlugin
) - Js-test-driver test runner for fast browser-based testing (
TestPlugin
) - Selenium test runner for pointy-clicky browser-based tests (
TestPlugin
)
You may have noticed that some of the plug-in types are often grouped together. Often you will write plug-ins that implement only a single plug-in interface, but bundler plug-ins often involve a number of plug-ins, due to the following inter-dependencies that they have:
- The
AssetLocationPlugin
recognizes JavaScript locations by virtue of there being either a manifest-file or a recognizer-file. - The
AssetPlugin
will only 'recognize' js source files within supported asset locations (usinggetJsStyle()
), so is dependent on anAssetLocationPlugin
. - The
BundlerContentPlugin
will only serve assets it recognizes (unless it's a composite), so we need a correspondingAssetPlugin
. - The
BundlerTagHandlerPlugin
plug-in will only generate requests forBundlerContentPlugin
instances it's associated with (unless it's a composite).
These are plug-ins we're not planning to write for 1.0, but which we believe our plug-in interfaces are capable of supporting, and for which we'd love to see contributions:
- EcmaScript6 support so we can write standards based code now (
AssetPlugin
,BundlerContentPlugin
&BundlerTagHandlerPlugin
-- depends on the BRJS conformant library plug-in) - TypeScript for strongly typed JavaScript, including sourcemap support (
AssetPlugin
,BundlerContentPlugin
&BundlerTagHandlerPlugin
-- depends on the BRJS conformant library plug-in) - Bower style library support (
AssetLocationPlugin
,AssetPlugin
,BundlerContentPlugin
&BundlerTagHandlerPlugin
) - Bower package management support (
CommandPlugin
) - JsHint to provide JavaScript linting support (
TagHandlerPlugin
&ContentPlugin
) - LessCSS to allow leaner style-sheets (
AssetPlugin
,BundlerContentPlugin
&BundlerTagHandlerPlugin
) - UglifyJS version 2 minification, with multi-level source map support (
MinifierPlugin
) - Karma test runner for reliable browser based testing (
TestPlugin
) - Node.js test runner for reliable non-browser based testing (
TestPlugin
) - App-Cache support as an alternative to HTTP caching (
TagHandlerPlugin
&ContentPlugin
) - Heroku deployment support (
CommandPlugin
)
We'll provide quick responsive support for anybody attempting to write any of these plug-ins that runs into problems in the core code base.
The plug-in interfaces are defined as follows:
Plug-ins are registered using the SPI Mechanism introduced in Java 6. All plug-ins available on the class-path will be automatically discovered, and be usable from within BladeRunnerJS. At present this can only be done by dropping plug-ins into the 'conf/java' directory, but by 1.0 we'll support plug-ins that get pulled in much the same way as libraries can, with the potential to do this using a package management tool like Bower.
Because plug-ins form part of the model, yet use the model to initialize themselves, an untenable circular dependency exists. To overcome this problem, each concrete plugin instance is wrapped inside a Virtual Proxy that delays plug-in initialization until somebody attempts to actually use the plug-in.
Since code interested in interacting with a subset of the plug-ins will often need to query all of them to locate the ones it needs, certain identifier methods are proxied through before the object's setBRJS()
method has been invoked, which plug-in authors must be aware of. Another consequence of wrapping all plug-ins in a virtual proxy is that the instanceof
operator and the getClass()
method does not work as expected. The Plugin.instanceOf()
and Plugin.getPluginClass()
methods are provided to overcome these deficiencies (see BRJS Initialization Problem for more details).