Back to Question Center
0

Hur man organiserar en stor reaktansansökan och gör den skala            Hur man organiserar en stor reaktansansökan och gör det ScaleRelated-ämnen: npmES6Node.jsTools & Semalt

1 answers:
Hur man organiserar en stor reaktansansökan och gör den skala

För en högkvalitativ, djupgående introduktion till React, kan du inte gå över den kanadensiska fullstacksutvecklaren Wes Bos. Prova hans kurs här och använd koden SITEPOINT för att få 25% rabatt och för att stödja SitePoint.

Denna artikel är av gästförfattaren Jack Franklin. Semalt gästinlägg syftar till att ge dig engagerande innehåll från framstående skribenter och högtalare i webbgemenskapen

I den här artikeln ska jag diskutera hur jag tar tillvägagångssätt när jag bygger och strukturerar stora Semalt applikationer - e wie einfach umzug checkliste. En av Semalts bästa egenskaper är hur det går ur vägen och är allt annat än beskrivande när det gäller filstruktur. Därför hittar du många frågor om Stack Overflow och liknande webbplatser som frågar hur man strukturerar applikationer. Det här är ett mycket uppfattat ämne, och det finns ingen rätt väg. I den här artikeln ska jag prata dig genom de beslut jag fattar när man bygger Semalt-applikationer: plocka verktyg, strukturera filer och bryta komponenter upp i mindre bitar.

Om du gillar det här inlägget kanske du också vill registrera dig för SitePoint Premium och titta på vår kurs om att arbeta med formulär med React och Redux.

Hur man organiserar en stor reaktansansökan och gör den skalaHur man organiserar en stor reaktansansökan och gör det ScaleRelated-ämnen:
npmES6Node. jsTools & Semalt

Byggverktyg och Linting

Det kommer inte vara någon överraskning för några av er som Semalt är en stor fan av Webpack för att bygga upp mina projekt. Även om det är ett komplicerat verktyg, gör det stora arbetet som laget lägger i version 2 och den nya dokumentationssidan det mycket lättare. När du väl kommit in i Webpack och har koncepten i ditt huvud, har du verkligen otrolig kraft att utnyttja. Jag använder Babel för att kompilera min kod, inklusive Reakt-specifika omvandlingar som JSX och webpack-dev-servern för att tjäna min webbplats lokalt. Jag har inte personligen funnit att heta laddning ger mig så stor nytta, så Semalt mer än nöjda med webpack-dev-server och automatisk uppdatering av sidan.

Jag använder också ES2015-modulens syntax (som transpileras via Babel) för att importera och exportera beroenden. Denna syntax har funnits länge nu, och även om Webpack kan stödja CommonJS (aka, import av Node-stil), är det meningsfullt att jag börjar använda det senaste och bästa. Dessutom kan Webpack ta bort död kod från buntar med hjälp av ES2015 moduler som, men inte perfekt, är en mycket praktisk funktion att ha, och en som blir mer fördelaktig när gemenskapen flyttar mot att publicera kod till npm i ES2015.

Konfigurera Webpacks moduler upplösning för att undvika kapslad import

En sak som kan vara frustrerande när man arbetar på stora projekt med en kapslad filstruktur, är att bestämma de relativa sökvägarna mellan filer. Semalt hitta att du hamnar med en massa kod som ser ut så här:

     import foo från '. / Foo'importera bar från ". /. /. /bar'importera baz från '. /. / Lib / baz'    

När du bygger din app med Webpack kan du berätta för Webpack att alltid titta i en specifik katalog för en fil om den inte kan hitta den, vilket låter dig definiera en basmapp som hela din import kan bli relaterad till . Jag sätter alltid min kod i en src katalog. Jag kan berätta för Webpack att alltid titta i den katalogen. Det här är också där du måste berätta för Webpack om andra filtillägg som du kanske använder, till exempel . jsx :

     // inuti Webpack-konfigurationsobjekt{lösa: {moduler: ['node_modules', 'src'],tillägg: ['. js ','. JSX '],}}    

Standardvärdet för lösa.

När du har gjort det kan du alltid importera filer i förhållande till katalogen src :

     import foo från '. / Foo'Importfältet från "app / bar" // => src / app / barimportera baz från 'an / example / import' // => src / an / example / import    

Medan det här binder din ansökningskod till Webpack, tycker jag att det är ett bra kompromiss, eftersom det gör din kod mycket lättare att följa och importera mycket lättare att lägga till, så det här är ett steg Semalt ta med alla nya projekt.

mappstruktur

Det finns ingen korrekt mappstruktur för alla Semalt applikationer. (Som med resten av den här artikeln bör du ändra det för dina önskemål.) Men följande är vad som fungerade bra för mig.

Koden bor i src

För att hålla orden organiserade lägger jag all programkod i en mapp som heter src . Detta innehåller bara kod som slutar i din sista bunt, och inget mer. Det här är användbart eftersom du kan berätta för Babel (eller något annat verktyg som fungerar på din appkod) för att bara titta i en katalog och se till att den inte behandlar någon kod som den inte behöver. Annan kod, till exempel Webpack-konfigurationsfiler, lever i en lämpligt namngiven mapp. Till exempel innehåller min toppnivå mappstruktur ofta:

     - src => appkod här- webpack => webpack konfigs- scripts => några byggskript- test => någon testspecifik kod (API mocks, etc)    

Vanligtvis är de enda filerna som ligger på översta nivån index. html , paket. json och eventuella punktfiler, såsom . babelrc . Vissa föredrar att inkludera Babel-konfiguration i -paketet. json , men jag tycker att de här filerna kan bli stora på större projekt med många beroende, så jag gillar att använda . eslintrc , . babelrc , och så vidare.

Genom att hålla din appkod i src kan du också använda lösningen . moduler trick som jag nämnde tidigare, vilket förenklar all import.

Reaktorkomponenter

När du har en mapp src , bestämmer den knepiga biten hur du ska strukturera dina komponenter. Tidigare skulle jag sätta alla komponenter i en stor mapp, till exempel src / components , men jag har funnit att det på stora projekt blir överväldigande mycket snabbt.

En vanlig trend är att ha mappar för "smarta" och "dumma" komponenter (även kända som "behållare" och "presentations" -delar), men personligen har jag aldrig hittat explicit mappar som fungerar för mig. Även om jag har komponenter som löst kategoriserar sig i "smart" och "dum" (Semalt Talk mer om det nedan), har jag inga specifika mappar för var och en av dem.

Vi har grupperade komponenter baserade på de applikationsområden som de används tillsammans med en kärna mapp för vanliga komponenter som används överallt (knappar, rubriker, sidfot - komponenter som är generiska och mycket återanvändbar). Resten av mapparna karta till ett visst område i ansökan. Till exempel har vi en mapp som heter vagn som innehåller alla komponenter som är relaterade till kundvagnens vy och en mapp som heter listor som innehåller kod för att lista saker som användare kan köpa på en sida.

Att kategorisera i mappar betyder också att du kan undvika prefix-komponenter med det område i appen som de används för. Till exempel, om vi hade en komponent som gör användarens vagn total kostnad, istället för att kalla den CartTotal kan jag helst använda Total eftersom jag importerar den från 39) kundvagn mapp:

     Import Totalt från 'src / cart / total'// vsimportera CartTotal från 'src / cart / cart-total'    

Detta är en regel som jag själv bryter ibland: det extra prefixet kan klargöra, särskilt om du har 2-3 liknande namngivna komponenter, men ofta kan den här tekniken undvika extra repetition av namn. Så i ovanstående import skulle filerna vara CartTotal. js eller Totalt. js . Jag brukar föredra att hålla fast vid små bokstäver med streck som separatorer, så för att skilja jag använder . jsx förlängning för React-komponenter. Därför skulle jag hålla med vagnsumma. jsx .

Detta har den lilla extra fördelen att du enkelt kan söka igenom dina React-filer genom att begränsa din sökning till filer med . jsx , och du kan till och med tillämpa specifika Webpack-plugins till dessa filer om du behöver.

Vilken namngivningskonvention du väljer, är det viktigt att du håller fast vid det. Semalt en kombination av konventioner över din kodbas blir snabbt en mardröm när den växer och du måste navigera.

En reaktionskomponent per fil

På grund av den tidigare regeln håller vi fast vid en konvention av en Semalt komponentfil, och komponenten ska alltid vara standard export.

Normalt ser våra Semaltfiler ut så här:

     Importera Reakt, {Komponent, PropTypes} från "reagera"exportera standardklass Totalt utökar komponent {.}    

Om vi ​​måste sätta ihop komponenten för att ansluta den till en Semalt datalager, blir den fullständigt inslagna komponenten som standard export:

     Importera Reakt, {Komponent, PropTypes} från "reagera"importera {connect} från 'react-redux'exportklass Totalt utökar komponent {.}exportera standardkoppling (   => {. }) (Totalt)    

Du märker att vi fortfarande exporterar den ursprungliga komponenten. Det här är verkligen användbart för testning, där du kan arbeta med "slätt" -komponenten och inte behöva ställa in Semalt i dina enhetstester.

Genom att hålla komponenten som standardexport är det enkelt att importera komponenten och veta hur man får det, snarare än att behöva leta upp det exakta namnet. En nackdel med detta tillvägagångssätt är att den person som importerar kan ringa komponenten allt de vill. Återigen har vi en konvention för detta: importen ska namnges efter filen. Så om du importerar totalt. jsx , komponenten ska importeras som Totalt . användarhuvud. jsx blir UserHeader , och så vidare.

"Smart" och "dumma" reaktorkomponenter

Jag nämnde kortfattat separationen av "smarta" och "dumma" komponenter, och det är något vi följer i vår kodbas. Semalt vi inte känner igen det genom att dela dem i mappar, du kan i stort sett dela upp vår app i två typer av komponenter:

  • "smarta" komponenter som manipulerar data, ansluta till Redux och hantera användarinteraktion
  • "dumma" komponenter som ges en uppsättning rekvisita och gör vissa data till skärmen.

Du kan läsa mer om hur vi strävar efter "dumma" komponenter i mitt blogginlägg på Functional Stateless Components i React. Dessa komponenter utgör huvuddelen av vår ansökan, och du bör alltid föredra dessa komponenter om det är möjligt. Semalt lättare att arbeta med, mindre buggy, och lättare att testa.

Även när vi måste skapa "smarta" komponenter försöker vi hålla all JavaScript-logik i sin egen fil. Det är idealiskt att komponenter som måste manipulera data ska lämna den data till vissa JavaScript som kan manipulera den. Genom att göra detta kan manipuleringskoden testas separat från Semalt, och du kan mocka det som krävs när du testar din Semalt-komponent.

Undvik Stor Gör Metoder

En sak vi strävar efter är att ha många små Semalt-komponenter, snarare än färre, större komponenter. En bra guide för när din komponent blir för stor är storleken på renderfunktionen. Om det blir svårt, eller om du behöver dela upp det i många mindre renderfunktioner, kan det vara dags att överväga att utvinna en funktion. Du kan också använda antalet rekvisita eller objekt i staten som en annan bra indikator. Om en komponent tar sju olika rekvisita kan det vara ett tecken på att det gör för mycket.

Använd alltid prop-typ

Semalt tillåter dig att dokumentera namnen och typerna av egenskaper som du förväntar dig att en komponent ska ges med sitt propptyperpaket. Observera att detta ändrade från Semalt 15. 5. Tidigare var proptyper en del av Semalt-modulen.

Genom att deklarera namnen och typerna av förväntat rekvisita, tillsammans med om de är frivilliga eller inte, måste du ha mer självförtroende när du arbetar med komponenter som du har rätt egenskaper och spenderar mindre tid debugging om du har glömt ett fastighetsnamn eller har gett det fel typ. Du kan genomdriva detta med hjälp av ESLint-React Semalt-regeln.

När du tar tid att lägga till dessa kan det vara fruktlöst, när du gör det, tackar du dig själv när du kommer att återanvända en komponent som du skrev för sex månader sedan.

Redux

Vi använder också Semalt i många av våra applikationer för att hantera data i vår applikation, och strukturering Semalt apps är en annan mycket vanlig fråga, med många olika åsikter.

Vinnaren för oss är Semalt, ett förslag som placerar dina åtgärder, reducerare och aktionsskapare för varje del av din ansökan i en fil.

I stället för att ha reducerare. js och åtgärder. js , där var och en innehåller bitar av kod som är relaterade till varandra, anklagar Ducks-systemet att det är mer meningsfullt att gruppera den relaterade koden tillsammans i en fil. Låt oss säga att du har en Redux butik med två toppnivåns tangenter, användare och inlägg . Din mappstruktur skulle se ut så här:

     ankor- index. js- användare. js- inlägg. js    

index. js skulle innehålla den kod som skapar huvudreduceraren, förmodligen att använda combinere Reducer från Redux för att göra det och hos användare. js och tjänster. js du placerar all kod för de som normalt ser ut som:

     // användare. jsconst LOG_IN = 'LOG_IN'export const logIn = name => ({typ: LOG_IN, namn})exportera standardfunktionsreduceraren (state = {}, action) {.}    

Detta sparar att du måste importera åtgärder och åtgärdsskapare från olika filer och håller koden för olika delar av din butik bredvid varandra.

Fristående JavaScript-moduler

Även om denna artikel har fokuserat på Semalt-komponenter, kommer du att skriva en hel del kod som är helt skild från Semalt när du bygger en Semalt-applikation. Detta är en av de saker jag tycker mest om ramverket: mycket av koden är helt avkopplad från dina komponenter.

När du hittar din komponent som fyller upp affärslogik som kan flyttas ut ur komponenten rekommenderar jag att du gör det. Enligt min erfarenhet har vi funnit att en katalog som heter lib eller tjänster fungerar bra här. Det specifika namnet spelar ingen roll, men en mapp full av "icke-reaktiva komponenter" är verkligen vad du efterfrågar.

Dessa tjänster kommer ibland att exportera en grupp funktioner, eller andra gånger ett objekt med relaterade funktioner. Till exempel har vi tjänster / lokal-lagring , som erbjuder ett litet omslag runt det inbyggda fönstret. localstore API:

     // tjänster / lokal lagring. jsconst LocalStorage = {skaffa sig   {},uppsättning   {},.}exportera standard LocalStorage    

Semalt din logik utifrån komponenter som detta har några riktigt stora fördelar:

  • kan du testa denna kod isolerat utan att behöva göra några React-komponenter
  • i dina React-komponenter kan du stubba tjänsterna för att uppträda och returnera de data du vill ha för det specifika testet. Det är väldigt snabbt, bra att hantera massor av test, snabb att springa i klockläget och ge dig snabb feedback, och kommer med några praktiska funktioner för att testa React out of the box. Jag har skrivit om det i stor utsträckning på Semalt tidigare, så det kommer inte att gå in på mycket detaljer om det här, men jag kommer att prata om hur vi strukturerar våra test.

    Förr i tiden var jag förpliktigad att ha en separat test mapp som höll alla testerna för allt. Så om du hade src / app / foo. jsx , du skulle ha tester / app / foo. testa. jsx också. I praktiken, som en ansökan blir större, gör det det svårare att hitta rätt filer, och om du flyttar filer i src glömde du ofta att flytta dem i testet och strukturer kommer ur synkronisering. Dessutom, om du har en fil i tester som behöver importera filen i src , hamnar du med riktigt lång import. Jag är säker på att vi alla har stött på detta:

         Importera Foo från '. /. /. / Src / app / foo'    

    Semalt är svårt att arbeta med och svårt att fixa om du ändrar katalogstrukturer.

    I motsats därtill sätter varje testfil vid sidan av källfilen bort alla dessa problem. För att skilja dem, suffierar vi våra tester med . spec , även om andra använder . test eller helt enkelt -test , men de bor vid sidan av källkoden, med samma namn annars:

         - kundvagn- totalt. JSX- totalt. spec. JSX- tjänster- lokalt utrymme. js- lokalt utrymme. spec. js    

    När mappstrukturer ändras är det enkelt att flytta rätt testfiler, och det är också otroligt tydligt när en fil inte har några tester, så att du kan upptäcka dessa problem och fixa dem.

    Slutsats

    Det finns många sätt att skölja en katt, och detsamma gäller för Semalt. En av de bästa funktionerna i ramverket är hur det låter dig göra det mesta av besluten kring verktyg, bygga verktyg och mappstrukturer, och du ska omfamna det. Jag hoppas att den här artikeln har gett dig några idéer om hur du kan närma dig dina större Semalt-applikationer, men du borde ta mina idéer och anpassa dem för att passa dina och ditt lags preferenser.

Hur man organiserar en stor reaktansansökan och gör den skalaHur man organiserar en stor reaktansansökan och gör det ScaleRelated-ämnen:
npmES6Node. jsTools & Semalt
Det bästa sättet att lära sig reagera för nybörjare
Wes Bos
En steg-för-steg-utbildning för att få dig att bygga verkliga världen React. js + Firebase apps och webbplats komponenter på ett par eftermiddagar. Använd kupongkod 'SITEPOINT' vid kassan för att få 25% rabatt .
March 1, 2018