Preprocesing HTML/JS/CSS

Sinula mi ideja da bi mogao raditi preprocesing gornjih stavki u svrhu kompresiranja failova i “kodiranja”, tako da zamjenim varijablama, i funkcijama imena. (Što bi dodatno kompresiralo)

E sad, naravno da se toga nisam sjetio prvi…pa me zanima što od toga već postoji?
Googlao sam malo, ali ovo prvo što sam naletio ne kodira imena varijablama, nego samo optimizira text brisanjem praznog mjesta, komentara…kodiranje lokalnih varijabli.

E sad, zamjena svih varijabli kao i imena funkcija je malo kompleksnija stvar…svjestan sam toga.
Problem je očito što različite skripte pristupaju funkcijama istog imena i globalnim varijablama. Isto tako unutar HTMLa se može pisati javascript unutar atributa onclick=’’, onmouseover=’’ …itd.
Nadalje i php skripte nisu skroz neutralne…jer recimo možda imamo nekakvu funkciju koja prenosi varijable iz PHP-a prema JS-u na poziv stranice.

Očito za uspješnu obradu treba sve to skupa procesuirati. Postoji li takvo što? (Da se opet ne hebem sa regularnim izrazima radeći svoj css preprocesor, ne znajući da postoji .less xd)

Sto se tice CSS a najpopularniji su SASS i LESS:

http://sass-lang.com/
http://lesscss.org/

Oni ti omogucuju varijable i funckije u samom CSS u.Naravno nakon toga taj kod treba konventirati u CSS postoje razni za taj dio posla i tu trebas viditi dali vise preferiras GUI alate ili terminal ( CMD u windowsima )

Na pitanje prijenosa PHP prema JS u mozes jednosatvno napraviti nesto tipa

<script>
    foreach($dates as $date) {
         // daljni kod
   }
</script>

i prebaci si si varijable u JS. Takoder mozes napraviti API koji ce ti request vracati u JSONu pa ga kasnije hendlas kako hoces naravno u API mozes raditi i post requestove…

Za HTML imas razlicite templating jezike. Nekakva kompresija ti nije potrebna, mozes eventualno raditi brisanje komentara i nepotrebnih indentation-a/line breakova, ali tome ne vidim bas smisla posto su dobitci minimalni.
Za JS jedino sto trebas (sto se kompresije tice) je UglifyJS.
Za CSS preporucam SASS (SCSS),

Sto se PHP u JS tice, kao sto je gore kolega napisao, ili radi direktni output na stranicu, ili napravi nekakav JSON API.

CSS je zapravo gore zalutao u naslovu. Razmišljao sam da bi mogao biti dio toga ukupnog preprocesora, ali to je već “tjeranja maka na konac”. Ali pod ovim gore ukupnim preprocesorom ne mislim na to što radi less (pridruživanje varijabli) …nego integraciju CSS-a sa ostatkom u nekoj drugoj domeni…gdje bi se čak moglo onda i optimizirati imena klasa, tako što bi preprocesor mijenjao sva imena i unutar css-a, unutar HTML-a i unutar JS-a gdje bi prepoznao koje funkcije upravljaju klasama… (No skraćivanje imena je manje bitno…čini mi se da bi takav preprocesing (ukupni) …otvorio mnoge dobre mogućnosti za pisanje code-a unutar framworka koji bi bio tako preprocesuiran)

Ovo što si spomenuo za prijenos iz PHP -> JS, to naravno štima…ali nisi uhvatio što sam htio reći.
Zamisli da imaš preprocesor koji obradi sve JS skripte i optimizira (i kodira) skripte tako što će svim varijablama i funkcijama zamjeniti imena.
I sad neka varijabla recimo var UserName nakon procesuiranja izgleda kao var a14, ili var c41 (sa samo 3 karaktera bi bilo moguće popisati cca 50 000 različitih nameSpaceova :smiley: , a sa 4 karaktera cca 2 000 000)
Uglavnom, napravi se to kodiranje svih imena varijabli u neki kraći oblik…a sa servera više onda također ne smije u tom foreachu stići naziv “UserName” …kad je to sad za browser tipa: “a14”, kako je zapisano u obrađenim JS scriptama.

Ako odemo korak dalje, moguće bi bilo procesuritai i nazive atributa varijabli koje su po tipu objekt. Znači:

var Automobil=
{
godište:2001,
boja:'crvena',
tehnologija_proizvodnje:'bla bla'
} 

se pretvori u:

a12:
{
a13:2001
a14:'crvena'
a15:'bla bla'
}

Koliko se meni čini, to bi dosadašnji max-compress moglo još dodatno smanjiti za 30-40%, jer code prevladava od imena varijabli i njenih atributa.
No glavna problematika kod kodiranja imena atributa je u tome da su ponekad potrebni izvorna imena atirbuta. Jer što kad se neka od tih varijabli pohranjuje u JSON, ili se prosljeđuje na server.
Kako će preprocesor razlikovati varijable (objekte) koje moraju zadržati izvorne nazive svojih atributa…i onih koji ne moraju.
Drugi grdi problem je što se atributi mogu prosljeđivati kao string varijable od funkcije do funkcije…kako bi preprocesor razlikovao takve stringove od običnih…

Za sve ostalo je prilično nebitno koji su nazivi atributa, dok god se ne mijenjaju nazivi onim objektima koji služe za komunikaciju sa nekim vanjskim izlazima/ulazima u aplikaciju.
A za svrhu developinga, kad bi recimo admin htio promatrati vrijednosti nekih atributa, on bi lako preko switcha učitavao stranicu sa izvornim skriptama.

Noćas sam legao u jedan, a nisam mogao zaspati do 5 ujutro koliko sam o ovom razmišljao, hahah :smiley:

Btw…ta komunikacija za ulaze/izlaze bi se dala rješiti sa konverterom, kojeg bi generirao sam preprocesor. Taj konverter bi imao i suvišnih “key-value” veza, ali bi se te suvišne veze dale izbaciti…kako sam konverter nebi bio nepotrebno prevelik.

I još jedna stvar, ovdje se ne radi samo o skraćivanju imena varijabli…nego vlastita kontrola nad takvim preprocesorom otvara razne moguće zanimljive nadogradnje.
Recimo mogućnost da se unutar istog JS file pišu debug funkcije, mobile funkcije i destkop funkcije.
Preporcesor iz toga može generirati JS koje će slati za destkop aplikaciju, JS koji će slati za mobile aplikaciju …i JS koji će slati za development mode rada…itd. Svašta bi se moglo…

Ja sam si recimo radio preprocesor .css-a i napravio mogućnost da mogu pisati sljedeći code:

.column
	{
	padding-bottom:$space_box;
	height:calc( 100% - 28px);
	position:relative;
	@destkop 
		{
		float:left;
		margin:0px ($space_box/2) 0;  
		}
	@mobile
		{
		padding-left:$s_s;
		padding-right:$s_s;
		width:calc(100% - [2*$s_s]);
		}
	} 

Što mi je full praktično da na licu mjesta mogu neke elemente oblikovati za mobitel i za destkop…a da ne uvjetujem da se oba pravila moraju učitavati, kao što bi to bio slučaj da se koristim sa @media screen.
U tom smjeru razmišljam i za JS.
Ovo za CSS znači generira dvije različite skripte, a u framework mi je ugrađeno da samostalno kontrolira s kojom će poslužiti destkop, a s kojom mobile verziju.

Meni se cini da ga ti vise kompliciras nego sto je potrebno.

Kompresija je ok stvar ali ovo sto si ti opisao (a i bilo koji slican pristup tome) toliko zakompliciran development cycle da se nikako ne isplati raditi, barem po mojem misljenju.

Da ne bude zabune, znam i ja da kompliciram :smiley:

Čisto bacam malo ideju kuda razmišljam, da mi se možda i ponudi nešto što je nasličnije tomu što govorim…što nemam pojma da postoji. Meni se onako čini da ovo što pričam bi moralo biti uklopnjeno u nekakav cijeloukupni framwork, jer separativno je pretpostavljam nemoguće dirati po imenima varijabli neke skripte, a da stvar šljaka u cjelini u kojoj je ta skripta samo dio.

No onako, iz razonode volim pričati o idejama i problemima ideje. Slažem se da bi bilo neisplativo sad to razvijati…ali me mami onaj dio razmišljanja bili bilo moguće tako nešto razviti. A sve mi se čini da bi bilo…u glavi barem nisam nigdje zaglavio u slijepoj ulici…

A sad back to real life…spomenuo si ovaj UglifyJS. Ako si upućen, da mi objasniš neke stvari u grubo kako tamo funkcioniraju…na stranici https://github.com/mishoo/UglifyJS čitam sljedeće:

The tokenizer/parser generates an abstract syntax tree from JS code.

-što bi to značilo. Pod apstraktni kod se misli nečitljiv jer je sve sažeto u jednu liniju? …i ostale pretumbacije koje su već napravljene?
Ili je code moguće još nekako apstraktirati/kodirati što je čitljivo browseru, no ne i čovjeku?

shorten variable names (usually to single characters). Our mangler will analyze the code and generate proper variable names, depending on scope and usage, and is smart enough to deal with globals defined elsewhere…

Evo nas na pragu onog što pričam. Sad ne kužim u kojoj mjeri su to oni mogli izvesti?
Ako sam dobro skužio i on mjenja imena varijablama? …to je valjda htio reći sa ovim: “generate proper variable names” ?
Što ako on promjeni globalnu var UserName, a ja tu istu globalnu koristim u nekoj drugoj skripti koje se parser nije dotakao?
Vodi me to k činjenici da i on mora raditi analizu nad cijelim projektom, svim skriptama?

Čini se da sam našao slagalicu koja mi je nedostajala.

Znači išao sam malo vidjeti o kojim brojkama se radi…i odem na neki online compreser i on mi napravi od 43kb skriptu od 28kb.

Onda sam u toj skripti zamjenio sva imena varijabli sa tri karaktera. (To sam samo onako ugrubo posjekao sa regexp replace, tako da sam zamjenio sve riječi koje su duže od 4 karaktera…ne mareći na višak koji inače nebi smio posjeći , jer je zanemariv za usporedbu rezultata)
I kad sam tako sasjekao, dobio sam skriptu od 12kb. …što mi je bilo wow reduciranje.

No nakon toga sa vidio neki gumbić base62 encode, na tom online compreseru, rekoh da probam i to …i bam, to je ono što tražim. xd. Nije mi pala na pamet ta fora sa evalom da se uistinu može tako dobiti apstraktan code čitljiv browseru, nečitljiv čovjeku…dobro kompresiran, a ujedno da zadržava izvorna imena varijabli. :slight_smile:

I ja sam bio prilično blind do sada…koliko sam puta uštekavao negdje tako kodirani code, a da se nisam zapitao zašto je takav apstraktan, jooj…

Sad sljedeća pitanja:

  1. dali je to base62 kodiranje reverzibilno. Tj. jeli moguće takvim kodiranjem zaštiti source od otuđivanja?
  2. kako je najlakše upregnuti to kompresiranje da mogu s njim upravljati putem php-a? Da s php-om kontroliram što ću kompresirati i gdje ću pohraniti?

To je analiza JS datoteke, analizom dobijest opis strukture:

Reads a program from a string or a stream, and produces an abstract syntax tree, which is a nested structure consisting of lists starting with keywords. The exact format of this structure is not very well documented, but the file as.txt gives a basic description.

The keyword arguments can be used to influence the parsing mode. emca-version can be 3 or 5, and influences the standard that is followed. The default is 3. Support for version 5 is incomplete at this time. When strict-semicolons is true, the parser will complain about missing semicolons, even when they would have been inserted by ‘automatic semicolon insertion’ rules. Finally, if reserved-words is true, the parser will complain about ‘future reserved words’, such as class being used.

Da, mijenjaju se imena varijabli. Kako je to tocno izvedeno nisam siguran. Pretpostavljam da se ne diraju globalne varijable, ili imena struktura koje su dostupne izvan samo scope-a funkcije.

Npr.

function nekoIme() {
    var obj = { svojstvoJedan: 3, svojstvoDva: 3 };
    return;
}

S obzirom da ovaj objekt ne ide izvan funkcije, svojstvoJedan i svojstvoDva se bez problema mogu skratiti, no neki objek koji se vraca npr return obj;, to vece ne moze jer ne znas da li netko ocekuje svojstva pod tim imenom.

Naravno da je reverzibilno, da nije kako bi onda browser mogao izvrsitit taj kod?

Ne zezaj se s evalom, jer oni koji ti zele procitati kod to mogu bez problema napraviti (nikakav base encoding ih nece sprijecitit u tome), a samo narusavas performanse izvrsavanja koda.

Pazi molim te ovo…koprat ću ti ulaze/izlaze jednog kompajlera…čini mi se čak googlovog.
Znači ulaz:

var object={};
object.hello=function(){alert('hello there there there there')};
object.hello2=function(){alert('hello there2 there2 there2')};

button.onclick=function(){object.hello()};
button2.onclick=function(){object.hello2()};
button3.onclick=function(){object.hello()};

Izlaz: (ostavio sam da izlaz bude razbijen u linije…čisto da bude čitko)

function a() {alert("hello there there there there"); }
button.onclick = function() {a();};
button2.onclick = function() {alert("hello there2 there2 there2"); };
button3.onclick = function() {a(); };

Znači, ne samo da nije zadržao imena atributima “hello” i “hello2” , nego je čak kompletno razbio objekt u nešto drugo, a da pri tome sačuva istu funkcionalnost!!!

Pokušao sam ga natjerati da ne smije uništiti objekt sa sljedećim ulazom: (Sve isto osim zadnje linije)

var object={};
object.hello=function(){alert('hello there there there there')};
object.hello2=function(){alert('hello there2 there2 there2')};

button.onclick=function(){object.hello()};
button2.onclick=function(){object.hello2()};
button3.onclick=function(){object.hello()};

for(var x in object){object[x]()}

IZLAZ:

var a = {
a:function() {alert("hello there there there there");},
b:function() { alert("hello there2 there2 there2");}};
button.onclick = function() { a.a();};
button2.onclick = function() { a.b(); };
button3.onclick = function() { a.a(); };
for (var b in a) { a[b](); }  ;

Sad je bome zadržao objekt, ali je imena atributima totalno sasjekao.

Tko se želi igrati, tu je online alat: http://closure-compiler.appspot.com/home
…i home page: https://developers.google.com/closure/compiler/docs/gettingstarted_ui

Znači, ipak postoji ovo gore što sam mozgao cijelu noć xd , samo eto ostaje problem spajanja takvih skripti u veću cjelinu. Pogotovo ako se ne može dublje djelovati na ponašanje kompresora.
Ja sam zamislio još nekakav koder koji bi mogao vratiti imena atributa nekog objekta u njihovo izvorno stanje…onda bi taj koder omogućio kodiranje/dekodiranje naziva atributa na ulazu i izlazu nekog objekta iz aplikacije. Tipa, prije postanja na server se samo dekodiraju nazivi atributa…a ako postoji neki vanjski API koji šalje request na aplikaciju, onda se prije ulaza kodiraju nazivi atributa objekta koji stiže.

Istina da…

I još jedna stvar koju nisam očekivao :slight_smile:
Kuži frajer da je string prosljeđen da bude u službi atributa objekta, njammm

ULAZ:

object.say1=function(){alert('hej')};
object.say2=function(){alert('ciao')};

var myAlert=function(atribut) //!!! znači ovdje atribut trebao stići kao STRING
{
object[atribut]();
}

myAlert("say1");

IZLAZ:

object.a = function() {alert("hej");};
object.b = function() {alert("ciao");};
object.say1();

Sad tek vidim da sam fulao ovo zadnje…inače bi zadnji line gornjeg izlaza trebao biti object.a();

Ali sad kad sam krenuo čitati dokumentaciju, skužio sam da je ovo gore zapravo željena situacija…jer to omogućuje da kreiramo atribute koji neće biti podložni promjeni imena, i one koji će se mijenjati. Na taj način su omogućili da aplikacija komunicira sa ulazima/izlazima.

Cool je zapravo ovo stvar…samo zahtjeva određeni napor da se postojeći djelovi codea prilagode za compaliranje…isto tako određenu disciplinu za daljnje pisanje codea.
Iako ne vidim previše novih pravila…a opet internet vrišti da ga nije najpametnije koristiti. S druge strane, koristi se za razvoj Googleovih značajki :D.