Upgrading LaxarJS

The LaxarJS packages use semantic versioning, so as long as you upgrade within a major version of LaxarJS or one of the associated libraries and widgets, you should not have any problems.

Of course, sometimes minor changes introduce bugs or new, (hopefully) better way to do things within applications. To get the full details of what happens between versions, consult the changelogs. A CHANGELOG.md file is maintained in each of our repositories, and accessible from the documentation site. Whenever a change comes with associated upgrade information, the changelog will mention this, and contain a pointer to the relevant GitHub issue. Note however, that sometimes individual changelog entries may be reverted or made obsolete by later changes.

Keeping in mind that only the changelogs contain the complete upgrade information with all the gritty details, this guide tries to give you the big picture of what happened between major versions. It also tries to give a short rationale for each change, so that you know why we think the upgrade effort is justified.

Migration Guide: LaxarJS v1.x to LaxarJS v2.x

Under the hood, LaxarJS v2 is a major refactoring of LaxarJS. In the process of this refactoring, AngularJS was removed as a core dependency, and stateful APIs such as logging were changed to become injectable services. This improves testability, and allows technology adapters to freely intercept and modify widget injections. It also enables multiple LaxarJS applications to run alongside each other within a single browser window.

Fortunately, for existing widgets, not that much has changed: AngularJS widgets now require an adapter (see below), and some APIs that were previously accessed as properties of the LaxarJS object will now need to be injected into the widget controller.

Cleaning up widget spec tests may require a little more work, since LaxarJS Mocks was cleaned up significantly.

Major Versions in Lockstep

The following libraries have their major version locked to that of LaxarJS Core itself:

This means, that for these libraries…

  • their v2.0 is released (roughly) around the same time as LaxarJS Core v2.0,
  • their v2.0 is compatible with LaxarJS Core v2.0.

For other packages, especially widgets and controls, this is not true. When in doubt, always consult the package.json of the respective artifact.

Tooling: npm and webpack

This should not affect widgets and activities too much directly, but will require to rebuild some project infrastructure and configuration.

LaxarJS v1 projects used:

  • Bower to obtain front end application artifacts,
  • RequireJS to load modules,
  • npm, Grunt, grunt-laxar and various grunt plugins to obtain and run the project build pipeline.

For LaxarJS v2, we wanted to support pre-built artifacts whose sources may be written in ES2015 or other "compile-to-js" languages, as well as artifacts that add dependencies to the development toolchain.

Bower is not really a good fit for pre-built artifacts, as it is always backed by sources on GitHub. Rather than adding more "build repositories", we chose to switch to npm for front end artifacts, which was already required for the tooling infrastructure anyway. In order to integrate seamlessly with workflows using ES2015 and SCSS, we switched from a collection of custom grunt tasks to a build infrastructure based around webpack.

So, the new list of tools looks like this:

  • npm to obtain front end artifacts as well as build-time dependencies
  • webpack and its loaders (especially the laxar-loader) to load and bundle artifacts

This saves us a lot of work maintaining grunt plugins: laxar-tooling and laxar-loader are much smaller than grunt-laxar. It also makes custom build setups much simpler, as it unlocks the full array of webpack plugins for loading widgets, controls and their assets. Where needed, it is of course still possible

More Information:

JSON Schema now Processed at build-time

LaxarJS feature configuration for widgets, activities and compositions is no longer processed at runtime, but while loading the application artifacts using the laxar-loader for webpack. This allows us to replace the jjv validator with the ajv validator which is more actively maintained, more feature-rich and apparently more performant. Simultaneously we save on bundle size and startup time, as neither the validator nor any widget schema instances need to be loaded or interpreted within the browser.

Note that LaxarJS deviates from standard JSON schema in two respects. This was the case with jjv, and we ported the deviations to ajv:

  • "additionalProperties": false is default for all schemas of "type": "object",
  • "format" allows for the LaxarJS specific value "topic", and checks it,
  • defaults for features (first level of widget/composition schema) are inferred if they are of type "array" or "object",
  • support for ${topic:…} and ${features.…} syntax in compositions, before applying format checks.

More Information:

AngularJS Support Moved to Standalone Adapter Project

The LaxarJS runtime no longer depends on functionality provided by AngularJS. Writing widgets using AngularJS works just like before, you just need to:

console npm install --save laxar-angular-adapter`

  • pass it to create using the adapters option.

More Information:

AngularJS: axLayout Control Removed

Because layouts are now first-class items in widget areas, directly embedding them in widgets unnecessarily complicates the implementation of both widgets and runtime. Widgets should simply offer widget areas, which can then be configured by the page to contain layouts.

More Information:

AngularJS: ngSanitize no longer loaded by default

Not every application needs angular-sanitize to secure dynamically loaded HTML. If you are using a widget that relies on ngSanitize, you need to manually install angular-sanitize and load it from the corresponding widget or control.

More Information:

Application Configuration: window.laxar is No More

LaxarJS is no longer using a global object property for configuration. This improves testability and allows to run multiple LaxarJS instances side-by-side. Pass your configuration values to create instead, using the last parameter (configuration).

More Information:

Artifact Directory Defaults Changed

With the new tooling infrastructure, all artifact types (themes, flows, pages, layouts, widgets, controls) will be expected to reside within the respective sub-folders of application/ within your project. Previously, widgets, controls and themes were expected to reside in sub-folders of includes/. This behavior can be customized by creating a laxar.config.js in your project and exporting the corresponding paths.flows, paths.pages and so on from there.

More Information:

Styles/Templates for Widgets/Controls Lookup by Name Only

Previously, LaxarJS used several heuristics to derive the name of activities/widgets, layouts, controls or themes from their file system path segment. The name is needed to find the JavaScript implementation module, CSS stylesheet and HTML template (for widgets and layouts) of an artifact.

Now, widgets and controls must always provide a descriptor (widget.json, control.json) with a name property. That name is then used to load the implementation module from the directory of the descriptor, as well as themed assets from the appropriate sub-directories. Here, the resolve configuration of webpack comes into play, which allows projects using Angular 2 or Vue.js to transparently load implementations from .ts or .vue files.

Using explicit names instead of incidental file system locations makes artifacts robust against being moved, and for being used in different contexts. It also eliminates confusion regarding the name of directories and files when styling artifacts from within a theme.

An exception is made for loading the implementation module of widgets that have a package.json: To allow these widgets to be pre-compiled from "compile-to-js" languages, they may use the "browser" field of their package.json to specify the location of their implementation module.

More Information:

Several LaxarJS APIs moved to Injectable Services

Previously, LaxarJS offered several stateful APIs as part of its exported API. These were replaced by injectable widget services as follows:

  • laxar.configuration -> axConfiguration
  • laxar.log -> axLog
  • laxar.i18n -> axI18n
  • laxar.storage -> axStorage

This change improves testability and allows to run multiple instances of LaxarJS on the same page. During your transition to LaxarJS v2, you can use the dist/laxar-compatibility.js entry point, which adds shims for the missing APIs. Note that the compatibility entry point is intended only for use during a migration and not part of the official API. This means that it may be removed in upcoming minor versions.

The stateless utility APIs assert, object and string are not affected by this change.

More Information:

Flow Definition: Format Changed

The flow definition files have a new format that clearly distinguishes between place IDs and URL mappings. This also allows to map multiple URL patterns to the same place, and to specify place parameter values for redirects.

Also, the syntax for routing pattern definition has changed slightly, as LaxarJS now uses Navigo for routing.

More Information:

Flow Definition: Removed entryPoint / exitPoint features

These features were hard-to-explain in manuals as they cater to a very narrow set of integration use cases. Entry points can be replaced by using entry pages containing an activity that fires navigation events. Exit points can be replaced by simply adding an activity that invokes the external API previously triggered by the exit point.

More Information:

Flow: Default Router Changed from Angular $route to Navigo

Because AngularJS was removed from LaxarJS core, we no longer use AngularJS $route for routing. Rather than creating our own standalone routing library, LaxarJS now depends on the Navigo routing microlibrary. We also evaluated page.js by visionmedia, but due to the recent lack of project activity we think that Navigo is the right choice for now. In the near-future, we plan on making routers pluggable. This will be especially useful if your UI framework comes with a router anyway.

More Information:

axFlowService: constructPath, constructAnchor removed

The methods constructPath and constructAnchor were removed because they are not portable across routing setups using hash-based and path-based navigation. You should always use constructAbsoluteUrl to create links within a LaxarJS application.

More Information:

axFlowService: No More Trailing '_'

When generating URLs where values of trailing parameters are missing, this no longer results in trailing underscores. Make sure to structure your routing patterns to handle these URLs, or avoid them by always populating the respective place parameters.

More Information:

Page Definition: builtin areas now use ax prefix

The builtin/auto-generated widget areas (activities, popups, popovers) were renamed (to axActivities, axPopups, axPopovers) to draw attention to the fact that they are automatically provided by LaxarJS. Hopefully, this saves new developers from wasting time looking for the responsible layout.

More Information:

Widget Descriptor: new styleSource and templateSource

Previously, SCSS had to be integrated by using the grunt-laxar-compass package, which required generated CSS to be committed to version control. Now, SCSS can be processed by setting the styleSource attribute of the widget.json descriptor. This allows for arbitrary compile-to-css languages (such as LESS).

Also, the grunt plugin was notoriously unreliable in watching transitive SCSS import dependencies, which is no longer the case when using webpack with the sass-loader. The Yeoman Generator generates appropriate webpack dependencies and configuration out-of-the-box.

Additionally, templateSource can be used to preprocess widget HTML templates. This allows to use HTML generators such as pug to preprocess widget templates.

More Information:

axVisibility: new widget service injection

Dealing with visibility events in LaxarJS v1 was too much voodoo. The new axVisibility widget injection hopefully simplifies things. To deal with visibility, the new injection is recommended over LaxarJS Patterns visibility and over using the event bus directly.

More Information:

axI18n: new widget service injection

Dealing with internationalization has been further simplified and detangled from AngularJS by the new axI18n injection. Also, the new injection is instantiated per bootstrapping instance, so that multiple LaxarJS applications can coexist in a browser window, and even use different locales. To deal with i18n, the new injection is recommended over LaxarJS Patterns i18n and over using the event bus directly.

More Information:

Replace require.toUrl() using axAssets

LaxarJS no longer depends on RequireJS, and it is not recommended to mix RequireJS with webpack either. Some widgets may use the toUrl-method provided by RequireJS for generating absolute URLs. As this method constructs URLs at runtime, it is not supported by webpack.

You may wish to use webpack to pre-bundle smaller assets within a reusable widget that has its own package.json and build-setup. In general, it is recommended to use the axAssets injection instead.

More Information:

axEventBus: removed methods: unsubscribe, setMediator, setErrorHandler

The LaxarJS event bus no longer allows to register a mediator, as this feature was never used. Configuring a custom error handler was removed from the public API as well, with its use case (testing) supported by a pre-configured event bus mock.

Using unsubscribe was usually not required except when using the axGlobalEventBus injection. To cancel an event bus subscription, you must now use the callback returned by axEventBus.subscribe. This avoids possible problems with trying to using the old unsubscribe on decorated subscriber functions.

More Information:

Widget adapter API changed

The widget adapter API was rewritten to make adapters more powerful. The two most important changes:

  • creating an adapter for a widget instance may now be asynchronous
  • widget adapters may now freely intercept and modify widget service injections

More Information:

LaxarJS Mocks: Static HTML Test Runner is No More

Because widget dependencies are no longer loaded at runtime by RequireJS, the recommended setup for testing widgets using LaxarJS Mocks has changed significantly:

  • no more copy/paste of HTML spec runner files
  • use the laxar-mocks/spec-loader for webpack to precompile widget dependencies
  • no more need to declare "missing" CSS assets of controls
  • run tests on the command-line using karma and karma-webpack
  • run tests within the browser using the webpack-jasmine-html-runner-plugin

More Information:

LaxarJS Mocks: Use axMocks.widget.setupForWidget

To clarify that test fixtures are now provided automatically and in advance (e.g. by the LaxarJS Mocks spec-loader for webpack), the testbed should now be created using setupForWidget.

LaxarJS Mocks: axMocks.widget.teardown is now Asynchronous

To clean up correctly after tests, LaxarJS mocks publishes the endLifecycleRequest event after each tests and allows the widget under test to perform cleanup before proceeding.

LaxarJS Patterns: patches API removed

The deprecated patches API was removed. Use JSON patch instead.

LaxarJS Patterns: resources API: removed updateHandler, replaceHandler

Use handlerFor( context ) instead (or $scope instead of context for AngularJS widgets).

LaxarJS Patterns: actions API: use Promise Rejections Correctly

Actions publisher promises are no longer rejected for actions with an ERROR outcome, caused by e.g. validation failure. Instead, promises will only be rejected when subscribers fail with an exception.

LaxarJS Patterns: Various Breaking Changes

Most likey, only very few widgets are affected by the remaining breaking changes. Consult the Changelog for details:

LaxarJS UiKit: I18n Controls Removed

The controls contained in LaxarJS UiKit were locked to the "angular" integration technology. The axLocalize filter for AngularJS is now included in the laxar-angular-adapter.

Browser Support

Support for MS Internet Explorer 9 was dropped. LaxarJS v2 relies on dynamic property getters, which are not available for MSIE 8 and cannot be polyfilled. In principle, MSIE 9 may still be working, but we are not actively supporting it.

Other than that, since LaxarJS no longer directly depends on AngularJS, it may actually be possible to support more browsers than in past major versions.

More Information:

Migration Guide: LaxarJS v0.x to LaxarJS v1.x

According to semantic versioning, minor versions starting with v0. may introduce breaking changes. We tried to avoid that as much as possible during our own v0.x releases, but depending on where you start off, only some of these items will be relevant for you. Since LaxarJS v0.x was not used that much, this information is kept short:

  • Support for MS Internet Explorer 8 was dropped.

  • The format of didUpdate events was changed from "update maps" to the standard JSON patch format. When upgrading any complex application, this is probably the most work-intensive change.

  • The JSON schema format for widgets was changed from v3 to v4, with a compatibility fallback.

  • The laxar.text helper was removed.

  • Location and naming of HTML templates and CSS stylesheets was unified across artifacts.

  • Some of the name-mangling magic was removed when translating artifact names to file names or AngularJS module names.

  • The testing library built into LaxarJS core was deprecated in favor of LaxarJS Mocks.

  • Controls became a themable artifact type, with the control.json as a descriptor.

  • AngularJS was upgraded from 1.2.x to (at least) 1.3.x.

For all the details, consult the changelog.