Introduction

Components.js is a dependency injection framework for JavaScript applications.

Object-oriented applications are typically composed of hard-wired component. For example, when programming a Car instance, several Seat components of a specific type can be inserted. When different seats would be required, the source code would have to be changed.

Instead of hard-wiring software components together, dependency injection allows these components to be defined externally, without the programmer having to know the exact component during implementation.

Components.js is a dependency injection framework that allows components to be instantiated and wired together declaratively using semantic configuration files. The advantage of these semantic configuration files is that software components can be uniquely and globally identified using URIs. Configurations can be written in JSON.

This software is aimed at developers who want to build modular and easily configurable and rewireable JavaScript applications. For example, Comunica is a meta query engine for the Web that uses Components.js to wire modules together in a flexible way to achieve easily configurable query engines.

Note

More specifically, configuration files are written in JSON-LD, which is a way to serialize RDF in JSON. In fact, different kinds of RDF serialization can be used, such as Turtle and TriG.

The following image shows an overview of how Components.js works in summary. Given an application and several external components, the application can be instantiated and the components can be dynamically injected using a JSON config file.

Components.js Overview

Quick Start

Components.js can be installed using npm:

$ npm install componentsjs

1. Define your module and its components

my-module.jsonld:

{
  "@context": [
    "https://linkedsoftwaredependencies.org/contexts/components.jsonld",
    { "ex": "http://example.org/" }
  ],
  "@id": "ex:MyModule",
  "@type": "Module",
  "requireName": "my-module",
  "components": [
    {
      "@id": "ex:MyModule/MyComponent",
      "@type": "Class",
      "requireElement": "MyComponent",
      "parameters": [
        { "@id": "ex:MyModule/MyComponent#name", "unique": true }
      ],
      "constructorArguments": [
        { "@id": "ex:MyModule/MyComponent#name" }
      ]
    }
  ]
}

The npm module my-module exports a component with the name MyComponent.

The constructor of MyComponent takes a single name argument.

2. Create a configuration file containing a component instantiation

config-my-component.jsonld:

{
  "@context": [
    "https://linkedsoftwaredependencies.org/contexts/components.jsonld",
    {
      "ex": "http://example.org/",
      "name": "ex:MyModule/MyComponent#name"
    }
  ],
  "@id": "http://example.org/myInstance",
  "@type": "ex:MyModule/MyComponent",
  "name": "John"
}

This configuration is a semantic representation of the instantiation of MyComponent with name set to "John".

3. Instantiate your component programmatically

...
const Loader = require('componentsjs').Loader;

const loader = new Loader();
await loader.registerModuleResourcesUrl('path/or/url/to/my-module.jsonld');
const myComponent = await loader.instantiateFromUrl(
    'http://example.org/myInstance', 'path/or/url/to/config-my-component.jsonld');
...

myComponent is an instance of type MyComponent, as defined in the config file.

Example Source

Please refer to the remainder of this documentation for more details on each of these parts.

Note

A full stand-alone version of this example, and all other examples in this documentation be found on a dedicated GitHub repository.

Source

Contribute to this documentation on GitHub.

This documentation itself is instantiable using Components.js!