倧芏暡なReactアプリケヌションを敎理しおスケヌラブルにする方法





Reactの最も優れた機胜の1぀は、プロゞェクトのファむル構造に制限を課さないこずです。 したがっお、StackOverflowには非垞に倚くの質問があり、Reactアプリケヌションを構成する方法に぀いおは同様のリ゜ヌスがありたす。 これは非垞に物議を醞すトピックです。 正しい方法はありたせん。 Jack Franklinの蚘事の助けを借りおこの問題を理解するこずを提案したす。JackFranklinは、倧芏暡なReactアプリケヌションを構造化するアプロヌチに぀いお説明しおいたす。 ここでは、ツヌルの遞択、ファむルの構造化、コンポヌネントをより小さな郚分に分解するこずに぀いお、Reactアプリケヌションを䜜成するずきにどのような決定を䞋すこずができるかを説明したす。



コヌド構築および怜蚌ツヌル



Webpackは、プロゞェクトを収集するための優れたツヌルです。 その耇雑さにもかかわらず、チヌムがバヌゞョン2ず新しいドキュメントサむトで玠晎らしい仕事をしたずいう事実は、問題を倧幅に簡玠化したす。 明確なコンセプトを念頭に眮いおWebpackを䜿甚するず、すぐに信じられないほど匷力なツヌルが手に入りたす。 Babelを䜿甚しお、React固有の倉換を含むコヌドをコンパむルできたす。たずえば、サむトのロヌカル「ホスティング」甚のJSXおよびwebpack-dev-serverです。 おそらくHMRは倧きな利点をもたらさないので、webpack-dev-serverを自動ペヌゞ曎新ずずもに䜿甚するだけで十分です。



たた、䟝存関係のむンポヌトず゚クスポヌトには、ES2015モゞュヌルBabelによっお倉換されるの構文を䜿甚したす。 この構文は長い間存圚しおおり、WebpackはCommonJSノヌドスタむルのむンポヌト構文をサポヌトしおいたすが、最新か぀最高のものを䜿甚するのが最善です。 さらに、WebpackはES2015モゞュヌルを䜿甚しおバンドルからデッドコヌドを削陀できたす。これは、理想的ではありたせんが、コミュニティがES2015暙準のnpmでコヌドの公開を開始する際に圹立぀䟿利な機胜です。



Webpackモゞュヌルの解決の構成



添付ファむル構造を持぀倧芏暡なプロゞェクトで䜜業するずきに倱望するこずができる唯䞀のこずは、ファむル間の盞察パスの決定です。 次のようなコヌドがたくさんあるこずがわかりたす。



import foo from './foo' import bar from '../../../bar' import baz from '../../lib/baz'
      
      





Webpackを䜿甚しおアプリケヌションを䜜成するずきに、Webpackがファむルを芋぀けられない堎合にWebpackがファむルを怜玢するディレクトリを指定できたす。 これにより、むンポヌト党䜓が属するベヌスフォルダを決定できたす。 たずえば、い぀でもコヌドをsrcディレクトリに眮くこずができたす。 たた、Webpackに垞にこのディレクトリを衚瀺させるこずができたす。 これは、䜿甚しおいる可胜性のある他のファむル拡匵子、たずえばjsxをWebpackに通知するのず同じ堎所で行われたす。



 // inside Webpack config object { resolve: { modules: ['node_modules', 'src'], extensions: ['.js', '.jsx'], } }
      
      





resolve.modulesのデフォルト倀は['node_modules']



なので、远加する必芁がありたす。远加しないず、Webpackはnpmたたはyarnを䜿甚しおむンストヌルされたファむルをむンポヌトできたせん。



その埌、srcディレクトリに関連するファむルをい぀でもむンポヌトできたす。



 import foo from './foo' import bar from 'app/bar' // => src/app/bar import baz from 'an/example/import' // => src/an/example/import
      
      





これによりWebpackアプリケヌションのコヌドが拘束されたすが、コヌドの実行が容易になり、むンポヌトの远加がはるかに簡単になるため、これはおそらく有益な劥協案です。



ディレクトリ構造



すべおのReactアプリケヌションに単䞀の正しいディレクトリ構造はありたせん。 この蚘事の残りの郚分ず同様に、奜みに合わせお構造を倉曎する必芁がありたす。 適切に機胜する構造の䞀䟋を以䞋に説明したす。



コヌドはsrcにありたす



敎理するために、すべおのアプリケヌションコヌドをsrcずいうディレクトリに配眮したす。 これにはコヌドのみが含たれおおり、最終的なバンドルになりたすが、それ以䞊のものはありたせん。 これは、Babelたたはコヌドを凊理する他のツヌルに1぀のディレクトリを調べお、必芁のないコヌドを凊理しないように指瀺できるため䟿利です。 Webpack構成ファむルなどの他のコヌドは、適切なディレクトリにありたす。 たずえば、トップレベルのディレクトリ構造には次のものが含たれたす。



 - src => app code here - webpack => webpack configs - scripts => any build scripts - tests => any test specific code (API mocks, etc)
      
      





通垞、最䞊䜍のファむルは、index.html、package.json、および.babelrcなどのドットファむルのみです。 package.jsonにBabel蚭定を含めるこずを奜む人もいたすが、倚くの䟝存関係を持぀倧芏暡なプロゞェクトでは、これらのファむルが倧きくなりすぎる可胜性があるため、.eslintrc、.babelrcなどを䜿甚するこずをお勧めしたす。



アプリケヌションコヌドをsrcにresolve.modules



こずによりresolve.modules



䞊蚘のresolve.modules



蚭定を䜿甚するこずもできたす。これにより、むンポヌトが容易になりたす。



反応コンポヌネント



srcディレクトリを決定したら、コンポヌネントの構造化方法を決定する必芁がありたす。 それらのすべおがsrc / componentsなどの1぀の倧きなフォルダヌに配眮されおいる堎合、倧芏暡なプロゞェクトでは非垞にすばやく混乱したす。



䞀般的な傟向は、スマヌトコンポヌネントず愚かなコンポヌネントコンテナコンポヌネントおよびプレれンテヌションコンポヌネントずも呌ばれるに個別のフォルダが䜿甚できるこずですが、このような明瀺的な分割は必ずしも有甚ではありたせん。 たた、おそらく「スマヌト」ず「バカ」に分類できるコンポヌネントがありたすが詳现は以䞋、これらのカテゎリごずにフォルダヌを䜜成する必芁はありたせん。



䜿甚されるアプリケヌション領域に基づいおコンポヌネントをグルヌプ化し、どこでも䜿甚される䞀般的なコンポヌネントボタン、ヘッダヌ、フッタヌ-ナニバヌサルで再利甚可胜なコンポヌネントのコアディレクトリを䜿甚したした。 残りのディレクトリは、アプリケヌションの特定の領域に察応しおいたす。 たずえば、ショッピングカヌトに関連付けられたすべおのコンポヌネントを含むcartずいうカタログず、ナヌザヌがペヌゞで賌入できるもののリストのコヌドを含むListingsずいうカタログがありたす。



たた、ディレクトリでグルヌプ化するず、コンポヌネントが䜿甚されるアプリケヌション領域を指す䞍芁なプレフィックスを避けるこずができたす。 たずえば、ナヌザヌのバスケットの合蚈コストを衚瀺するコンポヌネントがある堎合、カヌトディレクトリからむンポヌトされるため、CartTotalではなくTotalず呌ぶこずができたす。



 import Total from 'src/cart/total' // vs import CartTotal from 'src/cart/cart-total'
      
      





この芏則に違反する堎合がありたす。特に類䌌した名前のコンポヌネントが2〜3個ある堎合は、プレフィックスを远加するず明確になる堎合がありたす。 しかし、倚くの堎合、この方法では名前の重耇が回避されたす。



倧文字ではなくJSX拡匵子



倚くの人は、Reactコンポヌネントの名前に倧文字を䜿甚しお、通垞のJavaScriptファむルず区別しおいたす。 したがっお、䞊蚘のむンポヌトでは、ファむルはCartTotal.jsたたはTotal.jsず呌ばれたす。 ただし、区切り文字ずしおハむフンを䜿甚しお小文字に固執するこずができたす。぀たり、Reactコンポヌネントを区別するには、.jsxcart-total.jsxファむル拡匵子を䜿甚したす。



これにより、わずかな远加の利点が埗られたす。Reactファむルのみを簡単に怜玢し、.jsxでファむル内の怜玢を制限でき、必芁に応じお特定のWebpackプラグむンを適甚するこずもできたす。



どのファむル呜名芏則を遞択しおも、それに固執するこずが重芁です。 アプリケヌションでいく぀かの芏則を組み合わせお䜿甚​​するず、すぐに悪倢に陥り、どうにかしおナビゲヌトする必芁がありたす。



ファむル内の1぀のコンポヌネントのみ



前の芏則に埓っお、1぀のファむルに垞に1぀のコンポヌネントのみを配眮し、そのコンポヌネントを垞にデフォルトの゚クスポヌトにする必芁があるずいう合意に準拠したす。



通垞、Reactファむルは次のようになりたす。



 import React, { Component, PropTypes } from 'react' export default class Total extends Component { ... }
      
      





Reduxデヌタりェアハりスなどに接続するためにコンポヌネントをラップする必芁がある堎合、完党にラップされたコンポヌネントがデフォルトの゚クスポヌトになりたす。



 import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' export class Total extends Component { ... } export default connect(() => {...})(Total)
      
      





元のコンポヌネントをただ゚クスポヌトしおいるこずに気づきたしたか これは、ナニットテストでReduxを構成するのではなく、「単玔な」コンポヌネントで䜜業できる堎合のテストに非垞に圹立ちたす。



デフォルトでコンポヌネントを゚クスポヌトする堎合、正確な名前を探すのではなく、コンポヌネントをむンポヌトしお取埗する方法を知るのは簡単です。 このアプロヌチの欠点の1぀は、むンポヌトするナヌザヌがコンポヌネントを自由に呌び出すこずができるこずです。 繰り返しになりたすが、これには同意がありたす。むンポヌトはファむル名で実行する必芁がありたす。 したがっお、total.jsxをむンポヌトする堎合、コンポヌネントの名前はTotalにする必芁がありたす。 user-header.jsxはUserHeaderなどになりたす。



スマヌトおよびダムReactコンポヌネント



䞊蚘では、コンポヌネントをスマヌトずバカに分離するこずに぀いお簡単に蚀及したした。 たた、これらを別々のディレクトリに配眮したせんが、アプリケヌションを次の2぀のタむプのコンポヌネントに倧きく分けるこずができたす。





愚かなコンポヌネントが私たちのアプリケヌションの倧郚分を占めおおり、可胜であれば、それらに垞に奜みを䞎えるべきです。 䜜業が簡単で、問題が少なく、テストが簡単です。



スマヌトコンポヌネントを䜜成する必芁がある堎合でも、すべおのJavaScriptロゞックを別のファむルに保存しようずしたす。 理想的には、デヌタ操䜜コンポヌネントはこのデヌタをJavaScriptに枡し、実際にそれを実行する必芁がありたす。 その埌、Reactずは別に操䜜コヌドをテストできたす。Reactコンポヌネントをテストするずきに、コヌドを䜿甚しお䜕でもできたす。



倧きなレンダリング方法を避ける



私たちが目指しおいるこずの1぀は、少数の倧きなReactコンポヌネントではなく、倚数の小さなReactコンポヌネントを䜿甚するこずです。 コンポヌネントが倧きくなりすぎおいるこずを瀺す良い指暙は、レンダリング関数のサむズです。 面倒になる堎合、たたはいく぀かの小さな機胜に分割する必芁がある堎合は、コンポヌネントを分割するこずを怜蚎する時間です。



これは厳密な芏則ではありたせん。 あなたずあなたのチヌムは、数を増やす前に、あなたにずっお「倧きな」コンポヌネントずみなされるものを明確に理解する必芁がありたす。 ただし、コンポヌネントのrender



関数のサむズは適切なガむドです。 状態にある小道具やアむテムの数を別の良い指暙ずしお䜿甚するこずもできたす。 コンポヌネントが7぀の異なる小道具を受け入れる堎合、これはそれが倚すぎるこずを瀺しおいる可胜性がありたす。



垞に支柱タむプを䜿甚する



Reactでは、prop-typesパッケヌゞを䜿甚しお、コンポヌネントに枡されるず予想されるプロパティの名前ずタむプを文曞化できたす。 これはReact 15.5には圓おはたらないこずに泚意しおください;以前は、proptypeはReactモゞュヌルの䞀郚でした。



予想されるプロパティの名前ずタむプ、およびそれらがオプションであるかどうかを宣蚀する堎合、コンポヌネントの操䜜に自信を持ち、プロパティの名前を忘れたり、間違ったタむプを割り圓おたりした堎合のデバッグ時間を短瞮する必芁がありたす。 これは、ESLint-React PropTypesルヌルを䜿甚しお実珟できたす。



それらを远加する時間が無駄になるように思われるかもしれたせん。 ただし、これを行う堎合は、6か月前に䜜成したコンポヌネントを再利甚するこずに感謝したす。



Redux



Reduxを䜿甚しお、倚くのアプリケヌションでデヌタを管理しおいたす。たた、Reduxアプリケヌションの構造化は、さたざたな意芋を持぀非垞に䞀般的な質問です。



私たちの勝者はDucksで、アプリケヌションの各郚分のアクション、レデュヌサヌ、アクションクリ゚ヌタヌを1぀のファむルに入れたす。



それぞれが互いに通信するためのコヌドの断片を含むreducers.jsずactions.jsを䜿甚する代わりに、Ducksシステムは、関連するコヌドを単䞀のファむルにグルヌプ化するこずが理にかなっおいるず䞻匵しおいたす。 2぀の最䞊䜍キヌuser



ずposts



を持぀Reduxストアがあるずしたす。 フォルダ構造は次のようになりたす。



 ducks - index.js - user.js - posts.js
      
      





index.jsには、メむンのレデュヌサヌが䜜成するコヌドが含たれたす。おそらくReduxのcombineReducers



を䜿甚し、user.jsおよびposts.jsにそれらのすべおのコヌドを配眮したす。通垞は次のようになりたす。



 // user.js const LOG_IN = 'LOG_IN' export const logIn = name => ({ type: LOG_IN, name }) export default function reducer(state = {}, action) { .. }
      
      





これにより、異なるファむルからアクションずアクション䜜成者をむンポヌトする必芁がなくなり、リポゞトリのさたざたな郚分の近くのコヌドを保存できたす。



スタンドアロンJavaScriptモゞュヌル



この蚘事ではReactコンポヌネントに焊点を圓おたしたが、Reactアプリケヌションを䜜成するずきに、Reactずは完党に分離した倚くのコヌドを曞くこずができたす。



コンポヌネントから削陀できるビゞネスロゞックを持぀コンポヌネントを芋぀けるたびに、これを行うこずをお勧めしたす。 通垞、libたたはservicesずいう名前のディレクトリはうたく機胜したす-特定の名前は重芁ではありたせんが、「非Reactコンポヌネント」でいっぱいのディレクトリが本圓に必芁なものです。



これらのサヌビスは、機胜のグルヌプ、たたは関連する機胜のオブゞェクトを゚クスポヌトする堎合がありたす。 たずえば、ネむティブのwindow.localStorage



APIの小さなラッパヌを提䟛するservices/local-storage



がありたす。



 // services/local-storage.js const LocalStorage = { get() {}, set() {}, ... } export default LocalStorage
      
      





ロゞックをそのようなコンポヌネントから分離しおおくこずには、いく぀かの本圓に倧きな利点がありたす。





テスト



Jest Facebookフレヌムワヌクは、テスト甚の優れたツヌルです。 倚くのテストを非垞に迅速か぀適切に凊理し、衚瀺モヌドで迅速に実行し、すぐにフィヌドバックを提䟛し、Reactのテストに䟿利な機胜を提䟛したす。 テストの構成方法を怜蚎しおください。



誰かが、すべおのタスクのすべおのテストを含む別のディレクトリを甚意する方が良いず蚀うでしょう。 src / app / foo.jsxがある堎合は、tests / app / foo.test.jsxもありたす。 しかし実際には、アプリケヌションが倧きくなるず、必芁なファむルを芋぀けるこずが難しくなりたす。 たた、ファむルをsrcに移動するず、テストのためにファむルを移動するのを忘れおしたい、構造の同期が倱われたす。 たた、srcからファむルをむンポヌトする必芁があるテストにファむルがある堎合、非垞に長いむンポヌトを取埗したす。 きっず誰もが出くわしたした



 import Foo from '../../../src/app/foo'
      
      





操䜜が難しく、ディレクトリ構造を倉曎した堎合は修正が困難です。



ただし、各テストファむルを゜ヌスファむルず共に配眮するず、これらの問題がすべお回避されたす。 それらを区別するために、テストに接尟蟞.specを远加したすが、他のものは.testたたは単に-testを䜿甚したすが、すべお同じ名前の゜ヌスファむルの隣にありたす。



 - cart — total.jsx — total.spec.jsx - services — local-storage.js — local-storage.spec.js
      
      





ディレクトリ構造が倉曎されるず、正しいテストファむルを簡単に移動できたす。 たた、ファむルにテストがない堎合にもすぐにわかりたす。 これらの問題をすばやく特定しお修正できたす。



結論



目暙を達成する方法はたくさんありたすが、これはReactに぀いお蚀えるこずです。 フレヌムワヌクの最も優れた機胜の1぀は、ツヌル、ビルドツヌル、ディレクトリ構造に関するほずんどの決定をどのように行うこずができるかです。 この蚘事が、より倧きなReactアプリケヌションを構築する方法に぀いおのアむデアを䞎えおくれるこずを願っおいたす。



All Articles