SlideShare una empresa de Scribd logo
1 de 20
Descargar para leer sin conexión
Cesta k Webpacku
Skrz DEV Cirkus
10.6.2015
V Node.JS na server-side existuje jednoduchý způsob, jak začít používat cizí knihovny - `npm install …` a
poté stačí napsat `require(“…”)`. Pokud jde o browser, už to tak jednoduché není. a) Žádný standardní
způsob není. b) “assety” před tím, než se pošlou do prohlížeče je potřeba minifikovat (odstranit bílé
znaky, komentáře, zkrátit názvy proměnných). c) A nakonec optimalizovat pro posílání přes HTTP (spojit
soubory dohromady), upravit názvy, aby podporovaly dobré kešování apod. V této prezentaci probereme,
jak jsme ve Skrzu došli k Webpacku.
Co je Skrz? Skrz je katalog akčního zboží, takový online akční
leták. Musí poskytovat skvělou user experience pro své uživatele,
tudíž se řeší nejrůznější Javascriptové vychytávky, animace,
AJAXová volání. Ale zároveň musí být obsah dostupný pro
vyhledávače - tzn. že renderovaní se musí řešit na serveru.
-1.5 roku
Posuňme se v čase do ledna 2014…
Takhle nějak vypadal Javascriptový kód. Moc a moc úrovní odsazení, drlouhá jQuery
špageta. Jestli uživatel je/není na nějaké stránce se neřešilo, vždycky se posílal stejný
Javascript, který obsahoval vše - rozlišení, jestli se nějaký kód má, nebo nemá aplikovat
na dané stránce se řešilo přes různé ověřování, jestli existují elementy pro všechny
selektory, které daná fcionalita potřebovala = hromada ifů. Výsledkem bylo dlouhé
načítání, špatný výkon.
Takhle nějak vypadalo řešení knihoven a závislostí. Podobně to asi někdy řešil každý. Na produkci
se akorát zapla proměná `settings.user_compile_js`.

Minifikaci a spojování Javascriptových souborů řešila vlastní skript v PHP - tzv. packer. Tomu se v
packer.conf souboru určilo, co všechno za soubory má projít a jak je má spojit. Často je spojil
špatně, vyhodil znaky, které neměl apod. - takže až na produkci se zjistilo, že kód nefunguje.
-1 rok
LiveScript + LESS + AMD
Grunt + Require.JS
Březen až květen 2014 se řešil redesign Skrzu. Ještě důležitější než nový kabátek to ale znamenalo přepis hodně
stránek a nové technologie. Místo home-made frameworku Ulriky se začala na backendu používat Symfony. Většina
stránek začala brát data z Elasticsearch místo MySQL. A na client-side místo čistého Javascriptu se začal používat
LiveScript, místo čistého CSS zase LESS. Nejdůležitější však bylo strukturování LiveSciptu do AMD (asynchronous
module definition) - což dalo dobře základ škálovatelnému řešení rozdělení závilostí. Celé to spojoval Grunt a
Require.JS.
NO-FRAMEWORK
framework
aka vlastní řešení
Jak jsem říkal, jako požitek pro uživatele je pro Skrz důležitá přístupnost pro roboty - tzn. renderování musí probíhat
na serveru. V době redesignu byly v Javascriptu nejpoužívanější frameworky Backbone a Angular. Oba se snažily řešit
renderování na klientu a podpora pro renderování na serveru bylo nedostatečná. A pokud se odmyslelo renderování
na klientu, přidávaly pramálo užitečného pro strukturování aplikace - neřešili problém, který jsme měli ve Skrzu. My
pouze potřebujeme vyrenderované HTML na serveru “rozhýbat” na klientu, sem tam načíst něco AJAXem. Vznikl tedy
vlastní způsob, jak stránku rozděli na komponenty a jak je zaregistrovat a napojit na ně Javascript.
V aplikaci je jeden entry point - main.ls (tečka LS protože LiveScript). V elementu s ID
js-options je serializovaný JSON s proměnnými týkajících se celé stránky předaných z
backendu. Obsahuje např. ID uživatele. V Javascriptu používáme dependency
injection container. V této ukázce je to LillyContainer (Lilly je název jedné z aplikací).
Ten se předá aplikaci a pak se aplikaci prožene fronta událostí, které do té doby na
stránce vznikly.
Dependency injection container obsahuje metody s prefixem “get” a
“create”. “get” metody znamenají, že daná instance je singleton - bude
vytvořena pouze jednou za celý běh aplikace. “create” metody jsou
továrničky. Nejvíce pro tzv. “widgety” - to jsou právě jednotlivé části, na
které je stránka rozdělená.
Na začátku každé stránky (hned po otevíracím tagu <body>) se inicializuje kód fronty
událostí. Něco jako mají trackovací kódy Google Analytics (_gaq), Facebooku (_fbq).
Cílem (ke kterému jsme se bohužel ještě nedostali), je mít jeden `<script … async>` v
hlavičce, eventy tedy hned po načtení části stránky mohou hned napárovat
Javascriptovvý widget (který se stará o interakci) na naparsovaný DOM element.
Události jsou prostě kusy Javascriptu přímo v HTML, které zavolají vždy nějakou metodu na globalním
objektu `skrz`. Nejdůležitější/nejpoužívanější je událost/metoda `skrz.widget(…)`. Jako první argument
má název widgetu (přilepte na začátek “create” a na konec “Widget” a máte název metody z
dependency injection kontejneru) a jako druhý argument model v JSONu. Mohli jste si všimnout, že v
kontejneru mají ještě widget-továrničky parametr `el`. To je odkaz na parent DOM element, ve kterém je
volání `skrz.widget` (ten se odvodí auto-magicky díky způsobu, jakým prohlížeče zpracovávají DOM).
Wiget je třída, v konstruktoru dostane tři argumenty `el`, `model` a `children`.
`el` je element, ve kterém byla vyvolána eventa `skrz.widget`. `model` je
druhý argument předaný události. Např. máme `ItemWidget` a ten má v
model ID nabídky. Widgety tvoří strom, podobně jako DOM tvoří strom.
`children` jsou widgety podřazené současnému.

Lifecycle widgetu je jednoduchý - po vytvoření kontejnerem se zavolá
metoda `bind`. Ta se stará o interaktivitu. Najde si různé elementy. Máme
konvenci, že elementy používané z Javascriptu musí mít třídu s prefixem `j-
*`.

Opakem `bind` je `unbind`, která se zavolá, pokud je widget odstraňován.

Widgety tvoří zapouzdřené celky, které se jednoduše upravují. Starají se
pouze přidání interaktivity nad HTML renderované na serveru.
-0.9972 roku
Require.JS
Widgety byly super a rozdělení do více souborů jakbysmet. Ale asi za
1 den, když se mělo natáhnout třeba 30 souborů s 30 různými
widgety, jsme narazili na problém s připojením k internetu v
předchozích kancelářích Skrzu na Bohdalci - prostě se nestáhl jeden
z 30 souborů a najednou tu byl těžko debugovatelný problém.
Vykašlali jsme se tedy na Require.JS…
…a místo něj se inspirovali Stichem (https://github.com/
sstephenson/stitch), což je Node.JS middleware, který spojí X
JS souborů dohromady. Přepsali jsme řešení do PHP a
donedávna úspěšně používali.

Mělo to však několik problémů:

a) Stitch nechápal Javascript, pouze vzal soubory v adresáři,
dal kolem každého boilerplate a spojil je dohromady.
Výsledkem bylo mnoho opakujících se řetězců s názvem
modulu, a tdy zbytečně velká velikost souboru.

b) Řešil pouze Javascript (resp. LiveScript), na LESS jsme
používali stále Grunt tasky.
-3 měsíce
Webpack
S velkou popularitou a množstvím přednášek ohledně ReactJS, jsem narazil
na přednášku od Pete Hunta, který ve Facebooku řeší Instagram webový
frontend.

Facebook používá k minifikaci, modularizaci a servírování Javascriptu
adaptabilní a prediktivní řešení. Je ale hodně provázané s celým zbytkem
Facebooku. Pro Instagram potřebovali něco daleko jednoduššího, co by
mohli rychle nasadit. A našli Webpack.
Google ->
“pete hunt webpack
howto”
Zadejte do Google “pete hunt webpack howto” = nejjednodušší způsob,
jak s Webpackem začít. A taky, jak jsme začali my.
package.json:
{

"name": "Lilly",

"version": "1.0.0",

"devDependencies": {

"webpack-dev-server": "^1.7.0",

"webpack": "^1.7.3"

},

"dependencies": {

"LiveScript": "^1.3.1",

"bootstrap": "^3.3.2",

"bootstrap-webpack": "0.0.3",

"css-loader": "^0.9.1",

"expose-loader": "^0.6.0",

"extract-text-webpack-plugin": "^0.3.8",

"file-loader": "^0.8.1",

"font-awesome": "^4.3.0",

"font-awesome-webpack": "gowravshekar/font-awesome-webpack#e22214a",

"imports-loader": "^0.6.3",

"jquery": "^1.11.2",

"less": "^2.0.0",

"less-loader": "^2.0.0",

"livescript-loader": "^0.1.3",

"source-map-loader": "^0.1.3",

"style-loader": "^0.8.3",

"uglify-js": "^2.4.16",

"url-loader": "^0.5.5",

"webpack": "^1.5.3"

},

"scripts": {

"dev": "BUILD_DEV=true webpack-dev-server -d --hot --inline --progress --colors --port 8443 --inline --https --content-base is/ --
output-public-path https://localhost:8443/assets/",

"build": "npm run build:queue && webpack -p --progress --profile --colors",

"clean": "rm -f www/assets/*",

"build:queue": "lsc --compile --bare --print client-src/Skrz/Inlined/queue.ls | uglifyjs --compress --mangle > client-src/Skrz/Inlined/
queue.js"

}

}

V praxi to vypadá následovně: v
package.json máme natažené všechny
potřebné závislosti.

A pak už 2 důležité scripty:

a) `dev` spustí Webpack dev server -
NodeJS server, který poslouchá na
určitém portu. Umí livereload stránky
při změně a další vychytávky.
Nebuďte líní, pokud budete s
webpackem začínat, si dev server
nastavit.

b) `build` spojuje a minifikuje soubory
pro použití na produkci. V případě
skrzu to trvá několik minut, ale
výsledek je skvělý.

Že je pro nás webpack tak skvělý je
hlavně díky rozhodnutí strukturovat kód
pomocí AMD modulů. Ale stejně tak
webpack podporuje synchronní `require`
jako je v Node.JS a další způsoby.
webpack.config.js:
var webpack = require("webpack");

var ExtractTextPlugin = require("extract-text-webpack-plugin");



module.exports = {

entry: {

all: ["./client-src/Skrz/Bundle/LillyBundle/main"]

},

output: {

path: "./www/assets",

publicPath: "/assets/",

filename: "all.js"

},

module: {

loaders: [

{ test: /bootstrap/js//,

loader: ‘imports?jQuery=jquery' },

{ test: /.ls/,

loader: “livescript-loader" },

{ test: /.css$/,

loader: ExtractTextPlugin.extract("style-loader", “css-loader") },

{ test: /.less$/,

loader: ExtractTextPlugin.extract("style-loader", “css-loader!less-loader") },

{ test: /.(woff2?|ttf|eot|svg|jpg|png|gif|swf)(?.*)?$/,

loader: “file-loader" }

]

},

resolve: {

extensions: ["", ".js", ".json", ".ls"]

},

plugins: [

new webpack.DefinePlugin({

__DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || "true"))

}),

new ExtractTextPlugin("[name].css")

]



};

Webpack se nastaví přes `webpack.config.js`. Důležitá je sekce loaders,
kde podle přípony souboru nastavíte, co v tom souboru je. Např. tady
soubory končící na `.ls` se interpretují jako LiveScript. Soubory končící na
`.less` jako LESS = ano, uděláte v Javacriptu `require(“./style.less”)` a
webpack soubor přeloží do CSS, všechny CSS pak posbírá
ExtractTextPlugin (viz sekce plugins) a vytvoří jeden CSS soubory se vším.

Zahodili jsme tedy Grunt a o všechno se teď stará webpack.

Ten navíc např. fonty referencované v CSS, obrázky uloží do souboru,
který má jako název MD5 hash obsahu a nahradí všechny výskyty v CSS -
můžete tedy nastavit na fonty/obrázky kešování forever, a pokud se
změní, vznikne nový soubor, a tím pádem se invaliduje keš.
<head>:
<link rel="stylesheet" href="{$assetsBaseUrl}/all.css">
za <body>:
<script>{$queue nofilter}</script>

<script>skrz.begin();</script>
před </body>:
<script>skrz.end();</script>

<script>skrz.widget("Body");</script>

<script type="application/json" id=“js-options”>{$options|json_encode nofilter}</script>

<script src="{$assetsBaseUrl}/all.js"></script>
Pak už jsem stačí nastavit `$assetsBaseUrl`
v šabloně podle toho, jestli se jedná o vývoj
nebo produkci.
Otázky?
Díky!
Jedna otázek byla: “Proč použít Webpack a nepoužít Gulp?”

A proč nepoužít obojí! Každá věc je totiž na něco jiného. Webpack se stará o
přípravu “assetů” pro development/produkci. Gulp je task runner. Jedním z těch
tasků může být např. spuštění Webpacku pro development nebo vybuildovaní
assetů pro produkci.

My jsme Gulp jako task runner nepotřebovali, protože většinu tasků máme v PHP, v
Javascriptu máme pouze ty, které byly vidět v `package.json` na jednom z
předchozím slajdů. `npm run …` nám na to úplně stačí.

Más contenido relacionado

Destacado

Fonds Commercial
Fonds CommercialFonds Commercial
Fonds CommercialImane SBAI
 
SamanthaGottusoResume0516.pdf
SamanthaGottusoResume0516.pdfSamanthaGottusoResume0516.pdf
SamanthaGottusoResume0516.pdfSamantha Gottuso
 
cours de construction Généralités
cours de construction Généralitéscours de construction Généralités
cours de construction GénéralitésSami Sahli
 
Fiche thecnique pos7 boufarik
Fiche thecnique pos7 boufarikFiche thecnique pos7 boufarik
Fiche thecnique pos7 boufarikSami Sahli
 
FORMES ORGANISATIONNELLES TRADITIONNELLES ET MODERNES
FORMES ORGANISATIONNELLES TRADITIONNELLES ET MODERNESFORMES ORGANISATIONNELLES TRADITIONNELLES ET MODERNES
FORMES ORGANISATIONNELLES TRADITIONNELLES ET MODERNESImane SBAI
 
Louis Vuitton : Stratégies de fidélisation
Louis Vuitton : Stratégies de fidélisationLouis Vuitton : Stratégies de fidélisation
Louis Vuitton : Stratégies de fidélisationBlandine Darrieutort
 
Le web marketing, les stratégies et le principaux leviers
Le web marketing, les stratégies et le principaux leviersLe web marketing, les stratégies et le principaux leviers
Le web marketing, les stratégies et le principaux leviersMaxime Quintin
 
Marque marwa nouvelle stratégie digitale
Marque marwa nouvelle stratégie digitale Marque marwa nouvelle stratégie digitale
Marque marwa nouvelle stratégie digitale maryaslm
 
Qu'est-ce que le Digital Marketing ?
Qu'est-ce que le Digital Marketing ?Qu'est-ce que le Digital Marketing ?
Qu'est-ce que le Digital Marketing ?Matthieu THOMAS
 

Destacado (12)

Fonds Commercial
Fonds CommercialFonds Commercial
Fonds Commercial
 
Construction
ConstructionConstruction
Construction
 
SamanthaGottusoResume0516.pdf
SamanthaGottusoResume0516.pdfSamanthaGottusoResume0516.pdf
SamanthaGottusoResume0516.pdf
 
cours de construction Généralités
cours de construction Généralitéscours de construction Généralités
cours de construction Généralités
 
Fiche thecnique pos7 boufarik
Fiche thecnique pos7 boufarikFiche thecnique pos7 boufarik
Fiche thecnique pos7 boufarik
 
FORMES ORGANISATIONNELLES TRADITIONNELLES ET MODERNES
FORMES ORGANISATIONNELLES TRADITIONNELLES ET MODERNESFORMES ORGANISATIONNELLES TRADITIONNELLES ET MODERNES
FORMES ORGANISATIONNELLES TRADITIONNELLES ET MODERNES
 
Louis Vuitton : Stratégies de fidélisation
Louis Vuitton : Stratégies de fidélisationLouis Vuitton : Stratégies de fidélisation
Louis Vuitton : Stratégies de fidélisation
 
Le web marketing, les stratégies et le principaux leviers
Le web marketing, les stratégies et le principaux leviersLe web marketing, les stratégies et le principaux leviers
Le web marketing, les stratégies et le principaux leviers
 
Floating power stations
Floating power stationsFloating power stations
Floating power stations
 
Marque marwa nouvelle stratégie digitale
Marque marwa nouvelle stratégie digitale Marque marwa nouvelle stratégie digitale
Marque marwa nouvelle stratégie digitale
 
Lv Presentation
Lv PresentationLv Presentation
Lv Presentation
 
Qu'est-ce que le Digital Marketing ?
Qu'est-ce que le Digital Marketing ?Qu'est-ce que le Digital Marketing ?
Qu'est-ce que le Digital Marketing ?
 

Más de Jakub Kulhan

commit => #GitHub => #CircleCI => #Docker => #Kubernetes #AWS cluster
commit => #GitHub => #CircleCI => #Docker => #Kubernetes #AWS clustercommit => #GitHub => #CircleCI => #Docker => #Kubernetes #AWS cluster
commit => #GitHub => #CircleCI => #Docker => #Kubernetes #AWS clusterJakub Kulhan
 
Jak se dělal nový Skrz.cz na Symfony a Elasticsearch
Jak se dělal nový Skrz.cz na Symfony a ElasticsearchJak se dělal nový Skrz.cz na Symfony a Elasticsearch
Jak se dělal nový Skrz.cz na Symfony a ElasticsearchJakub Kulhan
 
ReactPHP + Symfony = profit aneb 1000req/s přes Symfony s minimálními nár...
ReactPHP + Symfony = profit aneb 1000req/s přes Symfony s minimálními nár...ReactPHP + Symfony = profit aneb 1000req/s přes Symfony s minimálními nár...
ReactPHP + Symfony = profit aneb 1000req/s přes Symfony s minimálními nár...Jakub Kulhan
 
#golang @SkrzCzDev (Skrz DEV Cirkus 21.10.2015)
#golang @SkrzCzDev (Skrz DEV Cirkus 21.10.2015)#golang @SkrzCzDev (Skrz DEV Cirkus 21.10.2015)
#golang @SkrzCzDev (Skrz DEV Cirkus 21.10.2015)Jakub Kulhan
 

Más de Jakub Kulhan (6)

Routing @ Scuk.cz
Routing @ Scuk.czRouting @ Scuk.cz
Routing @ Scuk.cz
 
commit => #GitHub => #CircleCI => #Docker => #Kubernetes #AWS cluster
commit => #GitHub => #CircleCI => #Docker => #Kubernetes #AWS clustercommit => #GitHub => #CircleCI => #Docker => #Kubernetes #AWS cluster
commit => #GitHub => #CircleCI => #Docker => #Kubernetes #AWS cluster
 
Jak se dělal nový Skrz.cz na Symfony a Elasticsearch
Jak se dělal nový Skrz.cz na Symfony a ElasticsearchJak se dělal nový Skrz.cz na Symfony a Elasticsearch
Jak se dělal nový Skrz.cz na Symfony a Elasticsearch
 
Ranking @ Skrz.cz
Ranking @ Skrz.czRanking @ Skrz.cz
Ranking @ Skrz.cz
 
ReactPHP + Symfony = profit aneb 1000req/s přes Symfony s minimálními nár...
ReactPHP + Symfony = profit aneb 1000req/s přes Symfony s minimálními nár...ReactPHP + Symfony = profit aneb 1000req/s přes Symfony s minimálními nár...
ReactPHP + Symfony = profit aneb 1000req/s přes Symfony s minimálními nár...
 
#golang @SkrzCzDev (Skrz DEV Cirkus 21.10.2015)
#golang @SkrzCzDev (Skrz DEV Cirkus 21.10.2015)#golang @SkrzCzDev (Skrz DEV Cirkus 21.10.2015)
#golang @SkrzCzDev (Skrz DEV Cirkus 21.10.2015)
 

Cesta k Webpacku (Skrz DEV Cirkus, 10.6.2015)

  • 1. Cesta k Webpacku Skrz DEV Cirkus 10.6.2015 V Node.JS na server-side existuje jednoduchý způsob, jak začít používat cizí knihovny - `npm install …` a poté stačí napsat `require(“…”)`. Pokud jde o browser, už to tak jednoduché není. a) Žádný standardní způsob není. b) “assety” před tím, než se pošlou do prohlížeče je potřeba minifikovat (odstranit bílé znaky, komentáře, zkrátit názvy proměnných). c) A nakonec optimalizovat pro posílání přes HTTP (spojit soubory dohromady), upravit názvy, aby podporovaly dobré kešování apod. V této prezentaci probereme, jak jsme ve Skrzu došli k Webpacku.
  • 2. Co je Skrz? Skrz je katalog akčního zboží, takový online akční leták. Musí poskytovat skvělou user experience pro své uživatele, tudíž se řeší nejrůznější Javascriptové vychytávky, animace, AJAXová volání. Ale zároveň musí být obsah dostupný pro vyhledávače - tzn. že renderovaní se musí řešit na serveru.
  • 3. -1.5 roku Posuňme se v čase do ledna 2014…
  • 4. Takhle nějak vypadal Javascriptový kód. Moc a moc úrovní odsazení, drlouhá jQuery špageta. Jestli uživatel je/není na nějaké stránce se neřešilo, vždycky se posílal stejný Javascript, který obsahoval vše - rozlišení, jestli se nějaký kód má, nebo nemá aplikovat na dané stránce se řešilo přes různé ověřování, jestli existují elementy pro všechny selektory, které daná fcionalita potřebovala = hromada ifů. Výsledkem bylo dlouhé načítání, špatný výkon.
  • 5. Takhle nějak vypadalo řešení knihoven a závislostí. Podobně to asi někdy řešil každý. Na produkci se akorát zapla proměná `settings.user_compile_js`. Minifikaci a spojování Javascriptových souborů řešila vlastní skript v PHP - tzv. packer. Tomu se v packer.conf souboru určilo, co všechno za soubory má projít a jak je má spojit. Často je spojil špatně, vyhodil znaky, které neměl apod. - takže až na produkci se zjistilo, že kód nefunguje.
  • 6. -1 rok LiveScript + LESS + AMD Grunt + Require.JS Březen až květen 2014 se řešil redesign Skrzu. Ještě důležitější než nový kabátek to ale znamenalo přepis hodně stránek a nové technologie. Místo home-made frameworku Ulriky se začala na backendu používat Symfony. Většina stránek začala brát data z Elasticsearch místo MySQL. A na client-side místo čistého Javascriptu se začal používat LiveScript, místo čistého CSS zase LESS. Nejdůležitější však bylo strukturování LiveSciptu do AMD (asynchronous module definition) - což dalo dobře základ škálovatelnému řešení rozdělení závilostí. Celé to spojoval Grunt a Require.JS.
  • 7. NO-FRAMEWORK framework aka vlastní řešení Jak jsem říkal, jako požitek pro uživatele je pro Skrz důležitá přístupnost pro roboty - tzn. renderování musí probíhat na serveru. V době redesignu byly v Javascriptu nejpoužívanější frameworky Backbone a Angular. Oba se snažily řešit renderování na klientu a podpora pro renderování na serveru bylo nedostatečná. A pokud se odmyslelo renderování na klientu, přidávaly pramálo užitečného pro strukturování aplikace - neřešili problém, který jsme měli ve Skrzu. My pouze potřebujeme vyrenderované HTML na serveru “rozhýbat” na klientu, sem tam načíst něco AJAXem. Vznikl tedy vlastní způsob, jak stránku rozděli na komponenty a jak je zaregistrovat a napojit na ně Javascript.
  • 8. V aplikaci je jeden entry point - main.ls (tečka LS protože LiveScript). V elementu s ID js-options je serializovaný JSON s proměnnými týkajících se celé stránky předaných z backendu. Obsahuje např. ID uživatele. V Javascriptu používáme dependency injection container. V této ukázce je to LillyContainer (Lilly je název jedné z aplikací). Ten se předá aplikaci a pak se aplikaci prožene fronta událostí, které do té doby na stránce vznikly.
  • 9. Dependency injection container obsahuje metody s prefixem “get” a “create”. “get” metody znamenají, že daná instance je singleton - bude vytvořena pouze jednou za celý běh aplikace. “create” metody jsou továrničky. Nejvíce pro tzv. “widgety” - to jsou právě jednotlivé části, na které je stránka rozdělená.
  • 10. Na začátku každé stránky (hned po otevíracím tagu <body>) se inicializuje kód fronty událostí. Něco jako mají trackovací kódy Google Analytics (_gaq), Facebooku (_fbq). Cílem (ke kterému jsme se bohužel ještě nedostali), je mít jeden `<script … async>` v hlavičce, eventy tedy hned po načtení části stránky mohou hned napárovat Javascriptovvý widget (který se stará o interakci) na naparsovaný DOM element.
  • 11. Události jsou prostě kusy Javascriptu přímo v HTML, které zavolají vždy nějakou metodu na globalním objektu `skrz`. Nejdůležitější/nejpoužívanější je událost/metoda `skrz.widget(…)`. Jako první argument má název widgetu (přilepte na začátek “create” a na konec “Widget” a máte název metody z dependency injection kontejneru) a jako druhý argument model v JSONu. Mohli jste si všimnout, že v kontejneru mají ještě widget-továrničky parametr `el`. To je odkaz na parent DOM element, ve kterém je volání `skrz.widget` (ten se odvodí auto-magicky díky způsobu, jakým prohlížeče zpracovávají DOM).
  • 12. Wiget je třída, v konstruktoru dostane tři argumenty `el`, `model` a `children`. `el` je element, ve kterém byla vyvolána eventa `skrz.widget`. `model` je druhý argument předaný události. Např. máme `ItemWidget` a ten má v model ID nabídky. Widgety tvoří strom, podobně jako DOM tvoří strom. `children` jsou widgety podřazené současnému. Lifecycle widgetu je jednoduchý - po vytvoření kontejnerem se zavolá metoda `bind`. Ta se stará o interaktivitu. Najde si různé elementy. Máme konvenci, že elementy používané z Javascriptu musí mít třídu s prefixem `j- *`. Opakem `bind` je `unbind`, která se zavolá, pokud je widget odstraňován. Widgety tvoří zapouzdřené celky, které se jednoduše upravují. Starají se pouze přidání interaktivity nad HTML renderované na serveru.
  • 13. -0.9972 roku Require.JS Widgety byly super a rozdělení do více souborů jakbysmet. Ale asi za 1 den, když se mělo natáhnout třeba 30 souborů s 30 různými widgety, jsme narazili na problém s připojením k internetu v předchozích kancelářích Skrzu na Bohdalci - prostě se nestáhl jeden z 30 souborů a najednou tu byl těžko debugovatelný problém. Vykašlali jsme se tedy na Require.JS…
  • 14. …a místo něj se inspirovali Stichem (https://github.com/ sstephenson/stitch), což je Node.JS middleware, který spojí X JS souborů dohromady. Přepsali jsme řešení do PHP a donedávna úspěšně používali. Mělo to však několik problémů: a) Stitch nechápal Javascript, pouze vzal soubory v adresáři, dal kolem každého boilerplate a spojil je dohromady. Výsledkem bylo mnoho opakujících se řetězců s názvem modulu, a tdy zbytečně velká velikost souboru. b) Řešil pouze Javascript (resp. LiveScript), na LESS jsme používali stále Grunt tasky.
  • 15. -3 měsíce Webpack S velkou popularitou a množstvím přednášek ohledně ReactJS, jsem narazil na přednášku od Pete Hunta, který ve Facebooku řeší Instagram webový frontend. Facebook používá k minifikaci, modularizaci a servírování Javascriptu adaptabilní a prediktivní řešení. Je ale hodně provázané s celým zbytkem Facebooku. Pro Instagram potřebovali něco daleko jednoduššího, co by mohli rychle nasadit. A našli Webpack.
  • 16. Google -> “pete hunt webpack howto” Zadejte do Google “pete hunt webpack howto” = nejjednodušší způsob, jak s Webpackem začít. A taky, jak jsme začali my.
  • 17. package.json: {
 "name": "Lilly",
 "version": "1.0.0",
 "devDependencies": {
 "webpack-dev-server": "^1.7.0",
 "webpack": "^1.7.3"
 },
 "dependencies": {
 "LiveScript": "^1.3.1",
 "bootstrap": "^3.3.2",
 "bootstrap-webpack": "0.0.3",
 "css-loader": "^0.9.1",
 "expose-loader": "^0.6.0",
 "extract-text-webpack-plugin": "^0.3.8",
 "file-loader": "^0.8.1",
 "font-awesome": "^4.3.0",
 "font-awesome-webpack": "gowravshekar/font-awesome-webpack#e22214a",
 "imports-loader": "^0.6.3",
 "jquery": "^1.11.2",
 "less": "^2.0.0",
 "less-loader": "^2.0.0",
 "livescript-loader": "^0.1.3",
 "source-map-loader": "^0.1.3",
 "style-loader": "^0.8.3",
 "uglify-js": "^2.4.16",
 "url-loader": "^0.5.5",
 "webpack": "^1.5.3"
 },
 "scripts": {
 "dev": "BUILD_DEV=true webpack-dev-server -d --hot --inline --progress --colors --port 8443 --inline --https --content-base is/ -- output-public-path https://localhost:8443/assets/",
 "build": "npm run build:queue && webpack -p --progress --profile --colors",
 "clean": "rm -f www/assets/*",
 "build:queue": "lsc --compile --bare --print client-src/Skrz/Inlined/queue.ls | uglifyjs --compress --mangle > client-src/Skrz/Inlined/ queue.js"
 }
 }
 V praxi to vypadá následovně: v package.json máme natažené všechny potřebné závislosti. A pak už 2 důležité scripty: a) `dev` spustí Webpack dev server - NodeJS server, který poslouchá na určitém portu. Umí livereload stránky při změně a další vychytávky. Nebuďte líní, pokud budete s webpackem začínat, si dev server nastavit. b) `build` spojuje a minifikuje soubory pro použití na produkci. V případě skrzu to trvá několik minut, ale výsledek je skvělý. Že je pro nás webpack tak skvělý je hlavně díky rozhodnutí strukturovat kód pomocí AMD modulů. Ale stejně tak webpack podporuje synchronní `require` jako je v Node.JS a další způsoby.
  • 18. webpack.config.js: var webpack = require("webpack");
 var ExtractTextPlugin = require("extract-text-webpack-plugin");
 
 module.exports = {
 entry: {
 all: ["./client-src/Skrz/Bundle/LillyBundle/main"]
 },
 output: {
 path: "./www/assets",
 publicPath: "/assets/",
 filename: "all.js"
 },
 module: {
 loaders: [
 { test: /bootstrap/js//,
 loader: ‘imports?jQuery=jquery' },
 { test: /.ls/,
 loader: “livescript-loader" },
 { test: /.css$/,
 loader: ExtractTextPlugin.extract("style-loader", “css-loader") },
 { test: /.less$/,
 loader: ExtractTextPlugin.extract("style-loader", “css-loader!less-loader") },
 { test: /.(woff2?|ttf|eot|svg|jpg|png|gif|swf)(?.*)?$/,
 loader: “file-loader" }
 ]
 },
 resolve: {
 extensions: ["", ".js", ".json", ".ls"]
 },
 plugins: [
 new webpack.DefinePlugin({
 __DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || "true"))
 }),
 new ExtractTextPlugin("[name].css")
 ]
 
 };
 Webpack se nastaví přes `webpack.config.js`. Důležitá je sekce loaders, kde podle přípony souboru nastavíte, co v tom souboru je. Např. tady soubory končící na `.ls` se interpretují jako LiveScript. Soubory končící na `.less` jako LESS = ano, uděláte v Javacriptu `require(“./style.less”)` a webpack soubor přeloží do CSS, všechny CSS pak posbírá ExtractTextPlugin (viz sekce plugins) a vytvoří jeden CSS soubory se vším. Zahodili jsme tedy Grunt a o všechno se teď stará webpack. Ten navíc např. fonty referencované v CSS, obrázky uloží do souboru, který má jako název MD5 hash obsahu a nahradí všechny výskyty v CSS - můžete tedy nastavit na fonty/obrázky kešování forever, a pokud se změní, vznikne nový soubor, a tím pádem se invaliduje keš.
  • 19. <head>: <link rel="stylesheet" href="{$assetsBaseUrl}/all.css"> za <body>: <script>{$queue nofilter}</script>
 <script>skrz.begin();</script> před </body>: <script>skrz.end();</script>
 <script>skrz.widget("Body");</script>
 <script type="application/json" id=“js-options”>{$options|json_encode nofilter}</script>
 <script src="{$assetsBaseUrl}/all.js"></script> Pak už jsem stačí nastavit `$assetsBaseUrl` v šabloně podle toho, jestli se jedná o vývoj nebo produkci.
  • 20. Otázky? Díky! Jedna otázek byla: “Proč použít Webpack a nepoužít Gulp?” A proč nepoužít obojí! Každá věc je totiž na něco jiného. Webpack se stará o přípravu “assetů” pro development/produkci. Gulp je task runner. Jedním z těch tasků může být např. spuštění Webpacku pro development nebo vybuildovaní assetů pro produkci. My jsme Gulp jako task runner nepotřebovali, protože většinu tasků máme v PHP, v Javascriptu máme pouze ty, které byly vidět v `package.json` na jednom z předchozím slajdů. `npm run …` nám na to úplně stačí.