Snippets Dependencies Management
Table of Contents
Dependency Philosophy
Elemental CMS follows a straightforward and efficient approach to dependency management:
- Load dependencies only when and where they are needed
- Keep files separate and focused - no bundling or minification required
- Direct inclusion of CSS and JavaScript files
- Clean, readable source code for easy maintenance
This philosophy prioritizes:
- Clarity over artificial optimization
- Maintainability over build complexity
- Direct file management over bundling
- Specific loading over generic inclusion
Dependency Levels
The system uses three distinct levels of dependencies, each serving a specific purpose:
1. Global Dependencies
├── Shared across all pages
├── Core functionality (e.g., jQuery, Bootstrap)
└── Managed via global-deps commands
2. Page Dependencies
├── Specific to individual pages
├── Language-specific resources
└── Loaded with page content
3. Snippet Dependencies
├── Loaded only when snippet is used
├── Self-contained in snippet spec
└── Injected during rendering
Global Dependencies
Global dependencies are organized by type in separate folders:
GLOBAL_DEPS_FOLDER/
├── text_css/
│ ├── bootstrap.json # Core styling
│ └── custom-theme.json # Site-wide theme
├── application_javascript/
│ ├── jquery.json # Core functionality
│ └── bootstrap.json # UI components
└── module/
└── app-module.json # Application logic
Each global dependency has its own specification file:
{
"_id": ObjectId("..."),
"order": 1,
"name": "jquery",
"type": "application/javascript",
"url": "js/jquery.js",
"meta": {
"crossorigin": "anonymous"
}
}
Page Dependencies
Pages can include their own specific dependencies:
{
"name": "about",
"language": "en",
"cssDeps": [
{
"name": "about-styles",
"type": "text/css",
"url": "css/about.css"
}
],
"jsDeps": [
{
"name": "about-interactions",
"type": "application/javascript",
"url": "js/about.js"
}
]
}
Snippet Dependencies
Snippets include only the dependencies they need:
{
"name": "product-gallery",
"cssDeps": [
{
"name": "gallery-styles",
"type": "text/css",
"url": "css/gallery.css"
}
],
"jsDeps": [
{
"name": "gallery-behavior",
"type": "application/javascript",
"url": "js/gallery.js"
}
]
}
Working with Dependencies
Creating Dependencies
Create dependencies directly and clearly:
# Global dependency
elemental-cms global-deps create -d datepicker application/javascript
# Snippet with dependencies
elemental-cms snippets create -s contact-form
# Edit contact-form.json
{
"name": "contact-form",
"cssDeps": [
{
"name": "form-styles",
"type": "text/css",
"url": "css/contact-form.css"
}
],
"jsDeps": [
{
"name": "form-validation",
"type": "application/javascript",
"url": "js/contact-form.js"
}
]
}
Managing Dependencies
Simple and direct dependency management:
# List all global dependencies
elemental-cms global-deps list
# Push snippet with dependencies
elemental-cms snippets push -s contact-form
# Pull snippet with dependencies
elemental-cms snippets pull -s contact-form
Best Practices
Follow these guidelines for clean dependency management:
1. Keep Dependencies Focused
├── One file = one purpose
├── Clear, descriptive names
└── Direct file references
2. Load Only What's Needed
├── Global deps for truly shared resources
├── Page deps for page-specific features
└── Snippet deps for snippet functionality
3. Maintain Readability
├── Use descriptive file names
├── Keep source files clean and commented
└── Organize files logically
4. Simple is Better
├── Avoid unnecessary build steps
├── Keep files separate and focused
└── Direct file inclusion
Examples and Use Cases
Navigation Snippet
# nav-bar.json
{
"name": "nav-bar",
"cssDeps": [
{
"name": "nav-styles",
"type": "text/css",
"url": "css/nav-bar.css"
}
],
"jsDeps": [
{
"name": "nav-behavior",
"type": "application/javascript",
"url": "js/nav-bar.js"
}
]
}
# nav-bar.html
<nav class="site-nav">
<ul class="nav-list">
<li><a href="/">nav.home</a></li>
<li><a href="/about">nav.about</a></li>
</ul>
</nav>
Form Snippet with Validation
# contact-form.json
{
"name": "contact-form",
"cssDeps": [
{
"name": "form-styles",
"type": "text/css",
"url": "css/contact-form.css"
}
],
"jsDeps": [
{
"name": "form-validation",
"type": "application/javascript",
"url": "js/contact-form.js"
}
]
}
# contact-form.html
<form class="contact-form" id="contactForm">
<div class="form-group">
<label>form.name</label>
<input type="text" name="name" required>
</div>
<button type="submit">form.submit</button>
</form>
Using Snippets in Pages
{# Each snippet loads only its required dependencies #}
{{ render_snippet('nav-bar', page, inject_inline_deps=True) }}
{{ render_snippet('contact-form', page, inject_inline_deps=True) }}
This approach ensures that each component loads exactly what it needs, when it needs it, without unnecessary complexity or overhead.