odan / twig-assets
Caching and compression for Twig assets (JavaScript and CSS).
Installs: 19 784
Dependents: 7
Suggesters: 0
Security: 0
Stars: 22
Watchers: 4
Forks: 6
Open Issues: 1
Requires
- php: 8.2.* || 8.3.*
- mrclay/jsmin-php: ^2.4
- symfony/cache: ^4.2.12 || ^5 || ^6 || ^7
- tubalmartin/cssmin: ^4.1
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3
- mikey179/vfsstream: ^1.6
- overtrue/phplint: ^3.0
- phpstan/phpstan: 1.*
- phpunit/phpunit: ^11
- squizlabs/php_codesniffer: ^3.5
- twig/twig: ^3.0
This package is auto-updated.
Last update: 2024-12-12 04:26:16 UTC
README
Caching and compression for Twig assets (JavaScript and CSS), inspired by Symfony Web Assets.
Installation
composer require odan/twig-assets
Requirements
- PHP 8.2, 8.3
- Twig 3
Configuration
$options = [ // Public assets cache directory 'path' => '/var/www/example.com/htdocs/public/assets/cache', // Public cache directory permissions (octal) // You need to prefix mode with a zero (0) // Use -1 to disable chmod 'path_chmod' => 0750, // The public url base path 'url_base_path' => 'assets/cache/', // Internal cache settings // // The main cache directory // Use '' (empty string) to disable the internal cache 'cache_path' => '/var/www/example.com/htdocs/temp', // Used as the subdirectory of the cache_path directory, // where cache items will be stored 'cache_name' => 'assets-cache', // The lifetime (in seconds) for cache items // With a value 0 causing items to be stored indefinitely 'cache_lifetime' => 0, // Enable JavaScript and CSS compression // 1 = on, 0 = off 'minify' => 1 ];
Integration
Register the Twig Extension
$loader = new \Twig\Loader\FilesystemLoader('/path/to/templates'); $twig = new \Twig\Environment($loader, array( 'cache' => '/path/to/compilation_cache', )); $twig->addExtension(new \Odan\Twig\TwigAssetsExtension($twig, $options));
Slim 4 Framework
Requirements
Run:
composer require slim/twig-view
Add these settings:
// Twig settings $settings['twig'] = [ 'path' => __DIR__ . '/../templates', // Should be set to true in production 'cache_enabled' => false, 'cache_path' => __DIR__ . '/../tmp/twig-cache', ]; // Twig assets cache $settings['assets'] = [ // Public assets cache directory 'path' => __DIR__ . '/../public/cache', // Public url base path 'url_base_path' => 'cache/', // Internal cache directory for the assets 'cache_path' => __DIR__ . '/tmp/twig-assets', 'cache_name' => 'assets-cache', // Should be set to 1 (enabled) in production 'minify' => 1, ];
Add a DI container definition.
This examples uses PHP-DI
<?php use Odan\Twig\TwigAssetsExtension; use Psr\Container\ContainerInterface; use Slim\App; use Slim\Factory\AppFactory; use Slim\Views\Twig; use Twig\Loader\FilesystemLoader; return [ // ... Twig::class => function (ContainerInterface $container) { $settings = $container->get('settings'); $twigSettings = $settings['twig']; $twig = Twig::create($twigSettings['path'], [ 'cache' => $twigSettings['cache_enabled'] ? $twigSettings['cache_path'] : false, ]); $loader = $twig->getLoader(); if ($loader instanceof FilesystemLoader) { $loader->addPath($settings['public'], 'public'); } $environment = $twig->getEnvironment(); // Add Twig extensions $twig->addExtension(new TwigAssetsExtension($environment, (array)$settings['assets'])); return $twig; }, ];
Add the TwigMiddleware
. In this case we pass the full
class name Twig::class
as the second parameter, because the
container entry is defined with the same name.
use Slim\Views\Twig; use Slim\Views\TwigMiddleware; // ... $app->add(TwigMiddleware::createFromContainer($app, Twig::class));
Add a route, e.g. in confg/routes.php
:
$app->get('/', \App\Action\Home\HomeAction::class)->setName('root');
Create a action class, e.g. src/Action/HomeAction.php
:
<?php namespace App\Action\Home; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Slim\Views\Twig; /** * Action. */ final class HomeAction { /** * @var Twig */ private $twig; /** * The constructor. * * @param Twig $twig The twig engine */ public function __construct(Twig $twig) { $this->twig = $twig; } public function __invoke(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface { return $this->twig->render($response, 'home/home.twig'); } }
The (pseudo) content of templates/home/home.twig
:
<html> <head> {{ assets({files: ['home/index.css']}) }} </head> <body> {{ assets({files: ['home/index.js']}) }} </body> </html>
Read more: Usage
Slim 3 Framework
Requirements
In your dependencies.php
or wherever you add your Service Factories:
$container[\Slim\Views\Twig::class] = function (Container $container) { $settings = $container->get('settings'); $viewPath = $settings['twig']['path']; $twig = new \Slim\Views\Twig($viewPath, [ 'cache' => $settings['twig']['cache_enabled'] ? $settings['twig']['cache_path']: false ]); /** @var \Twig\Loader\FilesystemLoader $loader */ $loader = $twig->getLoader(); $loader->addPath($settings['public'], 'public'); // Instantiate and add Slim specific extension $basePath = rtrim(str_ireplace('index.php', '', $container->get('request')->getUri()->getBasePath()), '/'); $twig->addExtension(new \Slim\Views\TwigExtension($container->get('router'), $basePath)); // Add the Assets extension to Twig $twig->addExtension(new \Odan\Twig\TwigAssetsExtension($twig->getEnvironment(), $settings['assets'])); return $twig; };
Usage
Custom template functions
This Twig extension exposes a custom assets()
function to your Twig templates. You can use this function to generate complete URLs to any Slim application assets.
Parameters
Template
Output cached and minified CSS content
{{ assets({files: ['Login/login.css']}) }}
Output cached and minified CSS content inline:
{{ assets({files: ['Login/login.css'], inline: true}) }}
Output multiple CSS assets into a single .css file:
{{ assets({files: [ '@public/css/default.css', '@public/css/print.css', 'User/user-edit.css' ], name: 'layout.css'}) }}
Output cached and minified JavaScript content
{{ assets({files: ['Login/login.js']}) }}
Output multiple JavaScript assets into a single .js file:
{{ assets({files: [ '@public/js/my-js-lib.js', '@public/js/notify.js', 'Layout/app.js' ], name: 'layout.js'}) }}
Output page specific assets
Content of file: layout.twig
<html> <head> {% block assets %}{% endblock %} </head> <body> {% block content %}{% endblock %} </body> </html>
Content of home.twig
:
{% extends "Layout/layout.twig" %} {% block assets %} {{ assets({files: ['Home/home.js'], name: 'home.js'}) }} {{ assets({files: ['Home/home.css'], name: 'home.css'}) }} {% endblock %} {% block content %} <div id="content" class="container"></div> {% endblock %}
Add custom attributes to the html element
WARNING: you can override ANY attribute including i.e. href
. Be careful here as it can cause unwanted results.
{{ assets({files: [ '@public/css/default.css', '@public/css/print.css', 'User/user-edit.css' ], attributes: { rel: 'preload', as: 'style', onload: 'this.onload=null;this.rel=\'stylesheet\'' }, name: 'layout.css'}) }}
Configure a base path
You should inform the browser where to find the web assets with a base href
in your layout template.
Slim Twig example:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <!-- other stuff --> <base href="{{ base_path() }}/"/> <!-- other stuff -->
Clearing the cache
Clearing the internal cache
use Odan\Twig\TwigAssetsCache; $settings = $container->get('settings'); // Internal twig cache path e.g. tmp/twig-cache $twigCachePath = $settings['twig']['cache_path']; $internalCache = new TwigAssetsCache($twigCachePath); $internalCache->clearCache();
Clearing the public cache
use Odan\Twig\TwigAssetsCache; $settings = $container->get('settings'); // Public assets cache directory e.g. 'public/cache' or 'public/assets' $publicAssetsCachePath = $settings['assets']['path']; $internalCache = new TwigAssetsCache($publicAssetsCachePath); $internalCache->clearCache();
Testing
composer test
Similar libraries
License
The MIT License (MIT). Please see License File for more information.