Skip to main content

Styles and Scripts

Deodar provides a powerful asset management system that handles SCSS compilation, JavaScript bundling, and proper enqueuing for both frontend and backend. This guide will show you how to add and manage styles and scripts in your Deodar project.

Overview

Deodar's asset management system offers:

  • SCSS Compilation: Automatic compilation with source maps
  • JavaScript Bundling: Modern ES6+ support with bundling
  • Conditional Loading: Load assets on frontend, backend, or both
  • Dependency Management: Handle script dependencies properly
  • Development & Production: Different builds for different environments
  • Watch Mode: Real-time compilation during development

Configuration

Styles and scripts are configured in your main project file using the deodar filter:

add_filter('deodar', function($data) {
return [
'path' => get_template_directory(), // or plugin_dir_path(__FILE__)
'url' => get_template_directory_uri(), // or plugin_dir_url(__FILE__)
'production' => false,
'styles' => [
// Your styles configuration
],
'scripts' => [
// Your scripts configuration
]
];
});

Styles Configuration

Basic Style Configuration

'styles' => [
[
'handle' => 'main-style',
'file' => '/build/index.build.scss',
'frontend' => true,
'backend' => false
]
]

Style Configuration Options

OptionTypeRequiredDescription
handlestringUnique identifier for the style
filestring⚠️Path to the SCSS file (relative to project root)
urlstring⚠️External URL for the style
frontendboolLoad on frontend (default: true)
backendboolLoad on backend/admin (default: false)
templatestring/arraySpecific template(s) to load this style on
dependenciesarrayArray of style handles this depends on
versionstringVersion string for cache busting
mediastringCSS media type (default: 'all')

⚠️ Either file or url is required (not both)

Advanced Style Configuration

'styles' => [
[
'handle' => 'google-fonts',
'url' => 'https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap',
'frontend' => true,
'backend' => false
],
[
'handle' => 'main-style',
'file' => '/source/index.scss',
'dependencies' => ['google-fonts'],
'version' => '1.0.0',
'media' => 'all',
'frontend' => true,
'backend' => false
],
[
'handle' => 'admin-style',
'file' => '/source/admin.scss',
'frontend' => false,
'backend' => true
]
]

Scripts Configuration

Basic Script Configuration

'scripts' => [
[
'handle' => 'main-script',
'file' => '/source/index.js',
'frontend' => true,
'backend' => false
]
]

Script Configuration Options

OptionTypeRequiredDescription
handlestringUnique identifier for the script
filestring⚠️Path to the JavaScript file (relative to project root)
urlstring⚠️External URL for the script
frontendboolLoad on frontend (default: true)
backendboolLoad on backend/admin (default: false)
templatestring/arraySpecific template(s) to load this script on
dependenciesarrayArray of script handles this depends on
versionstringVersion string for cache busting
argsboolLoad in footer (default: false)

⚠️ Either file or url is required (not both)

Advanced Script Configuration

'scripts' => [
[
'handle' => 'jquery',
'url' => 'https://code.jquery.com/jquery-3.6.0.min.js',
'frontend' => true,
'backend' => true
],
[
'handle' => 'main-script',
'file' => '/source/index.js',
'dependencies' => ['jquery'],
'version' => '1.0.0',
'args' => true, // Load in footer
'frontend' => true,
'backend' => false
],
[
'handle' => 'admin-script',
'file' => '/source/admin.js',
'dependencies' => ['jquery'],
'frontend' => false,
'backend' => true
]
]

File Structure

your-project/
├── source/ # Source files
│ ├── index.scss # Global styles
│ ├── index.js # Global scripts
│ ├── admin.scss # Admin-only styles
│ └── admin.js # Admin-only scripts
├── build/ # Compiled assets (auto-generated)
│ ├── index.build.css
│ ├── index.build.css.map
│ ├── index.build.js
│ └── index.build.js.map
└── ... # Other files

Template-Specific Loading

Template Key Usage

The template key allows you to load assets only on specific templates, improving performance by loading only what's needed:

'styles' => [
[
'handle' => 'homepage-style',
'file' => '/build/homepage.build.css',
'template' => 'front-page.php',
'frontend' => true,
'backend' => false
],
[
'handle' => 'blog-style',
'file' => '/build/blog.build.css',
'template' => ['index.php', 'single.php', 'archive.php'],
'frontend' => true,
'backend' => false
]
]

Common Template Patterns

A common pattern is to have global assets that are always loaded, plus template-specific assets. The global index.scss and index.js files import header styles and scripts:

'styles' => [
// Always loaded global styles (includes header via @use)
[
'handle' => 'main-style',
'file' => '/build/index.build.css',
'frontend' => true,
'backend' => false
],
// Template-specific styles
[
'handle' => 'homepage-style',
'file' => '/build/homepage.build.css',
'template' => 'front-page.php',
'frontend' => true,
'backend' => false
],
[
'handle' => 'contact-style',
'file' => '/build/contact.build.css',
'template' => 'page-contact.php',
'frontend' => true,
'backend' => false
]
],
'scripts' => [
// Always loaded global scripts (includes header via import)
[
'handle' => 'main-script',
'file' => '/build/index.build.js',
'frontend' => true,
'backend' => false
],
// Template-specific scripts
[
'handle' => 'homepage-script',
'file' => '/build/homepage.build.js',
'template' => 'front-page.php',
'frontend' => true,
'backend' => false
]
]

File Organization for Template-Specific Assets

your-project/
├── source/
│ ├── index.scss # Global styles (imports header.scss)
│ ├── index.js # Global scripts (imports header.js)
│ ├── homepage.scss # Homepage-specific styles
│ ├── homepage.js # Homepage-specific scripts
│ ├── contact.scss # Contact page styles
│ └── contact.js # Contact page scripts
├── template-parts/
│ ├── header/
│ │ ├── header.scss # Header styles (imported by index.scss)
│ │ └── header.js # Header scripts (imported by index.js)
│ └── footer/
│ ├── footer.scss # Footer styles (imported by index.scss)
│ └── footer.js # Footer scripts (imported by index.js)
└── build/ # Compiled assets
├── index.build.css
├── homepage.build.css
└── contact.build.css

Import Patterns

In source/index.scss:


// Template part styles
@use '../template-parts/header/header.scss';
@use '../template-parts/footer/footer.scss';

// Global styles
body {
font-family: 'Roboto', sans-serif;
}

In source/index.js:

// Import template part scripts
import Header from '../template-parts/header/header.js';
import Footer from '../template-parts/footer/footer.js';

// Global JavaScript
$(document).ready(function() {
console.log('Global script loaded');
});

External Dependencies

CDN Resources

You can include external resources from CDNs:

'styles' => [
[
'handle' => 'bootstrap',
'url' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css',
'frontend' => true,
'backend' => false
]
],
'scripts' => [
[
'handle' => 'bootstrap',
'url' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js',
'dependencies' => ['jquery'],
'frontend' => true,
'backend' => false
]
]

WordPress Dependencies

Use WordPress core dependencies:

'scripts' => [
[
'handle' => 'custom-script',
'file' => '/source/index.js',
'dependencies' => ['jquery', 'wp-api'],
'frontend' => true,
'backend' => false
]
]

Build Configuration

deodar.json Configuration

Create a deodar.json file in your project root to customize the build process:

{
"externals": {
"jquery": "jQuery",
"lodash": "_",
"gsap": "gsap"
},
"skip": [
"node_modules/**",
"dist/**",
".git/**"
]
}

Configuration Options

OptionTypeDescription
externalsobjectExternal dependencies to exclude from bundling
skiparrayFile patterns to skip during compilation

Development Workflow

1. Create Source Files

Create your SCSS and JavaScript files in the source/ directory:

// source/index.scss
$primary-color: #007cba;
$secondary-color: #f0f0f0;

body {
font-family: 'Roboto', sans-serif;
color: $primary-color;
}

.button {
background-color: $primary-color;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;

&:hover {
background-color: darken($primary-color, 10%);
}
}
// source/index.js
import $ from 'jquery';

$(document).ready(function() {
console.log('Deodar project loaded!');

// Your JavaScript code here
$('.button').on('click', function() {
console.log('Button clicked!');
});
});

2. Configure in Main File

Add the styles and scripts to your Deodar configuration:

add_filter('deodar', function($data) {
return [
'path' => get_template_directory(),
'url' => get_template_directory_uri(),
'production' => false,
'styles' => [
[
'handle' => 'main-style',
'file' => '/build/index.build.scss',
'frontend' => true,
'backend' => false
]
],
'scripts' => [
[
'handle' => 'main-script',
'file' => '/build/index.build.js',
'dependencies' => ['jquery'],
'frontend' => true,
'backend' => false
]
]
];
});

3. Build Assets

Use the Deodar CLI to build your assets:

# Development build
deodar development

# Production build
deodar production

# Watch mode for development
deodar watch

Best Practices

Performance Optimization

  1. Minimize Dependencies: Only include what you need
  2. Use CDNs Wisely: Balance performance vs. reliability
  3. Conditional Loading: Load assets only where needed
  4. Version Control: Use version strings for cache busting

Code Organization

  1. Modular SCSS: Break styles into logical components
  2. ES6 Modules: Use modern JavaScript features
  3. Consistent Naming: Use consistent naming conventions
  4. Documentation: Document complex configurations

Development Workflow

  1. Use Watch Mode: For real-time development
  2. Test Both Environments: Test frontend and backend loading
  3. Version Control: Track source files, not build files
  4. Error Handling: Handle missing files gracefully

Troubleshooting

Common Issues

Styles Not Loading

  • Check file paths in configuration
  • Verify SCSS compilation
  • Check browser console for errors

Scripts Not Working

  • Verify JavaScript file paths
  • Check for JavaScript errors in console
  • Ensure dependencies are loaded

Build Errors

  • Check SCSS syntax
  • Verify JavaScript syntax
  • Check deodar.json configuration

Debug Mode

Enable debug mode to see detailed information:

'production' => false, // Set to false for development

Examples

Complete Configuration Example

add_filter('deodar', function($data) {
return [
'path' => get_template_directory(),
'url' => get_template_directory_uri(),
'production' => false,
'styles' => [
// External dependencies
[
'handle' => 'google-fonts',
'url' => 'https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap',
'frontend' => true,
'backend' => false
],
// Global styles (includes header via @use in source/index.scss)
[
'handle' => 'main-style',
'file' => '/build/index.build.css',
'version' => '1.0.0',
'frontend' => true,
'backend' => false
],
// Template-specific styles
[
'handle' => 'homepage-style',
'file' => '/build/homepage.build.css',
'template' => 'front-page.php',
'frontend' => true,
'backend' => false
],
[
'handle' => 'blog-style',
'file' => '/build/blog.build.css',
'template' => ['index.php', 'single.php', 'archive.php'],
'frontend' => true,
'backend' => false
],
// Admin styles
[
'handle' => 'admin-style',
'file' => '/build/admin.build.css',
'frontend' => false,
'backend' => true
]
],
'scripts' => [
// Global scripts (includes header via import in source/index.js)
[
'handle' => 'main-script',
'file' => '/build/index.build.js',
'dependencies' => ['jquery'],
'version' => '1.0.0',
'args' => true,
'frontend' => true,
'backend' => false
],
// Template-specific scripts
[
'handle' => 'homepage-script',
'file' => '/build/homepage.build.js',
'template' => 'front-page.php',
'dependencies' => ['jquery'],
'frontend' => true,
'backend' => false
],
// Admin scripts
[
'handle' => 'admin-script',
'file' => '/build/admin.build.js',
'dependencies' => ['jquery'],
'frontend' => false,
'backend' => true
]
]
];
});

Next Steps

Now that you understand how to manage styles and scripts:


Ready to build something amazing? Let's create your first custom block!