Tak redakční systém už něco umí. Sice je toho málo, jen administraci stránek, ale máme tam dost bordelu - tu složku bower_component duplicitně, v administračním prostředí spousta nesmyslných řádků v levém menu...
Čili je na čase uklidit. Taky je dobré myslet na optimalizaci rychlosti načítání. Čili naučíme se minimalizovat css a js zdroje a sloučit všechny do jednoho.
Začneme tedy smazáním těch položek menu v levém panelu administrace. Takže otevři @layout.latte a smaž následující bloky. Čili ne jen řádky, ale opravdu celé bloky:
<div class="navbar-custom-menu">
<div class="user-panel">
<form action="#" method="get" class="sidebar-form">
<ul class="sidebar-menu" data-widget="tree">
<aside class="control-sidebar control-sidebar-dark" style="display: none;">
Následně pak do elementu <section class="sidebar"> vlož seznam:
<ul class="sidebar-menu" data-widget="tree">
<li n:class="$presenter->isLinkCurrent(':Page:Admin:Page:default') ? active">
<a n:href=":Page:Admin:Page:default"><i class="fa fa-file"></i>
<span>Textové stránky</span></a>
</li>
</ul>
A teď větší legrace: minifikace a sjednocení css a js souborů. V tuto chvíli bychom museli vždy načítat všechny css a js zdroje i v případě, že je nebudeme v daném modulu používat. Máme prostě jednu šablonu layoutu, kde načítáme zdroje. Jestli v jednom z modulů budeme potřebovat třeba kalendář z Bootstrapu, museli bychom css a js prostě načíst i v případě zobrazení jiných modulů.
Řešením je komponenta, kterou si každý konkrétní presenter vytvoří a která načte jen potřebné zdroje. Opět tedy budeme vyrábět komponentu. Ve složce BaseModule/Components vyrob složku Css. V ní soubor ICssFactory.php:
<?php
namespace BaseModule\Components;
interface ICssFactory
{
/**
* @return Css
*/
public function create();
}
Pak třídu Css.php:
<?php
namespace BaseModule\Components;
use Nette\Application\UI\Control;
use WebLoader\Compiler;
use WebLoader\FileCollection;
use WebLoader\Filter\LessFilter;
use WebLoader\Nette\CssLoader;
/**
* Class Css
*
* @package BaseModule\Components;
*/
class Css extends Control
{
const WWW_DIR = __DIR__ . '/../../../../www/';
/** @var string */
private $media = 'screen'; //'screen,projection,tv,print'
/** @var array */
private $styles = [];
/** @var array */
private $remoteStyles = [];
/** @var string */
private $templateFile = __DIR__ . '/Css.latte';
public function __construct()
{
parent::__construct();
}
/**
* @param string $media
*/
public function setMedia($media)
{
$this->media= $media;
}
/**
* @param array $styles
*/
public function setStyles($styles)
{
$this->styles= $styles;
}
/**
* @param array $remoteStyles
*/
public function setRemoteStyles($remoteStyles)
{
$this->remoteStyles= $remoteStyles;
}
public function render()
{
$this->template->setFile($this->templateFile);
$this->template->render();
}
/**
* @return \WebLoader\Nette\CssLoader
* @throws \WebLoader\InvalidArgumentException
*/
protected function createComponentCss()
{
$files = new FileCollection(self::WWW_DIR . '/css');
$files->addFiles($this->styles);
$files->addRemoteFiles($this->remoteStyles);
$compiler = Compiler::createCssCompiler($files, self::WWW_DIR . '/css/webtemp');
$compiler->addFileFilter(new LessFilter());
$compiler->addFilter(
function ($code) {
$minifier = new \MatthiasMullie\Minify\CSS();
$minifier->add($code);
return $minifier->minify();
}
);
$control = new CssLoader($compiler, $this->template->basePath . '/css/webtemp');
$control->setMedia($this->media);
return $control;
}
}
A šablona Css.latte:
{control css}
Následuje registrace služby, takže do BaseModule/DI/services.neon přidej řádek:
- BaseModule\Components\ICssFactory
V BasePresenteru si službu injectneme, plus nastavíme pár cest:
/** @var ICssFactory @inject */
public $cssFactory;
/** @var string */
protected $bowerDir = __DIR__ . '/../../../../vendor/bower_components/';
/** @var string */
protected $srcDir = __DIR__ . '/../../../../src/';
A pak vyrobíme komponentu, ve které načteme všechny css soubory, které do teď načítáme v <head> šablony @layout.latte:
/**
* @return \BaseModule\Components\Css
*/
protected function createComponentCss()
{
$control = $this->cssFactory->create();
$control->setStyles(
[
$this->bowerDir . 'bootstrap/dist/css/bootstrap.min.css',
$this->bowerDir . 'font-awesome/css/font-awesome.min.css',
$this->bowerDir . 'Ionicons/css/ionicons.min.css',
$this->bowerDir . 'admin-lte/dist/css/AdminLTE.min.css',
$this->bowerDir . 'admin-lte/dist/css/skins/_all-skins.min.css',
$this->bowerDir . 'morris.js/morris.css',
$this->bowerDir . 'jvectormap/jquery-jvectormap.css',
$this->bowerDir . 'happy/dist/happy.css',
$this->bowerDir . 'ublaboo-datagrid/assets/datagrid.css',
$this->bowerDir . 'ublaboo-datagrid/assets/datagrid-spinners.css',
$this->bowerDir . 'nprogress/nprogress.css',
$this->srcDir . 'BaseModule/assets/css/admin/style.css',
]
);
$control->setRemoteStyles(
[
]
);
return $control;
}
V layoutu smaž všechny řádky, které načítají css soubory a vlož jen vytvořenou komponentu:
{control css}
Pokud bude potřeba, můžeš pak v různých presenterech přetížit metodu createComponentCss() a vložit vlastní css. Stejný trik provedeme se soubory js. Takže vytvoř složku Js a v ní soubor IJsFactory.php:
<?php
namespace BaseModule\Components;
interface IJsFactory
{
/**
* @return Js
*/
public function create();
}
Pak soubor Js.php:
<?php
namespace BaseModule\Components;
use Nette\Application\UI\Control;
use WebLoader\Compiler;
use WebLoader\FileCollection;
use WebLoader\Filter\LessFilter;
use WebLoader\Nette\JavaScriptLoader;
/**
* Class Js
*
* @package AppModule\Components;
*/
class Js extends Control
{
const WWW_DIR = __DIR__ . '/../../../../www/';
/** @var array */
private $scripts = [];
/** @var array */
private $remoteScripts = [];
/** @var string */
private $templateFile = __DIR__ . '/Js.latte';
public function __construct()
{
parent::__construct();
}
/**
* @param array $scripts
*/
public function setScripts($scripts)
{
$this->scripts= $scripts;
}
/**
* @param array $remoteScripts
*/
public function setRemoteScripts($remoteScripts)
{
$this->remoteScripts= $remoteScripts;
}
/**
* Method render
*/
public function render()
{
$this->template->setFile($this->templateFile);
$this->template->render();
}
/**
* @return \WebLoader\Nette\JavaScriptLoader
* @throws \WebLoader\InvalidArgumentException
*/
protected function createComponentJs()
{
$files = new FileCollection(self::WWW_DIR . '/js');
$files->addFiles($this->scripts);
$files->addRemoteFiles($this->remoteScripts);
$compiler = Compiler::createJsCompiler($files, self::WWW_DIR . '/js/webtemp');
$compiler->addFileFilter(new LessFilter());
$compiler->addFilter(
function ($code) {
$minifier = new \MatthiasMullie\Minify\JS();
$minifier->add($code);
return $minifier->minify();
}
);
$control = new JavaScriptLoader($compiler, $this->template->basePath . '/js/webtemp');
return $control;
}
}
A naposledy šablona Js.latte:
{control js}
Následuje registrace služby, takže do BaseModule/DI/services.neon přidej řádek:
- BaseModule\Components\IJsFactory
No a samozřejme do BasePresenteru injektáž služby:
/** @var \BaseModule\Components\IJsFactory @inject */
public $jsFactory;
a metodu pro vytvoření komponenty:
/**
* @return \BaseModule\Components\Js
*/
protected function createComponentJs()
{
$control = $this->jsFactory->create();
$control->setScripts(
[
$this->bowerDir . 'jquery/dist/jquery.min.js',
$this->bowerDir . 'jquery-ui/jquery-ui.min.js',
$this->bowerDir . 'nette.ajax.js/nette.ajax.js',
$this->bowerDir . 'jquery.cookie/jquery.cookie.js',
$this->bowerDir . 'bootstrap/dist/js/bootstrap.min.js',
$this->bowerDir . 'raphael/raphael.min.js',
$this->bowerDir . 'morris.js/morris.min.js',
$this->bowerDir . 'admin-lte/dist/js/adminlte.min.js',
$this->bowerDir . 'ublaboo-datagrid/assets/datagrid.js',
$this->bowerDir . 'ublaboo-datagrid/assets/datagrid-instant-url-refresh.js',
$this->bowerDir . 'ublaboo-datagrid/assets/datagrid-spinners.js',
$this->bowerDir . 'prism/prism.js',
$this->bowerDir . 'happy/dist/happy.js',
$this->bowerDir . 'nprogress/nprogress.js',
$this->bowerDir . 'nprogress/nette.nprogress.js',
]
);
$control->setRemoteScripts(
[
]
);
return $control;
}
No a zase smažeme všechny řádky na konci šablony, které načítají js soubory a nahradíme jen komponentou:
{control js}
Dost možná si budeš muset postahovat nějaké knihovny, pokud nebudou v bower_component. A taky se občas stane, že css nebo js mají v sobě odkazy na další zdroje, jako obrázky, fonty, další js soubory atd. To pak budeš muset pořešit vlastními silami - nahrát potřebné fonty do složky www/css/fonts apod.
Je na čase smazat celou složku www/bower_components. Už ji nebudeme potřebovat, protože si zdroje taháme ze složky src/bower_components. Na druhou stranu musíš vytvořit složky www/css/webtemp a www/js/webtemp. Do těchto složek se budou vytvářet a ukládat komprimované zdroje.
To je pro dnešek vše, a jako obvykle nabízím stažení celé aplikace. Dnes opravdu celé.