◁ Markup ≡ Table of Contents Composite ▷
Seanox composite-js uses composite script, an extension of standard ECMAScript that provides a small set of macros for browser-based module execution.
Composite script is used for the JavaScript resources in the module directory. It is executed directly in a separate function scope rather than as a <script> element. Variables, constants and functions declared in a module remain local to that module and are not automatically available in the global scope or in other modules. The macros provide language extensions for tasks such as loading further JavaScript resources, exporting declarations and creating namespaces.
Embedded scripting has specific runtime behavior. Standard scripts are executed
automatically by the browser and independently of rendering. Markup for
rendering therefore supports the additional script type composite/javascript.
It uses normal JavaScript, but the browser does not recognize it as
text/javascript and does not execute it directly. The composer recognizes the
JavaScript code and executes it in every relevant render cycle. This allows
<script> elements to be combined with declarative attributes such as
condition to control execution.
<script type="composite/javascript">
...
</script>
The module directory contains composite modules, each grouping the resources of a composite. A JavaScript resource within a composite module is called a composite script and provides the application module.
JavaScript resources in the module directory can also exist independently of a composite. These are referred to informally as modules and can be used without composites. The logic is stored in individual files in the module directory and, if necessary, in further subdirectories.
The resources of a composite (JS, CSS, HTML) can be outsourced to the module directory and loaded at runtime, which supports the modular deployment of platform and modules in micro-frontends.
+ modules
+ example
- moduleE.js
- moduleF.js
- ...
- moduleA.js
- moduleB.js
- ...
- index.html
The modules are then loaded programmatically with Composer.include(...),
Composer.load(...) or preferably with the macro #import.
#import moduleA moduleB
#import example/moduleE example/moduleF
Macros are abbreviated notations for common JavaScript statements. A preprocessor resolves them before execution, so the JavaScript engine only executes standard ECMAScript and the surrounding language constructs remain effective.
The #export macro makes selected variables, constants and functions of the
separate function scope available in the global scope. Objects that participate
in composite binding must be exported in this way. The macro expects a
space-separated list of names that extends to the end of the line or the next
semicolon.
const connector = {
...
};
const utilities = {
...
};
#export connector utilities;
Export names can include namespaces so that the elements are added there explicitly.
const connector = {
...
};
const utilities = {
...
};
#export connector@io.example utilities@io.example;
The macro loads one or several modules implemented as composite script resources
from the module directory. Modules are loaded only once, regardless of whether
they are loaded directly via #import or indirectly as a resource of a
composite.
When calling modules, the file extension is omitted.
#import moduleA
#import moduleA moduleB moduleC
It should be noted that the macro will result in an error if the server state is different from 200. The error can be caught as usual with try-catch.
try {#import moduleA;
} catch (error) {
...
}
In the module directory subdirectories are also supported, which is represented in the module names by the slash.
#import example/io/connector;
The macro expects one or more space-separated namespaces to be created at the object level if they do not already exist.
#use a
#use a b c
#use a.b.c d.e.f g.h.i
The tolerating syntax (?...) is a special macro. If the logic inside the
brackets causes an error, no error is raised and no output is written to the
browser console. Instead, the brackets represent the value false. Syntax
errors are excluded from this tolerating behavior.
const value = (?object.that.does.not.exist());
When loading composite scripts, the runtime automatically appends a sourceURL
directive mapping the evaluated script to its original module path:
//# sourceURL=/modules/example/module.js
This allows browser DevTools to expose the dynamically executed script as a source in the sources panel. Composite scripts can therefore be opened, searched, and debugged with breakpoints and the Debugger like regular JavaScript sources.
◁ Markup ≡ Table of Contents Composite ▷