Nettaktiver - Tips for bedre organisering og ytelse

Husk tilbake til når vi måtte bruke mye tid på å optimalisere prosjektets eiendeler (bilder, CSS, etc ...)? Nå i dag, brukerne har en mye raskere Internett-tilkobling, og det ser ut til at vi har råd til å bruke større bilder eller større flashfiler med mye video og bilder inni. Men med veksten i mobilutvikling er vi igjen tilbake i samme situasjon. Det er ekstremt viktig å lage godt optimaliserte nettsteder, slik at vi får raskere applikasjoner, som laster ned mindre innhold og svarer umiddelbart.


Bilder

Server riktig størrelse

Ofte bruker vi de samme bildene for ulike deler av våre nettsider. For eksempel, i en nettbutikk, har alle produktene et oversiktsbilde. La oss si at vi har tre sider der vi må vise bildene - en side for oppføring av produktene, en annen side for produktets detaljer og en tredje side som bare viser bildet i sin opprinnelige størrelse.

Så vi trenger tre forskjellige bildestørrelser, og hvis vi bruker samme fil for alle tre forskjellige steder, vil nettleseren laste ned bildet i full størrelse selv for oppføringssiden, der vi faktisk bare trenger et 200x200 bilde. Hvis den opprinnelige filen er rundt 1 MB og vi har ti produkter per side, vil brukeren laste ned 10 MB. Det er ikke en veldig god idé. Hvis du kan, prøv å generere forskjellige bilder for de ulike delene av nettstedet ditt, dette vil spare mange KBer for brukerne dine. Det er en god ide å huske den nåværende skjermoppløsningen. For eksempel, hvis noen åpner nettstedet ditt på deres iPhone, er det ikke nødvendig å tjene det gigantiske toppbildet, som du vanligvis bruker. Ved å bruke CSS media spørringer kan du sende et bilde med en mindre størrelse:

@media-skjerm og (min-enhet-bredde: 320px) og (maksimal enhetbredde: 480px) .header bakgrunnsbilde: url (... /images/background_400x200.jpg); 

kompresjon

Det er ikke alltid nok å sende et bilde med bare de riktige dimensjonene. Noen filformater kan komprimeres mye uten å miste kvaliteten. Det er mange programmer som kan hjelpe deg. For eksempel gir Photoshop en fin funksjon som heter Lagre for web og enheter:


Det finnes mange alternativer i denne dialogen, men en av de viktigste er Kvalitet. Hvis du setter det til noe som 80%, kan filstørrelsen reduseres betydelig.

Selvfølgelig kan du bruke kode for å komprimere filene, men jeg personlig foretrekker Photoshop, og jeg bruker det når det er mulig. Her er et enkelt eksempel skrevet i PHP:

funksjon compressImage ($ kilde, $ destinasjon, $ kvalitet) $ info = getimagesize ($ source); bytte ($ info ['mime']) tilfelle "image / jpeg": $ image = imagecreatefromjpeg ($ source); imagejpeg ($ image, $ destinasjon, $ kvalitet); gå i stykker; tilfelle "image / gif": $ image = imagecreatefromgif ($ source); imagegif ($ bilde, $ destinasjon, $ kvalitet); gå i stykker; tilfelle "image / png": $ image = imagecreatefrompng ($ source); imagepng ($ image, $ destinasjon, $ kvalitet); gå i stykker;  compressImage ('source.png', 'destination.png', 85);

sprites

En av tingene du kan gjøre for å øke ytelsen til søknaden din, er å redusere antall forespørsler til serveren. Så, hvert nytt bilde betyr en ny forespørsel. Det er en god ide å kombinere bildene dine til en. Det resulterende bildet kalles a sprite og med å endre Bakgrunnen-stilling CSS-stil, kan du bare vise den delen av bildet du trenger. For eksempel bruker Twitter Bootstrap sprites for sine interne ikoner:


Deretter kan du i CSS gjøre noe slikt for å vise hvilken del av sprite du vil ha:

.ikon-rediger bakgrunnsbilde: url ("... /img/glyphicons-halfl-white.png"); bakgrunnsposisjon: -96px -72px; 

caching

Nettleserens cachemekanisme er din venn. Ja, noen ganger under utviklingen kan det føre til noen veldig morsom situasjoner, men det hjelper virkelig å forbedre ytelsen til nettstedet ditt. Hver nettleser caches innhold som bilder, JavaScript eller CSS. Det er flere måter å kontrollere caching på, og jeg foreslår at du sjekker ut denne flotte artikkelen for en detaljert gjennomgang. Generelt kan du styre prosessen ved å sette inn overskrifter, slik som:

$ expire = 60 * 60 * 24 * 1; // sekunder, minutter, timer, dager header ('Cache-Control: maxage = ". $ utløper); header (" Utløper:' .gmdate ('D, d MYH: I: s ', tid () + $ utløper).' GMT '); header ('Sist endret:' .gmdate ('D, d M Y H: i: s'). 'GMT');

forhåndshenting

HTML5 går fremover hver dag. Det er en fin funksjon som heter forhåndshenting som forteller nettleseren at du trenger litt ressurs i nær fremtid, og den skal lastes ned nå, på forhånd. For eksempel:

Data URI-skjema / Inline Images

For noen år siden måtte jeg utvikle en enkel nettside, som bare skulle være en HTML-fil. Selvfølgelig var det flere bilder, som jeg måtte ta med. Data URI-ordninger hjalp meg til å løse problemet. Tanken er å konvertere bildene til en base64 kodet streng og plassere den i src attributten til img stikkord. For eksempel:

rød prikk

Ved å bruke denne tilnærmingen, er bildet ditt faktisk i HTML-en, og du lagrer en HTTP-forespørsel. Selvfølgelig, hvis du har et stort bilde, vil strengen bli veldig lang. Her er et enkelt PHP-skript som konverterer bilder til base64-strenge:

$ picture = fread ($ fp, file size ($ file)); fclose ($ fp); // base64 koder for binære data, og bryter den inn i biter i henhold til RFC 2045 semantikk $ base64 = base64_encode ($ picture); $ tag = ''; $ css = 'url (data: image / jpg; base64,' .str_replace ("\ n", "", $ base64). '); ';

Du kan finne dette nyttig i noen tilfeller, men husk at det ikke fungerer veldig bra i IE.


CSS

Jeg liker å tro at skriving CSS er som skrive kode. Du må fortsatt organisere stilene dine, definere ulike blokker og forholdet mellom dem. Det er derfor jeg tror CSS-ledelsen er veldig viktig. Hver del av søknaden skal ha sine egne stiler, og de skal være pent skilt. Å holde alt i forskjellige filer gir god organisering, men kommer også med egne problemer.

Vi vet alle at bruken av @importere erklæring er ikke en veldig god idé. Det er fordi alle nye @importere betyr en ny forespørsel til serveren. Og hvis du for eksempel har 20 forskjellige .css filer betyr det at nettleseren vil gjøre 20 forespørsler. Og nettleseren gjengir / viser ikke siden før du laster ned alle stilene. Hvis noen av dine .css filer mangler eller er svært store, vil du få en stor forsinkelse før du ser noe på skjermen.

Bruk CSS Preprocessors

CSS preprocessors løser alle problemene ovenfor. Du deler fortsatt stilene dine i forskjellige filer, men på slutten komprimerer preprosessoren alt til en enkelt .css fil. De tilbyr faktisk en haug med kule funksjoner som variabler, nestede blokker, mixins og arv. Koden ser fortsatt ut som CSS, men den er godt formatert / strukturert. Det er få populære preprosessorer som er verdt å sjekke - Sass, LESS, og Stylus. Her er et enkelt eksempel skrevet i MINDRE:

.posisjon (@top: 0, @left: 0) posisjon: absolutt; toppen: @top; venstre: @left; tekstjustering: venstre; skriftstørrelse: 24px;  .header .position (20px, 30px); .tips .position (10px, -20px);  .logo .position (10px, 20px); 

vil produsere

.header posisjon: absolutt; topp: 20px; igjen: 30px; tekstjustering: venstre; skriftstørrelse: 24px;  .header .tips posisjon: absolute; topp: 10px; igjen: -20px; tekstjustering: venstre; skriftstørrelse: 24px;  .header .logo posisjon: absolutt; topp: 10px; venstre: 20px; tekstjustering: venstre; skriftstørrelse: 24px; 

Eller, for eksempel hvis du har styling for en knapp og vil produsere akkurat samme knapp, men med en annen farge for teksten, kan du gjøre dette:

.knapp border: solid 1px # 000; polstring: 10px; bakgrunn: # 9f0; farge: # 0029FF;  .aktiv-knapp . knapp (); farge: #FFF; 

Effektiv CSS

Normalt tenker de fleste utviklere ikke på effektiv CSS. Effektiviteten til CSS reflekterer på sidenes gjengivelse, og hvis stilene dine er ineffektive, blir søknaden din sakte sakte av nettlesere. Et interessant faktum er at nettlesere analyserer CSS-valgene fra høyre til venstre. Hvilket betyr at følgende kode:

body ul li a color: # F000; tekst-dekorasjon: ingen; 

... er ikke effektivt i det hele tatt. Det er fordi motoren vil få alle koder og må evaluere hver av de overordnede elementene for endelig å samle den nødvendige stilen. Du bør også vite at når det gjelder effektivitet, er valgene sortert i følgende rekkefølge: ID, klasse, tag og universell. Dette betyr at et element med en id sett vil bli gjengitt raskere enn et element med bare en tagvelger. Selvfølgelig er det ingen mening å legge til ids på alle elementene i DOM-treet, men du bør definitivt sjekke koden din og forbedre den der det er mulig. For eksempel, hvis du har noe slikt:

ul #navigation li bakgrunn: # ff0232; 

Du bør fjerne ul del fordi du bare har en #navigasjon element på siden. Eller i følgende valg:

body .content p font-size: 20px; 

Det er klart at .innhold element er et barn av kropp stikkord. Alle elementene er egentlig barn av dette elementet.

Her er to nyttige koblinger på dette emnet: developers.google.com og css-tricks.com

Filstørrelse

Som nevnt ovenfor er det godt å ha så lite kode som mulig, fordi nettleseren ikke gjengir siden før du laster ned CSS. Her er noen tips for å redusere filstørrelsen.

Kombiner lignende stiler:

.header font-size: 24px;  .content font-size: 24px; 

... forvandles til:

.header, .content font-size: 24px; 

Bruk shorthands. I stedet for:

.header bakgrunnsfarge: # 999999; bakgrunnsbilde: url (... /images/header.jpg); bakgrunnsposisjon: øverst til høyre; 

Skriv det på denne måten:

.header bakgrunn: # 999 url (... /images/header.jpg) øverst til høyre; 

Minifiser CSS-koden din. Du kan gjøre dette ved å bruke et verktøy som vanligvis fjerner alle mellomrom og nye linjer. For eksempel CSSOptimiser eller Minifycss. Det er en vanlig praksis å bruke slike instrumenter på serverens side av applikasjonen, det vil si noe som er skrevet på språket i back-end. Normalt reduserer disse komponentene koden din og serverer den til brukeren.

Sett CSS-filene dine i stikkord

Det er god praksis å inkludere din .css filer i hode tag, slik at nettleseren vil laste den ned først.


Javascript

Reduser antall HTTP-forespørsler

Samme som med CSS - det er godt å redusere antall forespørsler som skal sendes til serveren. I de fleste tilfeller stopper ikke lastingen av JavaScript-filene gjengivelsen av siden, men det vil gjøre noen deler av siden ufunksjonell.

Minifiser koden din

Det er en rekke biblioteker som gjør JavaScript-minifisering. Det er noe som vil redusere filstørrelsen, men husk at i et utviklingsmiljø er det godt å holde koden ren. De fleste av disse verktøyene endrer navnet på variablene dine og konverterer alt til en linje med en linje, noe som gjør debuggingprosessen nesten umulig..

CommonJS, AMD, RequireJS - Gi det et forsøk

JavaScript har ikke en mekanisme for styring av moduler. Så er alle disse tingene oppfunnet for å løse dette problemet. De gir en API som du kan bruke til å definere og bruke moduler. For eksempel, her er et eksempel tatt fra http://requirejs.org/:

   Mitt prøveprosjekt     

Mitt prøveprosjekt

Inni main.js, du kan bruke kreve () å laste inn andre skript du trenger:

krever (["hjelper / util"], funksjon (util) // Denne funksjonen kalles når skript / hjelper / util.js er lastet. // Hvis util.js-anrop definerer (), blir denne funksjonen ikke avbrutt før // util er avhengighet har lastet, og util argumentet vil holde // modulverdien for "hjelper / util".);

Bruk navnegrupper

Hvis vi snakker om kodeorganisasjon, kan vi ikke hoppe over delen om navneområder. Nativt finnes det ingen slik funksjon i JavaScript, men du kan likevel oppnå det samme med en liten kode. For eksempel, hvis du vil bygge din egen MVC rammeverk, vil du sannsynligvis ha følgende klasser:

varmodell = funksjon () ...; var view = funksjon () ...; var controller = funksjon () ...;

Hvis du forlater ting som de er i koden ovenfor, blir de offentlige og det er større sjanse for å produsere konflikter med andre biblioteker i prosjektet ditt. Så, gruppering av dem i et selvstendig objekt (namespace) gjør rammen beskyttet:

var MyAwesomeFramework = modell: funksjon () ..., visning: funksjon () ..., kontroller: funksjon () ...

Følg designmønstre

Det er ikke nødvendig å gjenoppfinne hjulet. JavasScript ble veldig populært, og det er mye god praksis der ute. Designmønstre er gjenbrukbare løsninger for vanlige problemer i programmeringen. Etter noen av dem vil du hjelpe til med å bygge en god applikasjon. Men hvis jeg prøver å dekke dem alle her, må jeg skrive en bok, så her er bare noen få av dem:

Konstruksjonsmønster

Bruk dette mønsteret til å lage en forekomst av en bestemt objekttype. Her er et eksempel:

var klasse = funksjon (param1, param2) this.var1 = param1; this.var2 = param2;  Class.prototype = metode: funksjon () alarm (this.var1 + "/" + this.var2); ;

Eller du kan prøve dette:

funksjonsklasse (param1, param2) this.var1 = param1; this.var2 = param2; this.method = function () alert (param1 + "/" + param2); ; ; var instance = ny klasse ("verdi1", "verdi2");

Modulmønster

Modulmønsteret gir oss muligheten til å lage private og offentlige metoder. For eksempel, i koden under, variabelen _index og metoden privateMethod er private. tilvekst og getIndex er offentlige.

var-modul = (funksjon () var _index = 0; var privateMethod = funksjon () retur _index * 10; returnere inkrement: funksjon () _index + = 1;, getIndex: funksjon () return _index; ;) ();

Observer Mønster

Uansett hvor du ser abonnement eller forsendelse av hendelser, ser du sannsynligvis dette mønsteret. Det er observatører som er interessert i noe som er relatert til en bestemt gjenstand. Når handlingen oppstår, informerer objektet observatørene. Eksempelet nedenfor viser hvordan vi kan legge til en observatør til brukere gjenstand:

var Brukere = liste: [], lyttere: , legg til: funksjon (navn) this.list.push (navn: navn); this.dispatch ( "bruker-tilsatt"); , på: funksjon (eventnavn, lytter) if (! this.listeners [eventName]) this.listeners [eventName] = []; this.listeners [Eventname] .push (listener); , send: funksjon (eventnavn) if (this.listeners [eventName]) for (var i = 0; i 

Funksjonssettemønster

Dette mønsteret er en fin måte å organisere det offentlige grensesnittet til modulen din. Det sparer tid og forbedrer lesbarheten:

var Bruker = profil: , navn: funksjon (verdi) this.profile.name = value; returnere dette; , jobb: funksjon (verdi) this.profile.job = value; returnere dette; , getProfile: function () return this.profile; ; var profil = Brukernavn ("Krasimir Tsonev"). jobb ("webutvikler"). getProfile (); console.log (profil);

Jeg anbefaler på det sterkeste å sjekke ut denne boken av Addy Osmani. Det er en av de beste ressursene du kan finne om designmønstre i JavaScript.


Eiendeler-Pack

Nå som vi nærmer seg slutten av denne artikkelen, vil jeg dele noen tanker om CSS og JavaScript-kodeadministrasjon på serveren. Det er en veldig vanlig teknikk for å legge til sammenslåing, minifisering og kompilering i logikken til applikasjonen. Ofte er det en slags caching-mekanisme, men alle ting skjer i løpet av kjøretiden. Så du har sannsynligvis noen kodelogikk, som håndterer forespørselen etter .js eller .css filer og serverer riktig innhold. Bak denne prosessen er kompilering, reduksjon eller hva du bruker til å pakke dine eiendeler.

I mine siste prosjekter brukte jeg et verktøy som heter eiendeler-pack. Det er veldig nyttig, og jeg vil forklare i detalj hva det egentlig gjør, men den mer interessante delen er hvordan jeg brukte den. Dette biblioteket er ment å bare brukes i utviklingsmodus, det er ikke noe som forblir i kodebase og det er ikke noe du bør distribuere på produksjonsserveren din.

Tanken er at du kun bruker pakkeren mens du jobber med eiendelene (CSS, JS). Den ser faktisk på endringer i bestemte kataloger og samler / pakker koden til en enkelt fil. Ved å bruke denne tilnærmingen trenger du ikke å tenke på minifisering eller kompilering. Alt du trenger å gjøre er å bare sende den kompilerte statiske filen til brukeren. Dette øker ytelsen til søknaden din, fordi den bare tjener statiske filer og selvfølgelig gjør ting enklere. Du trenger ikke å sette noe på serveren din eller utføre unødvendig logikk.

Slik kan du sette opp og bruke eiendeler-pack.

Installasjon

Dette verktøyet er en Nodejs-modul, så du bør ha Node allerede installert. Hvis du ikke gjør det, gå bare til nodejs.org/download og ta tak i pakken for operativsystemet. Etter det:

npm installer -g assetpack

bruk

Modulen fungerer med JSON konfigurasjon. Når den brukes via kommandolinjen, bør du legge inn innstillingene i en .json fil.

Via kommandolinjen

Lag en assets.json fil og kjør følgende kommando i samme katalog:

assetspack

Hvis konfigurasjonsfilen din bruker et annet navn eller er i en annen katalog, bruker du:

assetspack --config [path to json file]

I kode

var AssetsPack = krever ("assetspack"); var config = [type: "css", se: ["css / src"], utdata: "tester / pakket / styles.css", minify: true, exclude: ["custom.css"]]; var pack = nytt AssetsPack (config, function () console.log ("AssetsPack ser på");); pack.onPack (funksjon () console.log ("AssetsPack gjorde jobben"););

konfigurasjon

Konfigurasjonen skal være en gyldig JSON-fil / -objekt. Det er bare en rekke objekter:

[(aktiv objekt), (aktiv objekt), (aktiv objekt), ...]

Asset Object

Den grunnleggende strukturen til eiendomsobjektet er som slik:

type: (filtype / streng, kan være css, js eller mindre for eksempel), se: (katalog eller kataloger for å se / streng eller rekke av strenger /), pakke: (katalog eller kataloger for pakking / streng eller rekkevidde av strenger /.), output: (bane til utdatafil / streng /), redusere: / boolean /, ekskluder: (rekke filnavn)

De pakke Eiendommen er ikke obligatorisk. Hvis du savner det, er verdien lik lik se. minify som standard er feil.

Her er noen eksempler:

Pakking CSS

type: "css", se: ["tester / data / css", "tester / data / css2"], pakke: ["tester / data / css", "tester / data / css2"], utdata: tester / pakket / styles.css ", bekreft: true, ekskluder: [" header.css "]

Pakker JavaScript

type: "js", se: "tester / data / js", pakke: ["tester / data / js"], utdata: "tester / pakket / scripts.js", minify: true, exclude: ["A .js "]

Pakking .mindre filer

Pakningen av .mindre filer er litt annerledes. De pakke eiendom er obligatorisk og det er i utgangspunktet inngangspunktet ditt. Du bør importere alle de andre .mindre filer der. De utelukke Eiendommen er ikke tilgjengelig her.

type: "mindre", se: ["tester / data / mindre"], pakke: "tester / data / mindre / index.less", utdata: "tester / pakket / stiler-mindre.css" 

Hvis du finner noen problemer, vennligst sjekk prøver / pakning-less.spec.js av depotet i GitHub.

Pakker andre filformater

eiendeler-pack Fungerer med filformat. For eksempel kan vi kombinere HTML-maler til en enkelt fil ved å gjøre noe slikt:

type: "html", se: ["tester / data / tpl"], utdata: "tester / pakket / template.html", ekskluderer: ["admin.html"]

Den eneste tingen du bør vite her er at det ikke er noen minifisering.


Konklusjon

Som front-end webutviklere bør vi forsøke å levere best mulig ytelse til brukerne. Tipsene ovenfor er ikke ment å dekke alle aspekter av aktivitetsorganisasjon og ytelse, men de er de jeg har håndtert personlig under mitt daglige arbeid. Vær så snill å dele noen av tipsene dine nedenfor, i kommentarene.