Global Script Injector
While the <scripts-injector> custom element provides a powerful declarative approach to lazy-loading scripts by encapsulating logic within a Web Component, there are scenarios where a non-web-component solution is preferable to maintain a cleaner DOM structure or to aggregate script loading rules globally.
To accommodate these use cases, we provide the Global Script Injector.
Need a more straightforward approach?
Use the Web Component with scripts-injector and declarative triggers.
Read the main docs →
What is it?
The Global Script Injector utilizes a centralized JSON configuration (<script type="ecopages/global-injector-map">) and plain HTML data-eco-trigger attributes. It leverages the exact same robust interaction-tracking and intersection-observer logic as the <scripts-injector>, but completely decoupled from custom elements.
Configuration
Define a single global JSON map that associates arbitrary "trigger IDs" with their respective loading conditions (on:idle, on:interaction, on:visible) and target scripts:
<script type="ecopages/global-injector-map">
{
"analytics-trigger": {
"on:idle": {
"scripts": ["/_assets/tracker.js"]
}
},
"complex-ui-loader": {
"on:interaction": {
"value": "mouseenter,focusin",
"scripts": ["/_assets/heavy-ui.js"]
},
"on:visible": {
"value": "200px",
"scripts": ["/_assets/lazy-image.js"]
}
}
}
</script>HTML Attributes
Any standard HTML element can opt into these triggers by referencing the keys from the global map using a data-eco-trigger attribute. This keeps your component structure pristine without deeply nesting wrapper elements.
<!-- Loads analytics.js on idle as defined in the global map -->
<div class="page-wrapper" data-eco-trigger="analytics-trigger">...</div>
<!-- Loads heavy-ui.js on hover and lazy-image.js when visible -->
<button data-eco-trigger="complex-ui-loader">Load Complex UI</button>Initialization
Unlike the Web Component which autoregisters, the Global Injector must be explicitly initialized. Provide this in your main entrypoint or layout component:
import { initGlobalInjector } from '@ecopages/scripts-injector/global';
const injector = initGlobalInjector();
// Example: wire into your framework/router lifecycle
router.onAfterNavigate(() => {
injector.refresh();
});
app.onDispose(() => {
injector.cleanup();
});Behind the scenes, initGlobalInjector will:
- Parse your
<script type="ecopages/global-injector-map">blocks. - Query the DOM for any
[data-eco-trigger]elements. - Observe the DOM for any newly added elements via a
MutationObserver. - Return a handle with
refresh()andcleanup()so your framework controls lifecycle integration. - Bind
on:idle,IntersectionObserver(on:visible), and DOM event listeners (on:interaction) exactly like the Web Component does.
Compatibility & Deduplication
The Global Injector and <scripts-injector> can be used side-by-side seamlessly. Both implementations avoid duplicate <script> tag injection by checking existing scripts and tracking in-flight loads.
If <scripts-injector> and initGlobalInjector() both try to lazy-load the same script URL, duplicate script injection is prevented and already-present scripts are reused.