# MD5 Hash and Timestamp Based File Naming Convention for Minified Assets in OpenMage

> Discover the MD5 hash and timestamp based file naming convention for minified assets in OpenMage. Learn how fballiano/openmage-cssjs-minify creates unique cache-busting filenames for better asset management.

- Repository: [Fabrizio Balliano/openmage-cssjs-minify](https://github.com/fballiano/openmage-cssjs-minify)
- Tags: how-to-guide
- Published: 2026-03-01

---

**The openmage-cssjs-minify module generates minified asset filenames by combining an MD5 hash of the original file path with the Unix timestamp of the last modification, producing unique cache-busting names like [`d41d8cd98f00b204e9800998ecf8427e-1709254321.js`](https://github.com/fballiano/openmage-cssjs-minify/blob/main/d41d8cd98f00b204e9800998ecf8427e-1709254321.js).**

The **MD5 hash and timestamp based file naming convention for minified assets** ensures that every compressed JavaScript or CSS file in OpenMage has a unique, deterministic identifier that automatically invalidates browser caches when source files change. This article examines the implementation in the `fballiano/openmage-cssjs-minify` repository, specifically within the observer model that intercepts HTTP responses and manages asset compression.

## How the Naming Convention Works

The filename generation relies on three discrete components concatenated into a single string.

### MD5 Hash of the Relative Path

In [`app/code/community/Fballiano/CssjsMinify/Model/Observer.php`](https://github.com/fballiano/openmage-cssjs-minify/blob/main/app/code/community/Fballiano/CssjsMinify/Model/Observer.php), the module calculates `md5($path)` where `$path` represents the asset's relative path on disk. This operation occurs at line 45 for JavaScript files and line 75 for CSS stylesheets, producing a 32-character hexadecimal hash that guarantees uniqueness across different source files.

### File Modification Timestamp

Immediately after computing the hash, the module retrieves the source file's Unix modification time using `filemtime($baseDir . $path)` at line 46 for JS and line 76 for CSS. This timestamp serves as the cache-busting mechanism, ensuring that any modification to the source immediately generates a new filename.

### Original Extension Preservation

The final component appends the original file extension—`.js` or `.css`—to complete the pattern: `<md5-hash>-<timestamp>.extension`.

## Implementation in the Observer Model

The `httpResponseSendBefore` observer method handles the filename construction dynamically during the page rendering process.

For JavaScript assets (lines 44-48):

```php
$time = filemtime($baseDir . $path);
$hash = md5($path) . "-$time.js";

```

For CSS assets (lines 75-78):

```php
$time = filemtime($baseDir . $path);
$hash = md5($path) . "-$time.css";

```

## Benefits of the MD5-Timestamp Pattern

This dual-component approach solves three critical problems in asset management:

- **Deterministic Uniqueness**: The MD5 hash ensures that [`js/app.js`](https://github.com/fballiano/openmage-cssjs-minify/blob/main/js/app.js) and [`skin/js/app.js`](https://github.com/fballiano/openmage-cssjs-minify/blob/main/skin/js/app.js) produce different filenames even if modified simultaneously, preventing collisions in the `media/fbminify/` directory.
- **Automatic Cache Busting**: Because the timestamp changes with every file save, browsers treat updated assets as new resources, eliminating stale cache issues without manual version query strings.
- **Simplified Cleanup**: The `dailyCron` method (lines 22-35) parses the hash component to group related files, allowing the system to retain only the newest timestamp for each unique hash while deleting outdated versions.

## Working with the Filename Convention

Developers can leverage this pattern both within the module's automated workflow and for custom implementations.

### Accessing Minified URLs Programmatically

When the observer processes a response, it constructs the complete URL by combining the media base URL with the generated hash:

```php
$time = filemtime($baseDir . $path);
$hash = md5($path) . "-$time.js";
$minifiedUrl = $mediaUrl . 'fbminify/' . $hash;

```

### Manual Minification Outside the Observer

For custom scripts requiring manual compression:

```php
$srcPath = '/var/www/magento/js/custom/script.js';
$baseDir = Mage::getBaseDir();
$mediaDir = Mage::getBaseDir('media');
$minDir = $mediaDir . '/fbminify/';

$time = filemtime($baseDir . $srcPath);
$hash = md5($srcPath) . "-$time.js";
$target = $minDir . $hash;

$minifier = new \MatthiasMullie\Minify\JS($baseDir . $srcPath);
$minifier->minify($target);

```

### Cron-Based Cleanup Logic

The maintenance routine in `dailyCron` removes obsolete files by extracting the hash prefix:

```php
$files = scandir($minifiedDir, SCANDIR_SORT_DESCENDING);
foreach ($files as $file) {
    $hash = explode('-', preg_replace('/\.(js|css)$/', '', $file))[0];
    // Retain only the first (newest) file per hash, delete others
}

```

## Summary

- The **MD5 hash and timestamp based file naming convention** combines `md5($path)` with `filemtime()` to create unique asset identifiers.
- Filenames follow the pattern `<md5>-<timestamp>.js` or `<md5>-<timestamp>.css` as implemented in [`Observer.php`](https://github.com/fballiano/openmage-cssjs-minify/blob/main/Observer.php) lines 45-48 and 75-78.
- This approach guarantees cache invalidation when source files change while preventing filename collisions across different asset paths.
- The `dailyCron` method uses the hash component to group and clean up outdated minified versions automatically.

## Frequently Asked Questions

### How does the MD5 hash prevent filename collisions?

The hash is computed from the complete relative path of the source file, meaning [`js/app.js`](https://github.com/fballiano/openmage-cssjs-minify/blob/main/js/app.js) and [`skin/frontend/js/app.js`](https://github.com/fballiano/openmage-cssjs-minify/blob/main/skin/frontend/js/app.js) produce different MD5 values. This ensures that identically named files in different directories receive unique minified filenames, preventing one asset from overwriting another in the `media/fbminify/` storage directory.

### What triggers a new timestamp in the filename?

Any modification to the source file updates its Unix modification time, which the `filemtime()` function captures at processing time. When the observer detects a newer timestamp, it generates a fresh filename with the updated timestamp, forcing browsers to download the updated asset rather than serving a cached version.

### How does the module clean up old minified files?

The `dailyCron` method scans the minified directory and extracts the MD5 hash from each filename by splitting on the hyphen delimiter. Files sharing the same hash are grouped, and all but the newest timestamp version are deleted, preventing disk bloat while maintaining the most recent compressed assets.

### Can I manually generate these filenames outside the observer?

Yes. By importing the `MatthiasMullie\Minify` library and using the same logic found in [`Observer.php`](https://github.com/fballiano/openmage-cssjs-minify/blob/main/Observer.php)—computing `md5($path)`, appending `filemtime()`, and adding the extension—you can programmatically create minified files that follow the convention and remain compatible with the module's cleanup routines.