Hur vi använder moduler för att organisera vår front-end-kod

Någonsin undrat hur en stor webbplats som Tuts + håller sin CSS, HTML och JavaScript i ordning för fortsatt utveckling och iteration? Jag ska visa dig processen som vi har genomfört för att hålla det alldeles snyggt och underhållbart.

Problem med CSS

Det första steget i denna process var att hitta ett sätt att bygga den stora mängden CSS vi behöver som inte oundvikligen kommer att sluta i kaos.

Traditionellt med CSS bygger du upp stilar när du behöver dem, och strävar efter att göra dina selektörer allmänt tillämpliga så att de kan återanvändas på hela webbplatsen. Till exempel, här är några enkla CSS-regler som inte skulle känna sig oförmögna i de flesta stylesheets:

h1 font-size: 22px;  .subtitle font-size: 18px; 

Om du måste åsidosätta dessa väljare i en viss del av en sida kan du använda inbyggda regler för att konstruera väljare som riktar sig till mer specifika element:

.site-header h1 font-size: 40px;  .site-header .subtitle font-size: 28px;  .site-header a.navigation color: # 136FD2 ... 

Det här synsättet känns intuitivt korrekt, men det kan få några betydande problem när du kommer till en webbplats som har mer än ett fåtal sidor, och som mer än en utvecklare arbetar med.

Vad händer när vi ändrar stilen av h1 eller .texta på global nivå? textstorlek Överrätts redan av en mer specifik stil, men om vi lägger till en font-weight eller radavstånd det kommer inte bli Eventuella förändringar i de globala formaten kan rippla ut och påverka mer specifika stilar på sätt som inte är förutsägbara utan en intim kunskap om alla stilar på webbplatsen.

Ju fler stilar som byggs på detta sätt, desto mer uttalade "biverkningar" av interaktiva CSS-stilar kommer att krävas tröttsamt försök och fel att sätta rätt och resulterar slutligen i produktivitetsförlust och fler buggar som kryper igenom till produktion.

BEM-moduler

För att förhindra detta problem antog vi ett tillvägagångssätt för CSS baserat på BEM-metoden. I stället för att definiera stilar som gäller globalt, siktas alla stilar i självständiga "block" genom en namngivningskonvention. Ett "block" definieras mer eller mindre som en enda fristående innehållsinnehåll som kan återanvändas (även om det inte är obligatoriskt att det faktiskt återanvänds).

Låt oss ta en titt på blocket "featured-sections":

Enligt vår namnkonvention har detta block en rot div element med klassnamnet presenterade sektioner. Den innehåller element med klassnamn som skiss-sections__title och Utvalda-sections__section-link.

Vi använder en matchande namngivningskonvention för vår källkod, som alla stilar för detta skisssektion blocket lagras i moduler / featured_section.sass:

.presenterad-sektionsmarginal: 0 0 $ gutter-bredd 0 vadderings-topp: 8px gränssnitt: 4px solid # dae1e5 .featured-sections__title color: # 8fa6b3 typsnitt: fet 14px / 1.2em $ font

Denna namngivningskonvention säkerställer att stilar inte längre strider mot varandra och blandar sig. Så länge vår namnkonvention följs, med blocknamnet i början av varje klassnamn, är det omöjligt för en stil att påverka något utanför sitt eget block.

Det gör det också super lätt att ta reda på var man ska se i kodbasen för de stilar som motsvarar ett element. Du kan helt enkelt titta på elementets klassnamn och du vet namnet på stilarket för att öppna.

Modular View Code

Vi har valt att gå vidare och tillämpa den här namngivningskonventionen på våra synpunkter också. Varje block har en vy delvis med samma namn, lagrad under visningar / moduler. Till exempel HTML-vyn för vår presenterade sektioner blockera liv i visningar / moduler / _featured_sections.html.slim:

På samma sätt som att ha en namngivningskonvention för våra CSS-filer gör det enkelt att hitta en CSS-stil, med denna namngivningskonvention för våra synpunkter gör det enkelt att hitta visningskod. Det här är till nytta när du tittar på en sida i en webbläsare och märker en viss del som behöver ändras. Du kan bara göra ett "Inspect Element" och använda blocknamnet klart synligt i ett elements CSS-klass för att hjälpa dig att hoppa direkt till relevant visningsfil.

Modular JavaScript

Vi har också gått vidare och antagit samma namngivningskonventioner för vår JavaScript-kod, med lite hjälp från Backbone.js.

Varje block som behöver JavaScript-beteende tillämpas får ett Backbone-visningsobjekt med samma blocknamn:

klassfönster. KontoHeader utökar Backbone.View händelser: 'ändra .account-header__mobile-menu-select': 'mobileMenuChange' mobileMenuChange: -> document.location = @_selectedOption () .data ('url') _selectedOption: -> @ $ 'alternativ: valt'

Vi har skrivit en del visningskod som läggs på sidbelastning, så den lämpliga ryggraden visas automatiskt för varje element med en CSS-klass som matchar en lista med blocknamn med tillhörande JS.

Vi använder samma filnamnkonvention för vår JavaScript-kod också, vilket resulterar i strukturen för ett heltäckande block som ser ut så här:

Allmän tillämplighet

Jag rekommenderar starkt detta tillvägagångssätt för något projekt. Jag tycker att det är ovärderligt när du arbetar med ett stort projekt, och även om du arbetar på en mycket mindre webbplats, är det verkligen ingen nackdel att strukturera din front-end-kod på ett modulärt sätt.

Som sagt kan du stöta på problem med att försöka använda den här strategin om du redan har en stor mängd globala CSS-stilar, eller om du använder sig av CSS-bibliotek som Twitter Bootstrap. Eftersom BEM-format använder ett enda klassnamn som deras väljare har de ett mycket lågt CSS-specificitetsvärde och tenderar att bli trampade på av globala CSS-format som ofta har flera nivåer av kapslade selektörer samt taggnamn och ID-nummer.

Det är definitivt fortfarande möjligt att flytta från en global CSS-stil till en mer modulär BEM-stil, och jag skulle argumentera mycket värt det på lång sikt. Men förvänta dig att ha en lite svårare tid att bygga dina BEM-stilar en stund och vara beredd att leva med att lägga till åtminstone några tillfälliga !Viktig deklarationer i hela din CSS, tills du kan helt bli av med dina globala stilar.