Jak vyvíjet komfotrněji?
Přesunuto na https://blog.nette.org/…-komfotrneji
Na navigaci | Klávesové zkratky
Přesunuto na https://blog.nette.org/…-komfotrneji
Víte, že nejpozději do 30. září 2015 máte povinnost získat souhlas uživatelů, pokud používáte na svém webu třeba Google AdSense? Proč, nač a jak na to?
Evropská unie přišla se zkurvenou směrnicí (tzv. sušenkovým zákonem), podle které musí uživatel webu dát souhlas s používáním cookies nebo obdobných mechanismů. Souhlas musí být také kurva odvolatelný.
Výjimkou jsou cookies, které jsou nezbytné pro poskytnutí služby, kterou si uživatel sám vyžádal, například cookie pro zkurvený nákupní košík. Naopak příkladem cookies, které nejsou nezbytně nutné, jsou cookie pro analýzu návštěvnosti, reklamní systémy nebo zkurvené pluginy sociálních sítí.
Česko zkurvenou evropskou směrnici implementovalo tak, že ji vlastně ignorovalo. Což se zkurveně nelíbí Úřadu pro ochranu osobních údajů, který se tím bude zabývat. Zatím tedy u nás není potřeba uživatele zkurveně žádat o souhlas, nicméně provozovatelé webů mají povinnost informovat o rozsahu a účelu jejich zpracování, například v podmínkách používání na svých stránkách. Uživatelé také musí mít možnost takové zpracování odmítnout, kurva fix.
Víte, že nejpozději do 30. září 2015 máte povinnost získat souhlas uživatelů, pokud používáte na svém webu třeba Google AdSense? Proč, nač a jak na to?
Evropská unie přišla se směrnicí (tzv. sušenkovým zákonem), podle které musí uživatel webu dát souhlas s používáním cookies nebo obdobných mechanismů. A souhlas musí být také odvolatelný.
Výjimkou jsou cookies, které jsou nezbytné pro poskytnutí služby, kterou si uživatel sám vyžádal, například cookie pro nákupní košík. Naopak příkladem cookies, které nejsou nezbytně nutné, jsou cookie pro analýzu návštěvnosti, reklamní systémy nebo pluginy sociálních sítí.
Česko evropskou směrnici implementovalo tak, že ji vlastně ignorovalo. Což se nelíbí Úřadu pro ochranu osobních údajů, který se tím bude zabývat. Zatím tedy u nás není potřeba uživatele žádat o souhlas, nicméně provozovatelé webů mají povinnost informovat o rozsahu a účelu jejich zpracování, například v podmínkách používání na svých stránkách. Uživatelé také musí mít možnost takové zpracování odmítnout.
A teď to podstatné: protože Google nerozlišuje, jak která země implementovala směrnici EU, jste v případě, že používáte jeho služby jako Google AdSense nebo Analytics s některou z inzertních funkcí (remarketing, demografické přehledy), povinni získat souhlas koncového uživatele. A to do 30. září 2015.
S tím, jak žádost o souhlas formulovat, vám poradí web www.cookiechoices.org. Záleží především na tom, k čemu cookie používáte. Kupříkladu na tomto webu používám AdSense a Analytics, takže jsem použil tuto formulaci:
Tento web používá k poskytování služeb, personalizaci reklam a analýze návštěvnosti soubory cookie. Používáním tohoto webu s tím souhlasíte.
Řeším tím povinnost dát uživateli možnost používání cookie odmítnout (tím, že web opustí) a také odvolatelnost souhlasu (tím, že web opustí).
A teď čistě technicky. Souhlas s používáním cookies si budu ukládat
do cookie nazvané např. eu-cookies
. Panel s žádostí vložím
do layoutu na konec stránky a zobrazím pouze pokud nebyl udělen. Příklad
pro Latte:
<div class="eu-cookies" n:if="empty($_COOKIE[eu-cookies])">
Tento web používá k poskytování služeb, personalizaci reklam a analýze
návštěvnosti soubory cookie. Používáním tohoto webu s tím souhlasíte.
<button>V pořádku</button>
<a href="https://www.google.com/policies/technologies/cookies/">Další informace</a>
</div>
<noscript><style>.eu-cookies { display:none }</style></noscript>
Panel mám napozicovaný fixně, aby byl stále vidět. Sice tak ukrajuje kus prostoru zejména na mobilních zařízeních, ale to nevadí, uživatel stejně nemůže web používat, pokud neprojeví souhlas. Příklad stylu:
.eu-cookies {
position: fixed;
left: 0;
top: 0;
width: 100%;
color: white;
background-color: black;
z-index: 1000;
}
.eu-cookies button {
background: green;
color: white;
}
A nakonec JavaScript, který po stisknutí tlačítka uloží souhlas do cookie (používám jQuery):
$('.eu-cookies button').click(function() {
var date = new Date();
date.setFullYear(date.getFullYear() + 10);
document.cookie = 'eu-cookies=1; path=/; expires=' + date.toGMTString();
$('.eu-cookies').hide();
});
Pokud používáte subdomény a cookie se má nastavit i pro ně, doplňte
za path=/;
ještě domain=.vasedomena.cz;
(a tečka na
začátku je důležitá).
Ještě poznámka: dokud souhlas nezískáte, neměla by vaše stránka obsahovat ani reklamu, ani měřící kódy.
Stránka by měla být čitelná ihned. Je velmi protivné, když si například v metru nemůžete přečíst článek jen kvůli tomu, že se nestihl načíst webový font.
Prohlížeče se totiž chovají tak, že text zobrazí až poté, co se font stáhne, aby zabránili tzv. Flash of Unstyled Text (FOUT), tedy nepříjemnému probliknutí jiného fontu. Problém je, že některé browsery nemají žádný timeout, po jehož uplynutí by se použil systémový font namísto žádného (tj. webového, ale nestaženého).
O tomhle tématu jsem psal už dříve a doporučoval pro mobilní zařízení webové fonty vůbec nepoužívat. Stejně krom autora grafiky to nikdy nepozná 🙂
Mobilům (nebo lépe řečeno zařízením do šířky 500px) můžeme ulevit tímto způsobem:
/* font stáhneme jen na větších zařízeních */
@import "https://fonts.googleapis.com/css?family=PT+Serif" screen and (min-width: 500px);
/* systémové písmo */
body {
font: 18px/1.7 Georgia, serif;
}
@media (min-width: 500px) {
body { /* webový font použijeme jen na větších zařízeních */
font-family: 'PT Serif', Georgia, serif;
}
}
Ale co ostatní prohlížeče? Natahování fontu skrze @import
vypadá elegantně, ale blokuje zpracování CSS a to zase blokuje vykreslení
stránky. Jde tedy o nejhorší možné řešení. Jak se zbavit blokování a
zajistit timeout?
Timeout lze emulovat pomocí JavaScriptu. Jenže zjistit, že se font načetl, není nic triviálního, dělá se to pomocí triků, jako je třeba detekce změny šířky předpřipraveného text atd. Font Loading API zatím podporuje jen Chrome. Takže lepší bude použít hotové řešení, jako je například Web Font Loader.
Knihovnu Web Font Loader vyvíjí Google společně s Typekit. Nedávno o ní psal Aleš Roubíček, takže na něj navážu a pokusím se upravit řešení tak, aby se skript načítal asynchronně a neblokoval stránku.
Do hlavičky stránky (!) vložte tento kód, kterým asynchronně načtete Web Font Loader a také font:
<script>
WebFontConfig = {
google: { families: ['PT+Serif:400:latin,latin-ext'] }
};
</script>
<script src="https://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js" async defer></script>
Web Font Loader umí detekovat stavy, kdy se font načítá a kdy už je
načtený, a to pomocí událostí nebo nastavováním tříd elementu
<html>
. Jakmile je font načtený, nastaví třídu
wf-active
. Zároveň řeší timeout.
Upravíme styl tak, aby se webový font použil až ve chvíli, kdy bude načtený, a nahradil tak systémové písmo.
/* systémové písmo */
body {
font: 18px/1.7 Georgia, serif;
}
/* písmo po načtení fontu */
html.wf-active body {
font-family: 'PT Serif', Georgia, serif;
}
Tohle řešení má ale potíž. Bude docházet k FOUT, tedy k probliknutí systémového fontu. Při prvním načtení stránky, kdy webový font ještě není v cache prohlížeče, může probliknutí trvat sekundu či déle, při každém dalším zobrazení krátký okamžik. A to vypadá velmi ošklivě.
Proto během načítání písmo skryjeme, tak jak to dělají prohlížeče standardně, bez loaderu.
html.wf-loading * {
color: transparent !important;
}
Dále třídu wf-loading
nastavíme ihned, nelze čekat, až se
Web Font Loader načte. Ale zároveň ji musíme odstranit, když načtení
loaderu selže. Výsledný kód vypadá takto:
<script>
WebFontConfig = {
google: { families: ['PT+Serif:400:latin,latin-ext'] }
};
var el = document.documentElement;
el.className += ' wf-loading';
setTimeout(function() {
el.className = el.className.replace(/(^|\s)wf-loading(\s|$)/g, ' ');
}, 1000); // 1 second
</script>
<script src="https://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js" async defer></script>
Pokud je font v cache, stránka se ihned zobrazí se správným písmem bez probliknutí. Pokud v cache není, text nejprve nebude vidět a pokud se do vteřiny nepodaří font stáhnout, zobrazí se systémovým písmem a po stažení se přepne na webové písmo. Tedy při rychlém stažení k probliknutí vůbec nedojde a při pomalém ano, ale uživatel nebude koukat na prázdnou stránku.
Samozřejmě časovou prodlevu můžete dle libosti snížit.
Doplnění: s alternativním řešením přišel Petr Soukup.
Po načtení fontu si do prohlížeče uloží cookie wfont
,
která později bude značit, že font by měl být už v cache
prohlížeče:
<html>
<script>
WebFontConfig = {
google: { families: ['PT+Serif:400:latin,latin-ext'] },
active: function() { document.cookie ='wfont=1; expires='+(new Date(new Date().getTime() + 86400000)).toGMTString()+'; path=/' }
};
</script>
A při dalším načtení stránky, pokud tato cookie existuje, generuje trošku jiný kód, kde není Web Font Loader, ale:
<html class="wf-active">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=PT+Serif">
Tedy webový font se použije rovnou a načítá se bez JavaScriptu, nedochází tedy k žádnému probliknutí.
A tip nakonec: aby prohlížeč mohl započít načítání fontu hodně brzy, vlastně ještě před normálním zpracováváním stránky, mu lze poradit pomocí prefetch:
<link rel="prefetch" href="https://fonts.googleapis.com/css?family=PT+Serif">
Implementace v Latte by mohla vypadat třeba takto:
{var $wfont = isset($_COOKIE[wfont])}
<html n:class="$wfont ? wf-active">
<script n:syntax=off n:if=!$wfont>
WebFontConfig = {
google: { families: ['PT+Serif:400:latin,latin-ext'] },
active: function() { document.cookie ='wfont=1; expires='+(new Date(new Date().getTime() + 86400000)).toGMTString()+'; path=/' }
};
</script>
<script src="https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js" async defer n:if=!$wfont></script>
<link rel="{$wfont ? stylesheet : prefetch}" href="https://fonts.googleapis.com/css?family=PT+Serif">
Ukáži vám, jak zrychlit načítání Google Analytics nebo Web Loaderu a ještě zjednodušit měřící kód.
Tímto kódem vložíme do stránky měřící bod Google Analytics:
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXX-XX', 'auto');
ga('send', 'pageview');
</script>
Když si ho odtemníme, vypadá takto:
<script>
(function() {
window['GoogleAnalyticsObject'] = 'ga';
window['ga'] = window['ga'] || function() {
(window['ga'].q = window['ga'].q || []).push(arguments)
}, window['ga'].l = 1 * new Date();
var script = document.createElement('script'),
firstScript = document.getElementsByTagName('script')[0];
script.async = 1;
script.src = '//www.google-analytics.com/analytics.js';
firstScript.parentNode.insertBefore(script, firstScript)
})();
ga('create', 'UA-XXXXX-XX', 'auto');
ga('send', 'pageview');
</script>
Řádek window['GoogleAnalyticsObject'] = 'ga'
říká, že
objekt Google Analytics bude uložen v globální proměnné ga
,
nicméně je zbytečný, protože ga
je výchozí hodnota.
Dále následuje vytvoření objektu v proměnné ga
, který
představuje jen dočasný zásobník, kam se ukládá sekvence volání
jednotlivých příkazů, a po načtení skriptu bude nahrazen skutečným
objektem Google Analytics. Uvedený kód se dá výrazně zjednodušit
vypuštěním window
a pokud na stránce není víc měřících
kódu, můžeme zrušit i podmínky ga = ga || ...
a dostáváme
se k jednoduchému:
ga = function() { ga.q.push(arguments) };
ga.q = [];
ga.l = +new Date;
Dále následuje vytvoření elementu <script>
a jeho
vložení do stránky. Nastavení script.async = 1
je zbytečné,
protože podle HTML specifikace je každý skriptem vkládaný
<script>
asynchronní.
Nicméně – neexistuje žádný důvod, proč element
<script>
vytvářet JavaScriptem. Je mnohem výhodnější
použít normální HTML. Stránka se díky tomu
načte rychleji, nedochází k blokování a může se využít preload
scanner v moderních prohlížečích. Tím se dostáváme k této
podobě:
<script>
ga = function() { ga.q.push(arguments) };
ga.q = [];
ga.l = +new Date;
ga('create', 'UA-XXXXX-XX','auto');
ga('send','pageview');
</script>
<script src="//www.google-analytics.com/analytics.js" async></script>
Aby se kód načítal asynchronně i v prohlížečích IE 5.5 – 9, je
nutné kromě atributu async
přidat ještě
defer
.
V dnešní době se relativní URL //www.google-analytics.com
dá považovat za antipattern,
vhodnější je vždy používat https.
Konečná podoba včetně minifikace vypadá takto:
<script>
ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;
ga('create','UA-XXXXX-XX','auto');ga('send','pageview');
</script>
<script src="https://www.google-analytics.com/analytics.js" async defer></script>
Rychlejší, kratší a ještě navíc hezčí. Nechť slouží 🙂
Podobným způsobem je vhodné načítat i Web Font Loader, tj. místo v dokumentaci uvedeného
<script>
WebFontConfig = {
typekit: { id: 'xxxxxx' }
};
(function(d) {
var wf = d.createElement('script'), s = d.scripts[0];
wf.src = 'https://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js';
s.parentNode.insertBefore(wf, s);
})(document);
</script>
používejte
<script>
WebFontConfig = {
typekit: { id: 'xxxxxx' }
};
</script>
<script src="https://ajax.googleapis.com/ajax/libs/webfont/1.5.18/webfont.js" async defer></script>
Protože adresa skriptu se v kódu Tag Manageru skládá, uvedenou optimalizaci nelze bohužel použít.
Chrome 44 (beta) odesílá nově hlavičku HTTPS: 1, která může způsobovat problémy.
Na některých hostinzích (z těch co používám třeba
WebSupport už to opravili) si pak PHP myslí, že požadavek je pod
šifrovaným spojením HTTPS. Tj. proměnná
$_SERVER['HTTPS'] === 'on'
.
U aplikací v Nette, které neběží pod https, to pak způsobí
nekonečný redirect. Aplikace si prostě myslí, že k ní přistupujete přes
URL https://example.com
a přesměrovává na
http://example.com
.
Můžete to vyzkoušet z příkazové řádky pomocí:
curl -I --header "HTTPS: 1" http://example.com`
Že je hlavička HTTPS: 1
problematická se
už ví, takže je možné, že se změní a do Chrome nedostane.
Každopádně jako rychlý workaround, aby nedocházelo ke smyčce
přesměrování v betaverzi Chrome, je přidat na začátek bootstrap.php:
unset($_SERVER['HTTPS']);
Zároveň je dobré si uvědomit, že na některých hostinzích lze detekci šifrovaného spojení velmi snadno ošálit.
Doplnění: Chrome 45 už hlavičku HTTPS: 1 neodesílá.
PHP 5.3 je stále nejpoužívanější verzí PHP. Nicméně jde o verzi nepodporovanou, nevycházejí už ani záplaty na závažné bezpečnostní díry. Podle trendů se zdá, že verze 5.4 by ji mohla vystřídat po prázdninách. Ironií je, že v ten moment i jí skončí podpora.
Jisté je, že v době vydání další verze Nette bude PHP 5.3 dávno passé, tudíž jsem v masteru změnil minimální požadovanou verzi z PHP 5.3.1 na PHP 5.4.4.
Právě tohle setinkové číslo jsem zvolil s ohledem na Debian 7.0 Wheezy.
Opuštění větve 5.3 znamenalo řadu spíš kosmetických změn (DI, Tracy), odstranění drobného počtu workaroundů (magic quotes u Http, Reflection, Utils) a výjimečně i užití nových tříd (Finder nebo Component-Model). Což potvrzuje, že verze PHP 5.3 byla skutečně hodně dobrá.
PHP 5.4 zároveň skýtá nové možnosti, první implementovanou byla
žádaná serializace objektu DateTime do
JSON. Dále se nabízí možnost nahradit Nette\Object
za
trait atd.
Na co jsem se ale hodně těšil byla normální syntax pro zápis polí
pomocí []
namísto šíleného array()
. A také
možnost používat v šablonách <?=
místo dlouhého
<?php echo
.
S jejich nasazením v masteru jsem ale váhal, protože by to udělalo z cherry-pickování do starších větví peklo. Nicméně verze Nette 2.1 a od května i 2.2 jsou ve stádiu, kdy se opravují jen závažné chyby, které se v Nette objevují jen zřídkakdy, a v aktuální verzi 2.3 se nové komity objevují jen svátečně, tudíž jsem si řekl, že netřeba to odkládat a všechny repozitáře převedl na hezčí syntax.
(Rebasování větví byl docela oříšek, rozepsal jsem se o tom včera. Takový převod tabulátorů na mezery by musel být hotové peklo.)
Nástroj Code Checker nyní kontroluje, aby se v repozitářích používala výhradně nová syntax a nedocházelo k míchání obou zápisů polí.
Přechod na PHP 5.5 by přinesl taky jednu byť drobnou syntaktickou změnu:
konstantu
::class. A mohly by se použít nové funkce v
Nette\Utils\Image
a případně
Nette\Security\Password
, typ DateTime
by se
v typehintech nahradil za DateTimeInterface.
Přechod na PHP 5.6 by přinesl zejména nahrazení většiny
func_get_args()
& call_user_func_array()
za trojtečky
(včetně operátoru (expand)
v Latte). V pár případech by se
dalo využít i konstant obsahujících pole.
A přechod na PHP 7 by byla revoluce.
Jak jsem v projektech, které používají PHP 5.4 a
vyšší, převáděl starou syntaxi pro zápis polí array()
na
novou []
.
Samotný převod PHP souborů je úplně jednoduchý. Stačí použít PHP 5.4 Short Arrays Converter a v repozitáři zavolat:
php /php54-arrays/convert.php .
Nástroj zamění syntax ve všech souborech *.php
a
*.phpt
v aktuálním adresáři a také ve všech
podadresářích. Změněné soubory jsem pak komitnul (příklad).
Oříšek je ale rebasování dalších větví na takto změněný master.
Nakonec jsem na to šel přes filtry. Ale plně zautomatizovat se mi to nepovedlo.
Nejprve je vhodné všechny větve rebasovat na master těsně před samotnou změnou syntaxe.
Poté jsem si vytvořil filtr nazvaný phparray
, který bude
on-the-fly překládat v PHP souborech []
na array()
při checkoutu a obráceně při komitování. Tedy aby slučování probíhalo
při použití staré syntaxe, ale komitnulo se s novou.
Filtr se vytvoří v souboru .git/config
, v mém případě to
vypadalo takto:
[filter "phparray"] clean = c:/php/php.exe w:/php54-arrays/convert.php smudge = c:/php/php.exe w:/php54-arrays/convert.php -r required
Aby se filtr při slučování používal (ale i při každém checkoutu,
cherry-picku atd), je nutné doplnit do .git/config
ještě
následující:
[merge] renormalize = true
Filtr se bude aplikovat na soubory *.php
a *.phpt
,
což se definuje v souboru .git/info/attributes
(nepoužívejte
.gitattributes
, protože jde o dočasnou záležitost a nechceme
ji komitovat):
*.php filter=phparray *.phpt filter=phparray
Teď by ve větvi mělo fungovat git rebase master
. Bez
konfliktů, které by bylo nutné ručně řešit. Jenže ouha, konflikty se mi
vytvářely (na Windows; je možné, že na Linuxu to půjde) a když jsem je
chtěl řešit v TortoiseGit, objevovala se hláška, že na souboru
.git/index.lock
je zámek atd. Zkoušel jsem experimentovat
s dalšími nastaveními pro merge, ale bez výsledku.
Zkusil jsem dělat rebase ručně: což znamená nejprve větev resetnout na
master (git reset master --hard
) a pak jednotlivé komity
přidávat pomocí git cherry-pick <hash>
. Nedělal jsem to
z příkazové řádky, ale pomocí TortoiseGit. I nadále mi hlásil, že
některé soubory neumí automaticky sloučit a je vyžadován ruční zásah,
ale vždy stačilo soubor rozkliknout do TortoiseGitMerge a rovnou stisknout
Mark as resolved.
Bylo to otravné, ale fungovalo to a postupně jsem „rebasoval“ všechny
větve. Poté jsem filtr z .git/config
a
.git/info/attributes
smazal.
Proč to nešlo úplně automaticky, nemám páru, nicméně bylo snazší hodinu klikat, než dva dny studovat Git.
Způsob, jak se vyvíjejí aplikace v PHP, se v posledních 5 letech dramaticky proměnil. Nejprve jsme opouštěli čisté PHP a učili se používat frameworky, později přišel Composer a s ním instalace knihoven z příkazové řádky a nyní nastává konec frameworků, jak je známe.
Monolitické frameworky se postupně rozpadají do samostatných (decoupled) komponent. A to přináší řadu výhod. Zatímco dříve bylo použití jen jedné části frameworku obtížné až nemožné, dnes si prostě nainstalujete jeho komponentu. Vývojový cyklus jednotlivých komponent může mít různé tempo. Mají vlastní repozitáře, issue trackery, mohou mít vlastní vývojářské týmy.
Komponenty můžete aktualizovat na nové verze průběžně, bez čekání, než vyjde další verze celého frameworku. Nebo naopak se můžete rozhodnout určitou komponentu neaktualizovat, třeba kvůli BC breaku.
Význam slova framework se tak posouvá, o verzích už takřka nelze hovořit. Místo frameworku XYZ ve verzi 2.3.1 používáte sadu komponent v různých verzích, které spolu fungují.
Rozdělení frameworku na komponenty je dost složité. Nette to trvalo 2 roky a hotovo bylo loni. Naprostou nutností bylo prosazení se Composeru a také důsledné používání dependency injection. Nette dnes tvoří přes 20 samostatných repozitářů a v tom původním zbyla jen jediná třída.
Všechny významné frameworky, jako Symfony, Zend, Laravel nebo CakePHP, jsou rozčleněné do komponent, byť k dotažení chybí ještě jeden krok: rozdělení do samostatných repozitářů (namísto náhražky v podobě Git subtree split). Zend slibuje, že s tím přijde ve verzi 2.5, uvidíme, co Symfony.
Dlouhým úvodem jsem se vás snažil přivést na myšlenku, že dívat se na Nette jako na framework v nějaké konkrétní verzi je překonané. Že šikovnější je k němu přistupovat jako k sadě komponent.
Tj. namísto uvádění závislosti na nette/nette
uvádět
závislosti na konkrétních komponentách. Tak to nyní dělá
i Sandbox. Jako základ budoucí aplikace může posloužit i Nette Web Project, což je
úplně minimalistická obdoba Sandboxu. Stáhněte jej pomocí
composer create-project nette/web-project
a vyhoďte z composer.json
komponenty, které nepotřebujete.
Zrychlíte tak operace Composeru.
Rychleji se k vám dostanou i bugfixy. Po opravení chyby lze hned u příslušné komponenty tagnout novou verzi, zatímco cyklus uvolňování verzí celého frameworku je mnohem pomalejší.
Pokud tvoříte doplňky pro Nette, tak vůbec neváhejte a hned nahraďte
závislost na nette/nette
výčtem skutečně požadovaných
komponent.
Samozřejmě i nadále budou vycházet nové verze frameworku jako doposud,
bude fungovat require nette/nette
a pro verzi 2.3 budou vycházet
i distribuce v archivech ZIP. Ale jejich význam bude pomalu upadat.
Nette se v anketě Best PHP Framework for 2015 pořádané magazínem SitePoint umístilo na úžasném 3. místě. Moc děkuji všem za hlasy, tak skvělý výsledek jsem opravdu nečekal.
Těší mě na tom, že uživatelé jsou s Nette nejspíš spokojení, jinak by asi hlasy neposílali. A také samozřejmě fakt, že Nette tím na sebe upozornilo ve světě, kde se o něm kvůli jazykové bariéře tolik neví.
Na výsledcích je zajímavé i to, že si člověk uvědomí, jak velké množství PHP frameworků se reálně používá, že existují i další populární „lokální frameworky“ a že je tu stále dost těch, kteří žádný framework nepoužívají.