Skip to content

BladeRunnerJS NPM Integration Strawman

Dominic Chambers edited this page Jul 24, 2015 · 8 revisions

Introduction

We'd like BladeRunnerJS developers to be able to:

  1. Easily consume the huge number of libraries in NPM.
  2. Create NPM modules instead of creating BRJS libraries.
  3. Create multi-asset NPM modules instead of creating BRJS blades.

BladeRunnerJS doesn't currently have a hard dependency on Node.js, and the last time we canvassed our user-base some of them were unable to use Node.js even in development, but this may very well have changed in the intervening period. Clearly though, not needing to have this dependency would be even easier from a bureaucratic point of view, yet integration with NPM is becoming a necessity.

Integrating NPM

Whereas libraries can currently reside within the application or the SDK, where application libraries take precedence over SDK libraries, we'd additionally like to support NPM modules at these locations:

  • SDK/apps/<app>/node_modules for app libraries.
  • SDK/node_modules for SDK libraries.

The npm install and npm update commands, responsible for populating the node_modules directory, contain all the smarts for determining which versions of each module is to be used, potentially allowing us to avoid having a hard dependency on Node.js if we are willing to parse node_modules, which would invole us re-implementing the functionality present within require.resolve() in Java.

Although we originally imagined that we'd be able to have a mix and match approach, where libraries of all types can co-depend on each other, it's become clear that this approach won't be possible since NPM's installation algorithm can only function correctly when it's able to interpret the semver information for all dependencies. Therefore, although BRJS libraries will be able to depend on NPM modules, NPM modules won't be able to depend on BRJS libraries.

Developing Modules Locally

NPM's local-paths or npm link features can be used to allow NPM libraries and blades to be conveniently developed at the same time as the app.

Handling Global Install

Users that take advantage of the global-install feature to allow the SDK to be independent of the apps will need to set the NODE_PATH environment variable so that it points to SDK/node_modules.

Keeping package.json Synchronized

Developers that use NPM modules in their own apps will need to update their package.json to have entries for each of the SDK libraries currently updated to use NPM. Every time we update a library to NPM, this will cause a backwards compatibility issue. Additionally, if they set the version of internal SDK libraries to anything other than latest, then this may cause them not to get updates when they update the SDK.

These problems can be solved by having a brjs npm command that does the following:

  1. Updates package.json to include valid entries for all of the SDK NPM libraries that the app uses.
  2. Sets the NODE_PATH environment variable if needed (maybe Windows only?).
  3. Invokes npm update on your behalf, ensuring the NODE_PATH environment variable has been set.

and, by allowing non-NPM apps to forgo the package.json completely, and have us determine the NPM dependencies ourselves.

SystemJS

SystemJS will be used to replace browser-modules because it provides a number of advantages:

  • It makes it easier for BRJS & NPM modules to co-exist.
  • It can be made to allow multi-asset NPM modules (NPM blades) to be developed.
  • It makes it easier for us to avoid a hard dependency on Node.js, since it means we won't need to re-implement browserify in Java.
  • It even makes it possible for NPM modules to have hidden dependencies on BRJS modules (via System.import()), which may be useful as a last resort to hack around problems.

Issues

  1. SDK libraries aren't currently plug-able as the model dictates that libraries are the directories beneath SDK/sdk/libs/javascript and SDK/apps/<app>/libs. The asset-location plug-ins are then each given a chance to describe the asset locations within a particular library directory (using getAssetLocationDirectories() and getSeedAssetLocationDirectories()), and can also work together with other plug-ins to provide these asset locations (via allowFurtherProcessing()).
Clone this wiki locally