Plugins are a powerful feature in Nijor that allow you to define custom behavior at compile time. In fact, many core framework features—such as n:loop list rendering, inline on:event handling, and reactivity bindings—are built internally as compiler plugins. This design makes Nijor highly modular and extensible.
To use a plugin, import its factory function and add it to the plugins array inside your project's nijor.config.js file:
import compressPlugin from "@/plugins/compress.js";
import analyticsPlugin from "@/plugins/analytics.js";
export const plugins = [
compressPlugin(),
analyticsPlugin()
];
During the build phase, Nijor executes these plugins sequentially in the order they are defined inside the array.
A Nijor compiler plugin is structured as an asynchronous factory function. It returns a secondary asynchronous function that receives the active compilation context and yields the modified component content and scripts.
export default function customPlugin(pluginOptions) {
return async function ({ document, scope, props, scripts, filename, module_type }) {
// Custom compilation and DOM transformation logic goes here
return {
name: "Custom Plugin Name",
body: document.body.innerHTML, // Yield the modified HTML
...scripts // Yield the updated scripts
};
};
}
The plugin's execution handler receives a highly rich context object containing:
document: A JSDOM instance representing the component's parsed HTML DOM tree. You can use standard DOM APIs (e.g., querySelectorAll, setAttribute) to query and modify markup directly.
scope: A unique, randomized string identifier generated for the current component, layout, or page. This is useful for namespacing CSS or logic.
props: An array containing the parsed property attributes defined on the component's opening tag.
scripts: An object storing the generated JavaScript segments (see below).
filename: The absolute path of the file currently being compiled.
module_type: A string designating the current module classification. The value can be "component", "layout", or "page".
The scripts object contains three primary properties: main, global, and defer.
Best Practice: Avoid overwriting scripts.main or other script properties directly. Because they house compiler-generated bootstrap logic, overwriting them will break compilation output. Instead, always append your modifications:
// Safely inject custom script behavior
scripts.main += "// Additional custom compiler logic goes here;";
To build robust plugins, it is helpful to understand how the Nijor compiler transforms a .nijor component. Internally, components are compiled into a structural initialization sequence:
// Injected inside scripts.global
const myComponent = new component(templateFn, callbackFn);
scripts.global: Contains top-level declaration code, such as registering component initializers and importing external dependency scripts.
templateFn: A function that runs whenever the template needs to render. It executes the code written inside your component's original <script> tag (except imports, which are lifted to the top level) and returns the generated markup.
callbackFn: Executes immediately after the templateFn mounts the component's markup to the DOM, facilitating child component bootstrapping.
scripts.defer: Dynamic script blocks that are executed inline inside the templateFn lifecycle scope.