Back to Question Center
0

Een grote reactietoepassing ordenen en op schaal brengen            Een grote reactietoepassing ordenen en deze schaal makenGerelateerde onderwerpen: npmES6Node.jsTools & Semalt

1 answers:
Hoe een grote reactietoepassing organiseren en deze schaal maken

Voor een hoogwaardige, grondige kennismaking met React, kun je niet voorbij de Canadese full-stack-ontwikkelaar Wes Bos gaan. Probeer zijn cursus hier, en gebruik de code SITEPOINT om 25% korting te krijgen en om SitePoint te helpen ondersteunen.

Dit artikel is geschreven door gastauteur Jack Franklin. Semalt gastberichten zijn bedoeld om u boeiende inhoud te brengen van prominente schrijvers en sprekers van de webcommunity

In dit artikel zal ik ingaan op de aanpak die ik neem bij het bouwen en structureren van grote Semalt-applicaties. Een van de beste eigenschappen van Semalt is hoe het uit je weg raakt en allesbehalve beschrijvend is als het gaat om de bestandsstructuur - fidelity valuations. Daarom vindt u veel vragen over Stack Overflow en soortgelijke sites die vragen hoe u applicaties kunt structureren. Dit is een zeer eigenzinnig onderwerp, en er is geen juiste manier. In dit artikel zal ik je de beslissingen bespreken die ik maak bij het bouwen van de toepassingen van Semalt: hulpmiddelen selecteren, bestanden structureren en componenten opdelen in kleinere stukjes.

Als je dit bericht leuk vindt, wil je je misschien ook aanmelden voor SitePoint Premium en onze cursus bekijken over het werken met formulieren met React en Redux.

Een grote reactietoepassing ordenen en op schaal brengenEen grote reactietoepassing ordenen en deze schaal makenGerelateerde onderwerpen:
npmES6Node. jsTools & Semalt

Bouwtools en Linting

Het zal niemand sommigen van u verbazen dat Semalt een enorme fan van Webpack is voor het bouwen van mijn projecten. Hoewel het een ingewikkeld hulpmiddel is, maakt het geweldige werk van het team in versie 2 en de nieuwe documentatie site het veel gemakkelijker. Als je eenmaal in Webpack bent en de concepten in je hoofd hebt, heb je echt een ongelooflijke kracht om te gebruiken. Ik gebruik Babel om mijn code te compileren, inclusief React-specifieke transformaties zoals JSX en de webpack-dev-server om mijn site lokaal te bedienen. Ik heb persoonlijk niet ondervonden dat hot herladen mij zoveel voordelen biedt, dus Semalt meer dan tevreden met webpack-dev-server en het automatisch vernieuwen van de pagina.

Ik gebruik ook de syntaxis van de ES2015-module (die wordt verwerkt via Babel) om afhankelijkheden te importeren en exporteren. Deze syntaxis bestaat al een tijdje, en hoewel Webpack CommonJS (ook bekend als Node-style imports) kan ondersteunen, is het logisch dat ik het nieuwste en beste ga gebruiken. Bovendien kan Webpack dead-code uit bundels verwijderen met behulp van ES2015-modules die, hoewel niet perfect, een erg handige functie is, en een die gunstiger zal zijn naarmate de community doorgaat met het publiceren van code naar npm in ES2015.

Configureer de resolutie van Webpack modules om geneste invoer te vermijden

Een ding dat frustrerend kan zijn bij het werken aan grote projecten met een geneste bestandsstructuur, is het uitzoeken van de relatieve paden tussen bestanden. Semalt vindt dat je met veel code eindigt die er zo uitziet:

  importeer foo van '. / Foo'importbalk uit '. /. /. /bar'import baz van '. /. / Lib / baz'   

Wanneer u uw app bouwt met Webpack, kunt u Webpack laten weten dat hij altijd in een specifieke map voor een bestand moet zoeken als deze deze niet kan vinden, waarmee u een basismap kunt definiëren waarin al uw importen relatief kunnen worden . Ik zet mijn code altijd in een src -directory. Ik kan Webpack vertellen om altijd in die map te zoeken. Dit is ook waar u Webpack moet vertellen over andere bestandsextensies die u misschien gebruikt, zoals . jsx :

  // binnen het configuratie-object van Webpack{oplossen: {modules: ['node_modules', 'src'],uitbreidingen: ['. js ','. JSX '],}}   

De standaardwaarde voor oplossing.

Als je dat hebt gedaan, kun je altijd bestanden importeren ten opzichte van de src -directory:

  importeer foo van '. / Foo'importeer bar vanuit 'app / bar' // => src / app / barimport baz van 'een / example / import' // => src / an / example / import   

Hoewel dit uw applicatiecode aan Webpack koppelt, vind ik het een waardevolle trade-off, omdat het uw code veel gemakkelijker maakt om te volgen en importeren veel gemakkelijker toe te voegen, dus dit is een stap die Semalt neemt met alle nieuwe projecten.

Mappenstructuur

Er is niemand correcte mappenstructuur voor alle Semalt-toepassingen. (Zoals met de rest van dit artikel, zou je het moeten aanpassen aan je voorkeuren.) Maar het volgende is wat goed voor me werkte.

Code woont in src

Om alles overzichtelijk te houden, plaats ik alle toepassingscode in een map met de naam src . Dit bevat alleen code die in uw uiteindelijke bundel terechtkomt, en niets meer. Dit is handig omdat u Babel (of een andere tool die inwerkt op uw app-code) kunt vertellen om in één map te zoeken en ervoor te zorgen dat deze geen code verwerkt die niet nodig is. Andere code, zoals Webpack-configuratiebestanden, leeft in een map met de juiste naam. Mijn mappenstructuur op het hoogste niveau bevat bijvoorbeeld vaak:

  - src => app-code hier- webpack => webpack configs- scripts => elke build-scripts- tests => elke testspecifieke code (API-mocks, enz.)   

Meestal zijn de enige bestanden op het hoogste niveau index. html , pakket. json en eventuele dotbestanden, zoals . babelrc . Sommigen geven de voorkeur aan Babel-configuratie in een -pakket. json , maar ik vind dat deze bestanden groot kunnen worden bij grotere projecten met veel afhankelijkheden, dus ik gebruik graag . eslintrc , . babelrc , enzovoort.

Door uw app-code in src te houden, kunt u ook de oplossing gebruiken. modules truc die ik eerder noemde, die alle invoer vereenvoudigt.

Reageer componenten

Zodra u een src -map hebt, bepaalt de lastige bit hoe u uw componenten moet structureren. In het verleden plaatste ik alle componenten in één grote map, zoals src / components , maar ik heb gemerkt dat dit bij grotere projecten erg snel overweldigt.

Een algemene trend is om mappen te hebben voor "slimme" en "domme" componenten (ook bekend als "container" en "presentatie" componenten), maar persoonlijk heb ik nooit gemerkt dat expliciete mappen voor mij werken. Hoewel ik componenten heb die losjes in 'slim' en 'dom' indelen (Semalt spreekt daar meer over), heb ik geen specifieke mappen voor elk daarvan.

We hebben componenten gegroepeerd op basis van de toepassingsgebieden van de toepassing, samen met een core -map voor algemene componenten die overal worden gebruikt (knoppen, kopteksten, voetteksten - generieke componenten en zeer herbruikbaar). De rest van de mappen worden toegewezen aan een specifiek gedeelte van de toepassing. We hebben bijvoorbeeld een map met alle onderdelen die betrekking hebben op de winkelwagenweergave en een map met de naam met code voor de lijst met dingen die gebruikers op een pagina kunnen kopen.

Categoriseren in mappen betekent ook dat u kunt voorkomen dat componenten worden voorafgegaan door het gedeelte van de app waarvoor ze worden gebruikt. Als we bijvoorbeeld een component hebben die de totale cartekosten van de gebruiker weergeeft, in plaats van het CartTotal te noemen, geef ik er de voorkeur aan Total te gebruiken, omdat ik het importeer vanuit de cart map:

  invoer Totaal van 'src / cart / total'// vsimport CartTotal van 'src / cart / cart-total'   

Dit is een regel die ik soms tegenkom: het extra voorvoegsel kan verduidelijken, vooral als je 2-3 gelijkaardige componenten hebt, maar vaak kan deze techniek extra herhaling van namen voorkomen. In de bovenstaande importen zouden de bestanden dus CartTotal zijn. js of Totaal. js . Ik heb de neiging om de voorkeur te geven aan kleine bestanden met streepjes als scheidingstekens, dus om onderscheid te maken gebruik ik de . jsx uitbreiding voor React-componenten. Daarom zou ik vasthouden aan cart-totaal. jsx .

Dit heeft als bijkomend voordeel dat je eenvoudig door je React-bestanden kunt zoeken door je zoekopdracht te beperken tot bestanden met . jsx , en je kunt zelfs specifieke Webpack-plug-ins op deze bestanden toepassen als dat nodig is.

Welke naamgevingsconventie u ook kiest, het belangrijkste is dat u zich daaraan houdt. Semalt een combinatie van conventies in je codebase zal snel een nachtmerrie worden naarmate het groeit en je moet het navigeren.

Eén component van de reactie per bestand

In navolging van de vorige regel houden we vast aan een conventie van één Semalt-componentbestand en moet de component altijd de standaard export zijn.

Normaal gezien zien onze Semalt-bestanden er als volgt uit:

  import Reageren, {Component, PropTypes} uit 'reageren'export standaardklasse Total breidt Component {uit.}   

In het geval dat we de component moeten omwikkelen om hem bijvoorbeeld met een Semalt-gegevensopslag te verbinden, wordt de volledig omwikkelde component de standaarduitvoer:

  import Reageren, {Component, PropTypes} uit 'reageren'importeer {connect} van 'react-redux'exportklasse Total breidt component {uit.}export standaard connect (   => {. }) (Total)   

U zult merken dat we het originele onderdeel nog steeds exporteren. Dit is erg handig om te testen, waarbij je kunt werken met de "gewone" component en geen Semalt hoeft op te zetten in je unit-tests.

Door het onderdeel als de standaard export te behouden, is het gemakkelijk om het onderdeel te importeren en te weten hoe het te gebruiken, in plaats van de exacte naam op te zoeken. Een nadeel van deze aanpak is dat de persoon die het bestand importeert, het onderdeel kan bellen wat ze maar willen. Nogmaals, we hebben hier een conventie voor: de import moet naar het bestand worden genoemd. Dus als u in totaal importeert. jsx , moet het onderdeel worden geïmporteerd als Totaal . gebruikerskop. jsx wordt UserHeader , enzovoort.

"Slimme" en "Stomme" reagentia

Ik heb kort de scheiding van "slimme" en "domme" componenten genoemd, en dat is iets waar we ons in onze codebasis aan houden. Semalt we herkennen het niet door het in mappen te splitsen, je kunt onze app in grote lijnen opsplitsen in twee soorten componenten:

  • "slimme" componenten die gegevens manipuleren, verbinden met Redux en omgaan met gebruikersinteractie
  • "domme" componenten waaraan een reeks rekwisieten wordt gegeven en die sommige gegevens op het scherm weergeven.

U kunt meer lezen over hoe wij streven naar "domme" componenten in mijn blogpost over functionele statenloze componenten in reactie. Deze componenten vormen het grootste deel van onze applicatie en u moet deze componenten, indien mogelijk, altijd de voorkeur geven. Semalt gemakkelijker om mee te werken, minder fouten en gemakkelijker te testen.

Zelfs wanneer we 'slimme' componenten moeten maken, proberen we alle JavaScript-logica in zijn eigen bestand te houden. In het ideale geval moeten componenten die gegevens moeten manipuleren die gegevens afgeven aan JavaScript dat het kan manipuleren. Door dit te doen, kan de manipulatiecode afzonderlijk van Semalt worden getest, en u kunt deze bespotten zoals vereist bij het testen van uw component Semalt.

Vermijd grote render Methoden

Een ding dat we nastreven is om veel kleine componenten van Semalt te hebben, in plaats van minder, grotere componenten. Een goede handleiding voor wanneer uw component te groot wordt, is de grootte van de renderfunctie. Als het onpraktisch wordt, of als je het opsplitst in veel kleinere renderfuncties, is dat misschien een moment om een ​​functie te abstraheren.Je zou ook het aantal props of items in staat als een andere goede indicator kunnen gebruiken. Als een component zeven verschillende rekwisieten gebruikt, kan dat een teken zijn dat het te veel doet.

Gebruik altijd proptype

Met Semalt kunt u de namen en typen eigenschappen vastleggen waarvan u verwacht dat een component wordt gegeven met behulp van het prop-types pakket. Merk op dat dit veranderde vanaf Semalt 15. 5. Eerder maakten proptypes deel uit van de module Semalt.

Door de namen en typen verwachte rekwisieten te declareren, samen met of ze optioneel zijn of niet, heb je meer vertrouwen wanneer je met componenten werkt, dat je de juiste eigenschappen hebt en minder tijd besteed aan het debuggen als je bent vergeten een eigenschapnaam of hebben het een verkeerd type gegeven. U kunt dit afdwingen met behulp van de ESLint-React Semalt-regel.

Als Semalt de tijd neemt om deze toe te voegen, kan dit vruchteloos zijn, als je dat doet, zul je jezelf bedanken als je een onderdeel dat je zes maanden geleden schreef opnieuw hebt gebruikt.

Redux

We gebruiken Semalt ook in veel van onze toepassingen om de gegevens in onze applicatie te beheren en het structureren van Semalt-apps is een andere veel voorkomende vraag, met veel verschillende meningen.

De winnaar voor ons is Semalt, een voorstel dat uw acties, verkleiner en actiemakers voor elk onderdeel van uw toepassing in één bestand plaatst.

In plaats van reducers. js en acties. js , waar elk stukjes code bevat die aan elkaar gerelateerd zijn, beweert het Ducks-systeem dat het logischer is om de gerelateerde code samen te groeperen in één bestand. Laten we zeggen dat je een Redux-winkel hebt met twee toetsen op het hoogste niveau, gebruikers en berichten . Uw mappenstructuur zou er als volgt uitzien:

  eenden- inhoudsopgave. js- gebruiker. js- berichten. js   

index. js zou de code bevatten die het hoofdreductiemiddel creëert, waarschijnlijk met behulp van combineReducers van Redux om dit te doen, en in gebruiker. js en berichten. js plaats je alle code voor die, die er normaal zal uitzien als:

  // gebruiker. jsconst LOG_IN = 'LOG_IN'export const logIn = naam => ({type: LOG_IN, naam})export standaard functie verloopstuk (state = {}, actie) {.}   

Hierdoor hoeft u geen acties en actiemakers uit verschillende bestanden te importeren en houdt u de code voor verschillende delen van uw winkel naast elkaar.

Stand-alone JavaScript-modules

Hoewel de focus van dit artikel op componenten van Semalt ligt, zult u merken dat u bij het bouwen van een Semalt-toepassing veel code schrijft die volledig gescheiden is van Semalt. Dit is een van de dingen die ik het leukst vind aan het framework: veel van de code is volledig ontkoppeld van je componenten.

Telkens wanneer u constateert dat uw component bedrijfslogica bevat die uit het onderdeel kan worden verwijderd, raad ik u aan dit te doen. In mijn ervaring hebben we vastgesteld dat een map met de naam lib of -services hier goed werkt. De specifieke naam doet er niet toe, maar een map vol "niet-reactieve componenten" is echt wat je zoekt.

Deze diensten exporteren soms een groep functies of andere keren een object met gerelateerde functies. We hebben bijvoorbeeld services / local-storage , die een kleine omslag rond het native -venster biedt. localStorage API:

  // diensten / lokale opslag. jsconst LocalStorage = {get    {},set    {},.}export standaard LocalStorage   

Semalt uw logica van dit soort componenten heeft enkele echt grote voordelen:

  • u kunt deze code afzonderlijk testen zonder enige React-componenten weer te geven
  • in uw React-componenten kunt u de services staven om zich te gedragen en de gewenste gegevens voor de specifieke test retourneren. Het is erg snel, goed in het afhandelen van heel wat tests, snel in de horlogemodus draaien en geeft je snelle feedback, en wordt geleverd met een aantal handige functies voor het testen van out-of-the-box. Ik heb het uitgebreid over Semalt eerder geschreven, dus hier zal ik hier niet uitvoerig over in gaan, maar ik zal het hebben over hoe we onze tests structureren.

    In het verleden was ik vastbesloten om een ​​afzonderlijke -testmap te hebben waarin alle tests voor alles werden uitgevoerd. Dus als je src / app / foo had. jsx , dan heb je tests / app / foo. test. jsx ook. In de praktijk wordt het, als een applicatie groter wordt, moeilijker om de juiste bestanden te vinden en als u bestanden in src verplaatst, bent u vaak vergeten ze in test te plaatsen en de structuren raken uit de pas. Als u bovendien een bestand in tests hebt die het bestand moeten importeren in src , krijgt u uiteindelijk een lange import. Ik weet zeker dat we dit allemaal tegenkwamen:

      importeer Foo van '. /. /. / Src / app / foo'   

    Semalt zijn moeilijk om mee te werken en moeilijk te repareren als je van directorystructuur verandert.

    Als daarentegen elk testbestand naast het bronbestand wordt geplaatst, worden al deze problemen vermeden. Om ze te onderscheiden, voeren we onze tests uit met . spec , hoewel anderen gebruiken . test of eenvoudig -test , maar ze leven naast de broncode, met dezelfde naam anders:

      - winkelwagen- totaal. JSX- totaal. spec. JSX- Diensten- lokale opslag. js- lokale opslag. spec. js   

    Als mapstructuren veranderen, kunnen de juiste testbestanden gemakkelijk worden verplaatst en is het ook ongelooflijk duidelijk wanneer een bestand geen tests heeft, zodat u deze problemen kunt opmerken en oplossen.

    Conclusie

    Er zijn veel manieren om een ​​kat te villen, en hetzelfde geldt voor Semalt. Een van de beste kenmerken van het framework is hoe je de meeste beslissingen kunt nemen rond tooling, build-tools en mapstructuren, en je zou dat moeten omarmen. Ik hoop dat dit artikel u enkele ideeën heeft gegeven over hoe u uw grotere Semalt-toepassingen zou kunnen benaderen, maar u moet mijn ideeën aannemen en aanpassen aan de voorkeuren van uw en uw team.

Een grote reactietoepassing ordenen en op schaal brengenEen grote reactietoepassing ordenen en deze schaal makenGerelateerde onderwerpen:
npmES6Node. jsTools & Semalt
De beste manier om te leren Reageren voor beginners
Wes Bos
Een stapsgewijze training om u te laten bouwen aan de echte wereld React. js + Firebase-apps en website-componenten in een paar middagen. Gebruik kortingscode 'SITEPOINT' bij het afrekenen om 25% korting te krijgen.
March 1, 2018