2.4 | The Cubbles Dependency API


Introduction

The Cubbles platform comes with an own dependency management mechanism. In the following we will describe how you can use the API provided by the platform to handle dependencies. This in particular means

  • How to add additional dependencies
  • How to exclude one or more dependencies
  • How to replace existing dependencies

A dependency of an artifact is another required artifact. In most cases those required artifacts will be compound components, elementary components or utilities. 

Note

We strongly recommend you to read and understand the section before you proceed!


Prerequisites

Assuming we do have included a <first-demo-component> component instance into our index.html. Furthermore in this example the <first-demo-component> should be a compound component. Thus we do have several dependencies that our compound component needs to work as expected.

The dependency tree of first-demo-component looks as follows:

Dependency tree of first-demo-component
demo-package@1.0/first-demo-component // we call this a root dependency
  |
  |- another-demo-package@1.0/demo-elementary-component
  |  |
  |  |- third-party-lib@1.0/awesome-lib-util
  |
  |- demo-package@1.0/my-utility

As a page editor or html developer that just wants to use the first-demo-component from the webpackage demo-package@1.0 you don't need to take care about including all the needed dependencies (and their coresponding resources) into the page's <head> area.

The dependency resolving mechanism inside the RTE does all the magic to ensure all of these needed resources are included into the page's head to make the first-demo-component work as expected. Duplicated dependencies are also removed.

index.html before dependency injection
<head>
...
</head>
<body>
	...
	<first-demo-component cubx-webpackage-id="demo-package@1.0">
	</first-demo-component>
	...
</body>
index.html after dependency injection
<head>
...
	<!-- 
		Note: this is just for explanation purposes! 
		In fact each artifact comes with a list of ordinary web 
		resources like JS, HTML or CSS files which will be included
		by DependencyManager of the RTE.
	-->
	<link rel="import" href="third-party-lib@1.0/awesome-lib-util">
	<link rel="import" href="another-demo-package@1.0/demo-elementary-component">
	<link rel="import" href="demo-package@1.0/my-utility">
	<link rel="import" href="demo-package@1.0/first-demo-component">
...
</head>
<body>
	...
	<first-demo-component cubx-webpackage-id="demo-package@1.0">
</first-demo-component>
	...
</body>

Adding additional artifacts to existing dependencies

In some cases you might want to add some additional dependencies to the existing ones that come from the used components. Normally you are using components out-of-the-box and are not able or willing to manipulate their dependencies by editing the corresponding manifest.webpackage file. This can be because you don't want to release a new version of the component only for the sake of adjusting their dependency list. Or simply because of the fact that you are not the owner of the used component.  

The Cubbles API provides several ways of adding additional dependencies to the existing list of dependencies without changing the used components itself. 

Adding a dependency using the Cubbles TAG API

One way to add dependencies is using the <cubx-dependencies> and <cubx-dependency> tags inside a custom tag of a cubbles component. This is useful when you are restricted to edit only small snippets of a page's html body. For example assume that you are editing content of a Wordpress post. In that case you normally don't have access to the whole html tree of a page but rather can edit html in content section.

In our example on the right hand side we use the Cubbles TAG API to add a new artifact dependency second-demo-utility from webpackage third-party-pkg@1.0. Internally the RTE adjusts the dependency tree by adding the new artifact as new root dependency (Note: the new dependency will be inserted before the existing dependencies into list of root dependencies). The resulting dependency tree will look as follows:


Extended dependency tree of first-demo-component
third-party-pkg@1.0/second-demo-utility // adding  an new root dependency
  |
  |-- ...

demo-package@1.0/first-demo-component
  |
  |- another-demo-package@1.0/demo-elementary-component
  |  |
  |  |- third-party-lib@1.0/awesome-lib-util
  |
  |- demo-package@1.0/my-utility
  • Each custom html tag representing a cubbles component can have exactly one <cubx-dependencies> child
  • The <cubx-dependencies> element can have 1..n <cubx-dependency> children with attributes
    • artifact-id (mandatory)
    • webpackage-id (optional. If no webpackage-id is given then the artifact will be searched in the same webpackacke like the parent cubbles component. In example above this would be demo-package@1.0

    • endpoint-id (optional, needed when referencing an artifact with webpackage.modelVersion < 9)
add dependencies using TAG API
<head>
...
</head>
<body>
	...
	<first-demo-component cubx-webpackage-id="demo-package@1.0">
		<cubx-dependencies>
			<cubx-dependency artifact-id="second-demo-utility" webpackage-id="third-party-pkg@1.0"></cubx-dependency>
		</cubx-dependencies>
	</first-demo-component>
	...
</body>

Adding a dependency using the global window.cubx.CRCInit object

Besides the Cubbles TAG API you can add dependencies using the global property window.cubx.CRCInit.rootDependencies

This property is an array of items where each item defines a root dependency holding the properties

  • webpackageId (mandatory)
  • artifactId (mandatory)
  • endpointId (optional when referencing artifacts with webpackage.modelVersioin < 9)

The resulting dependency tree for the left hand side example will be equal to the one displayed in the last section above.

Add dependencies to CRCInit object
<head>
...
	<!-- 
		The below script block needs to be placed before(!) 
		the crc-loader script is included 
	-->
	<script>
		window.cubx = {
			CRCInit: {
				rootDependencies: [
					{
						webpackageId: 'third-party-pkg@1.0',
						artifactId: 'second-demo-utility'	
					}
				]	
			}
		};
	</script>
...
</head>
<body>
	...
	<first-demo-component cubx-webpackage-id="demo-package@1.0">
	</first-demo-component>
	...
</body>

Exclude certain artifacts from existing dependencies

Similar to adding dependencies it can be useful to exclude specific dependencies. Consider for example a scenario where you do already have the jQuery library on a web page but the cubbles component you want to use also comes with jQuery in it's own dependencies. Thus it would be great if you could exclude jQuery in the dependencies to avoid naming conflicts in global javascript scope.  

Exclude a dependency using the Cubbles TAG API

Analogous to adding dependencies you can use the <cubx-dependency-excludes> and <cubx-depdency-exclude> to exclude one or more dependencies from an artifacts dependency tree.

Dependency tree of first-demo-component
demo-package@1.0/first-demo-component 
  |
  |- another-demo-package@1.0/demo-elementary-component
  |  |
  |  |- third-party-lib@1.0/awesome-lib-util // this package is excluded!
  |
  |- demo-package@1.0/my-utility

The resulting dependency tree would look as follows:

Custom dependency tree of first-demo-component
demo-package@1.0/first-demo-component 
  |
  |- another-demo-package@1.0/demo-elementary-component
  |
  |- demo-package@1.0/my-utility
  • Each custom html tag representing a cubbles component can have exactly one <cubx-dependency-excludes> child
  • The <cubx-dependency-excludes> element can have 1..n <cubx-dependency-exclude> children with attributes
    • artifact-id (mandatory)
    • webpackage-id (optional. If no webpackage-id is given then the artifact will be searched in the same webpackacke like the parent cubbles component. In example above this would be demo-package@1.0

    • endpoint-id (optional, needed when referencing an artifact with webpackage.modelVersion < 9)
exclude dependencies using TAG API
<head>
...
</head>
<body>
	...
	<first-demo-component cubx-webpackage-id="demo-package@1.0">
		<cubx-dependency-excludes>
			<cubx-dependency-exclude 
				artifact-id="awesome-lib-util" 
				webpackage-id="third-party-lib@1.0">
			</cubx-dependency-exclude>
		</cubx-dependency-excludes>
	</first-demo-component>
	...
</body>

Exclude a dependency using the global window.cubx.CRCInit object

Dependency excludes can also be added using the global window.cubx.CRCInit.rootDependencyExcludes property.

This property is an array of items where each item defines a root dependency exclude holding the properties

  • webpackageId (mandatory)
  • artifactId (mandatory)
  • endpointId (optional when referencing artifacts with webpackage.modelVersioin < 9)


Add dependency excludes to CRCInit object
<head>
...
	<!-- 
		The below script block needs to be placed before(!) 
		the crc-loader script is included 
	-->
	<script>
		window.cubx = {
			CRCInit: {
				rootDependencyExcludes: [
					{
						webpackageId: 'third-party-lib@1.0',
						artifactId: 'awesome-lib-util'	
					}
				]	
			}
		};
	</script>
...
</head>
<body>
	...
	<first-demo-component cubx-webpackage-id="demo-package@1.0">
	</first-demo-component>
	...
</body>

The scope of dependency excludes

There is a difference between rootDependencyExcludes and dependency excludes  which are defined for a specific artifact. The main difference is that rootDependencyExcludes always apply to the whole dependency tree. So you could say so they are global. An artifact that added into rootDependencyExcludes array will always be ignored.

In contrast if you define a dependency exclude on artifact level using the Cubbles TAG API then this exclude is only valid within the dependencies of that artifact the exclude is bound to. Let's see an example for pointing out the differences. 

<body>
	...
	<my-first-cubble webpackage-id="...">
		<cubx-dependency-excludes>
			<cubx-dependency-exclude artifact-id="another-artifact" webpackage-id="another-package@1.0"></cubx-dependency-exclude>
		</cubx-dependency-excludes>
	</my-first-cubble>
	...
	<my-second-cubble webpackage-id="..."></my-second-cubble>
	...
</body>

In the example above there are two different Cubble components instantiated. Assuming that my-first-cubble as well as my-second-cubble does use artifact another-artifact from webpackage another-package@1.0.

The exclude defined for this shared artifact is only valid within the dependencies of my-first-cubble. Because it is only declared for my-first-cubble. And because my-second-cubble does need this artifact the exclude will be ignored by the Dependency Manager of the RTE.


Replace artifacts in existing dependencies

When combining dependency addition and dependency excludes it it possible to replace artifacts in existing dependencies. 

The example on the ride hand side replaces the artifact awesome-lib-util from webpackage third-party-lib@1.0 with artifact awesome-lib-util from webpackage third-party-lib@2.0

In fact here we replaced an existing dependency with a newer version of it's own.

replace dependencies using TAG API
<head>
...
</head>
<body>
	...
	<first-demo-component cubx-webpackage-id="demo-package@1.0">
		<cubx-dependencies>
			<cubx-dependency
				webpackage-id="third-party-lib@2.0"
				artifact-id="awesome-lib-util">
			</cubx-dependency>	
		</cubx-dependencies>
		<cubx-dependency-excludes>
			<cubx-dependency-exclude 
				webpackage-id="third-party-lib@1.0"
				artifact-id="awesome-lib-util">
			</cubx-dependency-exclude>
		</cubx-dependency-excludes>
	</first-demo-component>
	...
</body>