◁ Markup ≡ Table of Contents Composite ▷
Seanox aspect-js uses Composite JavaScript, an extension of JavaScript for browser environments that provides a small set of macros.
Composite JavaScript is used for the JavaScript resources of Composites. It is executed directly in an isolated runtime scope rather than as a script element. Variables, constants and functions declared in an Application Module (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 importing modules, 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 renderer recognizes the JavaScript code
and executes it in every relevant render cycle. This allows SCRIPT elements to
be combined with other composite attributes to control execution.
<script type="composite/javascript">
...
</script>
Application Modules (modules) are part of the Composite concept. Composite resources (JS, CSS, HTML) can be outsourced to the module directory and loaded at runtime, supporting modular deployment of platform and modules in micro-frontends.
Modules can also be used in JavaScript without Composites. The logic is stored in individual files in the module directory and, if necessary, in further subdirectories.
+ modules
+ example
- moduleE.js
- moduleF.js
- ...
- moduleA.js
- moduleB.js
- ...
- index.html
The modules are then loaded programmatically with Composite.include(...),
Composite.load(...) or preferably with the macro #import.
When calling modules, the file extension is omitted.
#import moduleA moduleB
#import example/moduleE example/moduleF
Macros are a meta-syntax that fits into the existing JavaScript syntax. They are abbreviated notations for common JavaScript statements.
Composite JavaScript is executed directly in an isolated runtime scope rather than as a script element. Variables, constants and functions declared in a module are local to that module and are not automatically available in the global scope or in other modules.
The #export macro makes selected variables, constants and functions available
in the global scope. It 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 JavaScript
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. Since the macro integrates into the general JavaScript syntax, 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;
This macro has been implemented as an aid for debugging. It expects text to the end of the line or to the next semicolon, which is output in the browser console in the debug level.
#module some text;
As a special feature, the string expression syntax of JavaScript is also supported, which allows the use of variables.
const value = "Hallo Welt!";
#module some more complex text: ${value} ... ${1 + 2};
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());
Resources and modules, including JavaScript, are loaded only at runtime. The browser therefore does not know the sources and does not show the modules in the developer tools. This is relevant for breakpoints. The entry point into the JavaScript must be accessed through the browser console. The console output also contains a link to the output source. This link opens the module source code in the debugger, where breakpoints can be used. Since modules are loaded dynamically at runtime, they are not initially available in the developer tools of the browser.
Modules should generate console output for debugging. This can be done manually
via the console object or with the macro #module.
#module example;
...
◁ Markup ≡ Table of Contents Composite ▷