File Resolving in Magento 2 (Static, Template, Script, …) : Clues for Debugging


When Magento 2 wants to find a view file from the filesystem, it uses a fallback mechanism with a file resolving method. Unlike when a Class file is missing (where it gives an error) sometimes Magento 2 doesn’t provide an error message or so (even if error display is enforced).

I came up with a typo in the filename, which I didn’t notice, I got empty content area on frontend. No error messages. After a few debug sessions, found some clues on few interesting places to look on such a scenario.

Let’s take seeking of a static resource file [DOC_ROOT]/app/code/Netstarter/Training/view/base/web/custom.css

Magento 2 Static File Resolving

But by mistake, we have created the file with a typo, custom2.css

Magento 2 Static File Resolving

“Static Resource” Application

When a static file is requested from Magento 2, within [DOC_ROOT]/pub folder, if the requested file does not exist  (i.e. [DOC_ROOT]/pub/static directory), using Apache/NginX rules, the request is redirected to the [DOC_ROOT]/pub/static.php file which will try to find the file in the file system

This file is a mini application which can be called as “Static Resource Application” based on the class Magento\Framework\App\StaticResource

The Asset Repository

The Magento\Framework\View\Asset\Repository object will allow us to create asset objects. Asset objects can convert a file identifier Netstarter_Training::custom.css into a full URL.

Resolving the File Path

Resolving the static resource filename/path is done by several classes which all are implemented using \Magento\Framework\View\Design\FileResolution\Fallback\ResolverInterface

Currently there are 3 types of Resolvers found under [DOC_ROOT]/vendor/magento/framework/View/Design/FileResolution/Fallback/Resolver

  1. Simple.php
  2. Alternative.php (Which extends Simple to search through alternative extensions available)
  3. Minification.php

These classes will try to resolve following kinds of file types.

  1. file
  2. locale
  3. template (phtml files for block classes)
  4. static (static resources like css, js)
  5. email (email template files)
#FILE::[DOC_ROOT]/vendor/magento/framework/View/Design/Fallback/RulePool.php:Line 259
/**
 * Get rule by type
 *
 * @param string $type
 * @return RuleInterface
 * @throws \InvalidArgumentException
 */
public function getRule($type)
{
    if (isset($this->rules[$type])) {
        return $this->rules[$type];
    }
    switch ($type) {
        case self::TYPE_FILE:
            $rule = $this->createFileRule();
            break;
        case self::TYPE_LOCALE_FILE:
            $rule = $this->createLocaleFileRule();
            break;
        case self::TYPE_TEMPLATE_FILE:
            $rule = $this->createTemplateFileRule();
            break;
        case self::TYPE_STATIC_FILE:
            $rule = $this->createViewFileRule();
            break;
        case self::TYPE_EMAIL_TEMPLATE:
            $rule = $this->createEmailTemplateFileRule();
            break;
        default:
            throw new \InvalidArgumentException("Fallback rule '$type' is not supported");
    }
    $this->rules[$type] = $rule;
    return $this->rules[$type];
}

*** Where to Debug ***

Following code in the [DOC_ROOT]/vendor/magento/framework/View/Design/FileResolution/Fallback/Resolver/Simple.php will loop through the fallback paths available for the asset, and will check whether the file existing and will return the path.

 //FILE:: DOC_ROOT]/vendor/magento/framework/View/Design/FileResolution/Fallback/Resolver/Simple.php:Line 91
/**
 * Get path of file after using fallback rules
 *
 * @param RuleInterface $fallbackRule
 * @param string $file
 * @param array $params
 * @return string|bool
 */
protected function resolveFile(RuleInterface $fallbackRule, $file, array $params = [])
{
    if (\strpos($file, 'content.html') !== false) {
        $a = 1;
    }
    foreach ($fallbackRule->getPatternDirs($params) as $dir) {
        $path = "{$dir}/{$file}";
        if ($this->rootDirectory->isExist($this->rootDirectory->getRelativePath($path))) {
            return $path;
        }
    }
    return false;
}

Placing a debug pointer here or by adding log message, one can determine, what file path its actually looking for, what are the places to look for the files. This would be quick and accurate way to debug the failing asset.

Fallback Path Samples for Asset Files

Fallback mechanism for asset files in order for the custom Module Netstarter_Training. File will be searched in the below order and return with the path if found, otherwise will return false.

1. "/var/www/html/trn/magento2/vendor/magento/theme-frontend-luma/Netstarter_Training/web/i18n/en_US"
2. "/var/www/html/trn/magento2/vendor/magento/theme-frontend-luma/Netstarter_Training/web"
3. "/var/www/html/trn/magento2/vendor/magento/theme-frontend-blank/Netstarter_Training/web/i18n/en_US"
4. "/var/www/html/trn/magento2/vendor/magento/theme-frontend-blank/Netstarter_Training/web"
5. "/var/www/html/trn/magento2/app/code/Netstarter/Training/view/frontend/web/i18n/en_US"
6. "/var/www/html/trn/magento2/app/code/Netstarter/Training/view/base/web/i18n/en_US"
7. "/var/www/html/trn/magento2/app/code/Netstarter/Training/view/frontend/web"
8. "/var/www/html/trn/magento2/app/code/Netstarter/Training/view/base/web"

Fallback Path Samples for Template Files

For a template file, it will look into the theme fallback, and will come to the module and will check appropriated area (frontend, adminhtml) then in the common area (base). Please note that Netstarter_Training module is used as the sample module. As an example, for a template file

  1. Your Theme/Relevant Module/templates
  2. Parent Theme/Relevant Module/templates
  3. Relevant Module/view/frontend/templates
  4. Relevant Module/view/base/templates
1. “/var/www/html/trn/magento2/vendor/magento/theme-frontend-luma/Netstarter_Training/templates”
2. “/var/www/html/trn/magento2/vendor/magento/theme-frontend-blank/Netstarter_Training/templates”
3. “/var/www/html/trn/magento2/app/code/Netstarter/Training/view/frontend/templates”
4. “/var/www/html/trn/magento2/app/code/Netstarter/Training/view/base/templates”

Hope this helps.

Leave a Reply

  • (will not be published)