s2b / vite-asset-collector

Bundle your TYPO3 frontend assets with Vite
GNU General Public License v2.0
41 stars 11 forks source link

Load additional stylesheets in TYPO3 backend #33

Open zenoussi opened 9 months ago

zenoussi commented 9 months ago

It is possible to load additional CSS files for the TYPO3 backend interface via regular $TYPO3_CONF_VARS settings in a settings.php file of a project (previously known as LocalConfiguration.php) file or in an extension's ext_localconf.php.

$GLOBALS['TYPO3_CONF_VARS']['BE']['stylesheets'][my_extension] = 'EXT:myextension/Resources/Public/Css/myfile.css';
$GLOBALS['TYPO3_CONF_VARS']['BE']['stylesheets'][my_extension] = 'EXT:myextension/Resources/Public/Css/';

How can the requirements be solved?

Thanks a lot

s2b commented 9 months ago

Hi! This was a topic in the Slack channel recently. There isn't an elegant solution in the extension yet, but it seems to be possible:

https://typo3.slack.com/archives/C05JYUT3CDP/p1700160676583849

zenoussi commented 9 months ago

Thank you very much, but as an integrator you don't understand what was done here to arrive at this result - a pity. Perhaps the functionality can be extended or the workaround can be explained in advance in the documentation?

Greetings

ri-klein commented 1 month ago

Hello, I recently came across basically the same problem as well. I first attempted to just use the ViteService in ext_localconf, but apparently it cannot be instantiated inside ext_localconf, as the core does not allow injecting the CacheManager at that time in the bootstrapping process. Instead, I came up with something similar to the approach already discussed in Slack:

Since we already have the VitePlaceholderProcessor for resolving %vite(...)%-placeholders in yaml files, my idea was to just use those placeholders in the $GLOBALS['TYPO3_CONF_VARS']['BE']['stylesheets'] array as well. A Middleware then lets the VitePlaceholderProcessor do the 'heavy lifting' in resolving the entry points, before the PageRenderer evaluates the stylesheet array.

My code basically looks like this:

// ext_localconf.php

$GLOBALS['TYPO3_CONF_VARS']['BE']['stylesheets']['some_identifier'] = "%vite('ENTRY_POINT_IDENTIFIER')%";
// Classes/Middleware/ProcessVitePlaceholdersInConfVars.php

class ProcessVitePlaceholdersInConfVars implements MiddlewareInterface
{
    protected ?VitePlaceholderProcessor $placeholderProcessor = null;

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        foreach($GLOBALS['TYPO3_CONF_VARS']['BE']['stylesheets'] as $key => $placeholder) {
            if (preg_match('/^%vite\((?<value>.*?)\)%$/', $placeholder, $matches) !== 1) {
                continue;
            }

            $placeholderProcessor = $this->getPlaceHolderProcessor();
            // The placeholder processor only needs the substring within '%vite(...)%', not the entire placeholder. We
            // still keep the placeholder syntax, so we can distinguish vite entrypoints from 'legitimate' CSS files in
            // the TYPO3_CONF_VARS array.
            $resolvedPath = $placeholderProcessor->process($matches['value'], []);
            // Strip leading slash, or else the path will not be interpreted as relative to webroot
            $GLOBALS['TYPO3_CONF_VARS']['BE']['stylesheets'][$key] = ltrim($resolvedPath, '/');
        }

        return $handler->handle($request);
    }

    // Use lazy instantiation here, since this middleware runs at every BE request.
    // So we should only instantiate the placeholder processor when we really need it.
    protected function getPlaceHolderProcessor(): VitePlaceholderProcessor
    {
        if ($this->placeholderProcessor === null) {
            $this->placeholderProcessor = GeneralUtility::makeInstance(VitePlaceholderProcessor::class);
        }

        return $this->placeholderProcessor;
    }
}
// Configuration/RequestMiddlewares.php

return [
    'backend' => [
        'vendor/name/process-vite-placeholders-in-conf-vars' => [
            'target' => \Vendor\Name\Middleware\ProcessVitePlaceholdersInConfVars::class,
            'before' => [
                'typo3/cms-core/response-propagation',
            ],
        ],
    ],
];

Some things to note:

Maybe this will help someone.