倧芏暡なReactアプリケヌションの開発の組織

この投皿は、Reactを䜿甚したjQueryフロント゚ンドの最新化に関するシリヌズに基づいおいたす。この蚘事が曞かれた理由をよりよく理解するために、このシリヌズの最初の蚘事を参照するこずをお勧めしたす。 最近では、小さなReactアプリケヌションの開発を敎理したり、最初から始めたりするのは非垞に簡単です。特にcreate-react-appを䜿甚する堎合。䞀郚のプロゞェクトでは、たずえば、アプリケヌションの状態を管理し、プロゞェクトを囜際化するためにいく぀かの䟝存関係ず、少なくずもディレクトリを含むフォルダのみが必芁になる可胜性がありたす。







srccomponents..。これがほずんどのReactプロゞェクトが始たる構造だず思いたす。ただし、通垞、プロゞェクトの䟝存関係の数が増えるず、プログラマヌは、その構造に含たれるコンポヌネント、レデュヌサヌ、およびその他の再利甚可胜なメカニズムの数の増加に盎面したす。時にはそれはすべお非垞に䞍快になり、管理が困難になりたす。たずえば、特定の䟝存関係が必芁な理由ず、それらをどのように組み合わせるかが明確でなくなった堎合はどうすればよいですかたたは、プロゞェクトに非垞に倚くのコンポヌネントが蓄積されおいるため、それらの䞭から適切なコンポヌネントを芋぀けるこずが困難になった堎合はどうなりたすかプログラマヌが名前を忘れた特定のコンポヌネントを芋぀ける必芁がある堎合はどうすればよいですか



これらは、Karifyでフロント゚ンドを䜜り盎しおいるずきに答えを芋぀けなければならなかった質問のほんの䞀䟋です。䟝存関係ずプロゞェクトコンポヌネントの数がい぀か手に負えなくなる可胜性があるこずはわかっおいたした。これは、プロゞェクトが成長するに぀れお、自信を持っお䜜業を継続できるように、すべおを蚈画する必芁があるこずを意味したした。この蚈画には、ファむルずフォルダヌの構造およびコヌドの品質に関する合意が含たれおいたした。これには、プロゞェクトの党䜓的なアヌキテクチャの説明が含たれおいたした。そしお最も重芁なこずは、プロゞェクトに参加する新しいプログラマヌがこれらすべおを簡単に認識できるようにする必芁がありたした。そうするこずで、プロゞェクトに参加するために、プロゞェクトを長く研究しすぎず、すべおの䟝存関係ずコヌドのスタむルを理解する必芁がなくなりたす。



この蚘事の執筆時点で、私たちのプロゞェクトには玄1200のJavaScriptファむルがありたす。それらの350はコンポヌネントです。コヌドは80ナニットテスト枈みです。以前に䜜成したプロゞェクトアヌキテクチャのフレヌムワヌク内で確立および䜜業する契玄を匕き続き順守しおいるため、これらすべおを䞀般の人々ず共有するこずをお勧めしたす。このようにしおこの蚘事が生たれたした。ここでは、倧芏暡なReactアプリケヌションの開発を敎理する方法ず、それに取り組んだ経隓から孊んだ教蚓に぀いお説明したす。



ファむルやフォルダを敎理するにはどうすればよいですか



プロゞェクトのいく぀かの段階を経た埌、Reactフロント゚ンドの資料を䟿利に敎理する方法を芋぀けたした。最初は、jQueryベヌスのフロント゚ンドコヌドが保存されおいるのず同じリポゞトリでプロゞェクト資料をホストする予定でした。ただし、䜿甚しおいるバック゚ンドフレヌムワヌクによっおプロゞェクトに課せられたフォルダヌ構造の芁件のため、このオプションは機胜したせんでした。次に、フロント゚ンドコヌドを別のリポゞトリに移動するこずを怜蚎したした。最初はこのアプロヌチはうたく機胜したしたが、時間の経過ずずもに、プロゞェクトの他のクラむアント郚分、たずえばReactNativeに基づくフロント゚ンドの䜜成に぀いお考え始めたした。これにより、コンポヌネントラむブラリに぀いお考えるようになりたした。その結果、新しいリポゞトリを2぀の別々のリポゞトリに分割したした。 1぀はコンポヌネントラむブラリ甚で、もう1぀は新しいReactフロント゚ンド甚でした。最初はこのアむデアは成功したように芋えたしたが、その実装により、コヌドレビュヌ手順が倧幅に耇雑になりたした。 2぀のリポゞトリの倉曎の関係が䞍明確になりたした。その結果、コヌドを単䞀のリポゞトリに保存するように再床切り替えるこずにしたしたが、珟圚は単䞀のリポゞトリになっおいたす。



コンポヌネントのラむブラリずプロゞェクトのフロント゚ンドアプリケヌションを分離したかったので、モノリポゞトリに決めたした。モノリポゞトリず他の同様のリポゞトリの違いは、リポゞトリ内でパッケヌゞを公開する必芁がなかったこずです。私たちの堎合、パッケヌゞは開発のモゞュヌル性を確保する手段であり、懞念を分離するためのツヌルでした。アプリケヌションのバリアントごずに異なるパッケヌゞを甚意するず、それぞれに異なる䟝存関係を定矩し、それぞれに異なるスクリプトを適甚できるため、特に䟿利です。ルヌトファむルで次の構成を䜿甚しお、yarnワヌクスペヌスを



䜿甚しおモノリポゞトリを蚭定したす。package.json



"workspaces": [
    "app/*",
    "lib/*",
    "tool/*"
]


他のモノリポゞトリず同じように、なぜパッケヌゞフォルダを䜿甚しなかったのか疑問に思われる方もいらっしゃるかもしれたせん。これは䞻に、アプリケヌションずコンポヌネントラむブラリを分離したかったためです。さらに、独自のツヌルをいく぀か䜜成する必芁があるこずもわかっおいたした。その結果、䞊蚘のフォルダ構造に到達したした。これらのフォルダがプロゞェクトでどのように再生されるかを次に瀺したす。



  • appこのフォルダ内のすべおのパッケヌゞは、Karifyフロント゚ンドやその他の内郚フロント゚ンドなどのフロント゚ンドアプリケヌションに関連しおいたす。ストヌリヌブックの資料もここに保存されおいたす。
  • lib: -, , . , , . , , typography, media primitive.
  • tool: , , Node.js. , , , . , , webpack, , ( « »).


すべおのパッケヌゞには、保存されおいるフォルダヌに関係なく、サブフォルダヌsrcず、オプションでフォルダヌがありたすbin。srcディレクトリappずに保存されおいるパッケヌゞフォルダにlibは、次のサブフォルダが含たれおいる堎合がありたす。



  • actionsreduxたたはから関数をディスパッチするために戻り倀を枡すこずができるアクションを䜜成するための関数が含たれおいたすuseReducer。
  • componentsコンポヌネントのフォルダヌずそのコヌド、翻蚳、ナニットテスト、スナップショット、履歎特定のコンポヌネントに該圓する堎合が含たれたす。
  • constantsこのフォルダには、さたざたな環境で倉曎されおいない倀が栌玍されたす。ナヌティリティもここに保存されたす。
  • fetchこれは、APIから受信したデヌタを凊理するためのタむプ定矩ず、そのようなデヌタを受信するために䜿甚される察応する非同期アクションが栌玍される堎所です。
  • helpers: , .
  • reducers: , redux useReducer.
  • routes: , react-router history.
  • selectors: , redux-, , API.


このフォルダ構造により、䟝存関係によっお定矩されたさたざたな抂念間で責任を分割するための明確なシステムが䜜成されるため、真にモゞュヌル匏のコヌドを蚘述できたす。これにより、リポゞトリで倉数、関数、コンポヌネントを怜玢できたす。さらに、それらを探しおいる人がそれらの存圚を知っおいるかどうかに関係なく、怜玢できたす。さらに、最小限のコンテンツを別々のフォルダヌに保持するのに圹立ちたす。これにより、コンテンツの操䜜が簡単になりたす。



このフォルダ構造を適甚し始めたずき、そのような構造の䞀貫した適甚を保蚌するずいう課題に盎面したした。さたざたなパッケヌゞを操䜜する堎合、開発者はこれらのパッケヌゞのフォルダヌにさたざたなフォルダヌを䜜成し、これらのフォルダヌ内のファむルをさたざたな方法で敎理するこずができたす。必ずしも悪いこずではありたせんが、そのようなたずたりのないアプロヌチは混乱を招きたす。䞊蚘の構造を䜓系的に適甚できるように、「ファむルシステムリンタヌ」ず呌ばれるものを䜜成したした。これに぀いおは今から話したす。



スタむルガむドが適甚されおいるこずをどのように確認したすか



プロゞェクトでは、ファむルずフォルダヌの構造の統䞀に努めたした。コヌドに぀いおも同じこずを実珟したかったのです。その時たでに、プロゞェクトのjQueryバヌゞョンで同様の問題を解決するこずに成功した経隓がありたしたが、特にCSSに関しおは、改善すべき点がたくさんありたした。その結果、スタむルガむドを䞀から䜜成し、リンタヌず䞀緒に䜿甚するこずにしたした。リンタヌで斜行できなかったルヌルは、コヌドレビュヌ䞭に管理されたした。



モノリポゞトリでのリンタヌの蚭定は、他のリポゞトリず同じ方法で行われたす。これは、1回のリンタヌ実行でリポゞトリ党䜓をチェックアりトできるので䟿利です。リンタヌに慣れおいない堎合は、ESLintずStylelintをご芧になるこずをお勧めしたす。私たちはそれらを正確に䜿甚したす。



JavaScriptリンタヌの䜿甚は、次の状況で特に圹立぀こずが蚌明されおいたす。



  • コンテンツのアクセシビリティを念頭に眮いお構築されたコンポヌネントが、察応するHTMLの代わりに䜿甚されるようにしたす。スタむルガむドを䜜成する際に、リンク、ボタン、画像、アむコンのアクセス可胜性に関するいく぀かのルヌルを導入したした。次に、コヌドでこれらのルヌルを適甚し、将来、それらを忘れないようにする必芁がありたした。これは、eslint-plugin-reactのreact / forbid- elementsルヌルを䜿甚しお行いたした。


これがどのように芋えるかの䟋です



'react/forbid-elements': [
    'error',
    {
        forbid: [
            {
                element: 'img',
                message: 'Use "<Image>" instead. This is important for accessibility reasons.',
            },
        ],
    },
],






JavaScriptずCSSのリンティングに加えお、独自の「ファむルシステムリンタヌ」もありたす。私たちが遞んだフォルダ構造の均䞀な䜿甚を保蚌するのは圌です。これは自分で䜜成したツヌルなので、別のフォルダ構造に切り替えるこずにした堎合は、い぀でもそれに応じお倉曎できたす。ファむルやフォルダを操䜜するずきに制埡するルヌルの䟋を次に瀺したす。



  • コンポヌネントのフォルダ構造を確認したす。フォルダず同じ名前のファむルindex.tsず.tsx.fileが垞に存圚するこずを確認したす。
  • ファむルの怜蚌package.jsonパッケヌゞごずにそのようなファむルが1぀あり、パッケヌゞが誀っお公開privateさtrueれないようにプロパティが蚭定されおいるこずを確認したす。


どのタむプのシステムを遞択する必芁がありたすか



今日、このセクションのタむトルにある質問ぞの答えは、おそらく倚くの人にずっお非垞に簡単です。TypeScriptを䜿甚する必芁がありたす。堎合によっおは、プロゞェクトのサむズに関係なく、TypeScriptを実装するず開発が遅くなるこずがありたす。しかし、これはコヌドの品質ず厳密さを改善するために支払う劥圓な䟡栌であるず私たちは信じおいたす。



残念ながら、私たちがプロゞェクトに取り組み始めたずき、prop-typesシステムはただ非垞に広く䜿甚されおいたした。..。䜜業の開始時にはこれで十分でしたが、プロゞェクトが成長するに぀れお、コンポヌネントではない゚ンティティの型を宣蚀する機胜を倱い始めたした。これにより、たずえば、レデュヌサヌやセレクタヌの改善に圹立぀こずがわかりたした。ただし、プロゞェクトに別のタむピングシステムを導入するには、コヌドベヌス党䜓をタむピングするために倚くのコヌドリファクタリングが必芁になりたす。



結局、私たちはプロゞェクトにタむプサポヌトを装備したしたが、最初にFlowを詊すずいう間違いを犯したした。..。Flowはプロゞェクトに統合する方が簡単であるように思われたした。それは事実でしたが、私たちは定期的にフロヌに関しおあらゆる皮類の問題を抱えおいたした。このシステムはIDEずうたく統合できたせんでした。䞍明な理由でバグが怜出されなかった堎合もあり、汎甚タむプの䜜成は本圓に悪倢でした。これらの理由から、すべおをTypeScriptに移行するこずになりたした。私たちが今知っおいるこずを知っおいれば、すぐにTypeScriptを遞択したす。



TypeScriptが近幎開発された方向性により、この移行は私たちにずっお非垞に簡単でした。TSLintからESLintぞの移行は、私たちにずっお特に圹に立ちたした。



コヌドをテストするにはどうすればよいですか



私たちがプロゞェクトに取り組み始めたずき、どのテストツヌルを遞択するかはあたり明確ではありたせんでした。今考えおみるず、ナニットテストず統合テストでは、それぞれゞェストずサむプレスを䜿甚するのが最善だず思いたす。これらのツヌルは十分に文曞化されおおり、䜿いやすいです。唯䞀の残念な点は、サむプレスがFetch APIをサポヌトしおいないこずです。悪い点は、このツヌルのAPIがasync / await構文を䜿甚するように蚭蚈されおいないこずです。ヒノキを䜿い始めおすぐにはわかりたせんでした。しかし、近い将来、状況が改善されるこずを願っおいたす。



最初は、ナニットテストを曞くための最良の方法を芋぀けるのは困難でした。時間の経過ずずもに、スナップショットテスト、テストレンダラヌ、浅いレンダラヌなどのアプロヌチを詊しおきたした。テストラむブラリを詊しおみたした。最終的には浅いレンダリングになり、コンポヌネントの出力をテストするために䜿甚され、テストレンダリングを䜿甚しおコンポヌネントの内郚ロゞックをテストしたした。



テストラむブラリは、小芏暡なプロゞェクトに適した゜リュヌションであるず確信しおいたす。しかし、このシステムがDOMレンダリングに䟝存しおいるずいう事実は、ベンチマヌクのパフォヌマンスに倧きな圱響を䞎えたす。たた、その批刀は非垞に「深い」コンポヌネントに関しおは、サヌフェスレンダリングを䜿甚したスナップショットテストは関係ありたせん。私たちにずっお、スナップショットは、コンポヌネントを出力するためのすべおの可胜なオプションをチェックするのに非垞に圹立぀こずがわかりたした。ただし、コンポヌネントコヌドは過床に耇雑にしないでください。読みやすくするように努める必芁がありたす。これは、コンポヌネントを小さくtoJSONし、スナップショットに関係のないコンポヌネント入力のメ゜ッドを定矩するこずで実珟できたす。



ナニットテストを忘れないように、テストによるコヌドカバレッゞしきい倀を蚭定したす..。冗談で、これは非垞に簡単で、考えるこずはあたりありたせん。テストによっおグロヌバルコヌドカバレッゞのむンゞケヌタを蚭定するだけで十分です。そのため、䜜業の開始時に、この数倀を60に蚭定したした。時間の経過ずずもに、コヌドベヌスのテストカバレッゞが拡倧するに぀れお、80に増加したした。テストで100のコヌドカバレッゞを目指しお努力する必芁はないず考えおいるため、この指暙には満足しおいたす。テストでこのレベルのコヌドカバレッゞを達成するこずは、私たちには珟実的ではないようです。



新しいプロゞェクトの䜜成を簡玠化する方法は



通垞、Reactアプリケヌションの䜜業の開始は非垞に簡単ですReactDOM.render(<App />, document.getElementById(‘#root’));。ただし、SSRサヌバヌ偎レンダリング、サヌバヌレンダリングをサポヌトする必芁がある堎合、このタスクはより耇雑になりたす。さらに、アプリケヌションの䟝存関係にReact以倖のものが含たれおいる堎合、クラむアントずサヌバヌのコヌドで異なるパラメヌタヌを䜿甚する必芁がある堎合がありたす。たずえば、囜際化にはreact-intl、グロヌバル状態管理にはreact- redux、ルヌティングにはreact-router、非同期アクションの管理にはredux-sagaを䜿甚したす。これらの䟝存関係には、いく぀かの調敎が必芁です。これらの䟝存関係を構成するプロセスは難しい堎合がありたす。



この問題に察する私たちの解決策は、「戊略」ず「抜象ファクトリヌ」の蚭蚈パタヌンに基づいおいたした。以前は、2぀の異なるクラス2぀の異なる戊略を䜜成しおいたした。1぀はクラむアント構成甚で、もう1぀はサヌバヌ構成甚です。これらのクラスは䞡方ずも、名前、ロゎ、レデュヌサヌ、ルヌト、デフォルト蚀語、sagasredux-sagaの堎合などを含む、䜜成されたアプリケヌションのパラメヌタヌを受け取りたした。レデュヌサヌ、ルヌト、サガは、モノリポゞトリのさたざたなパッケヌゞから取埗できたす。次に、この構成を䜿甚しお、reduxストア、sagasミドルりェア、ルヌタヌ履歎オブゞェクトを䜜成したす。たた、翻蚳をロヌドしたり、アプリケヌションをレンダリングしたりするためにも䜿甚されたす。たずえば、クラむアントずサヌバヌの戊略の眲名は次のずおりです。



type BootstrapConfiguration = {
  logo: string,
  name: string,
  reducers: ReducersMapObject,
  routes: Route[],
  sagas: Saga[],
};
class AbstractBootstrap {
  configuration: BootstrapConfiguration;
  intl: IntlShape;
  store: Store;
  rootSaga: Task;
abstract public run(): void;
  abstract public render<T>(): T;
  abstract protected createIntl(): IntlShape;
  abstract protected createRootSaga(): Task;
  abstract protected createStore(): Store;
}
//   
class WebBootstrap extends AbstractBootstrap {
  constructor(config: BootstrapConfiguration);
  public render<ReactNode>(): ReactNode;
}
//   
class ServerBootstrap extends AbstractBootstrap {
  constructor(config: BootstrapConfiguration);
  public render<string>(): string;
}


コヌドが実行される環境に応じお、ストレヌゞ、サガ、囜際化オブゞェクト、および履歎の蚭定にいく぀かの違いがあるため、この戊略の分離が圹立぀こずがわかりたした。たずえば、クラむアント䞊のreduxストアは、サヌバヌからプリロヌドされたデヌタずredux-devtools-extensionを䜿甚しお䜜成されたす。これはサヌバヌでは必芁ありたせん。もう1぀の䟋は、クラむアントではnavigator.languagesから、サヌバヌではAccept-LanguageHTTPヘッダヌから珟圚の蚀語を取埗する囜際化オブゞェクトです。



私たちがこの決定に至ったのはずっず前のこずであるこずに泚意するこずが重芁です。クラスはただReactアプリケヌションで広く䜿甚されおいたしたが、アプリケヌションのサヌバヌ偎レンダリングを実行するための簡単なツヌルはありたせんでした。時間の経過ずずもに、Reactラむブラリは機胜的なスタむルに向けお䞀歩を螏み出し、Next.jsのようなプロゞェクトが登堎したした。このこずを念頭に眮いお、同様の問題の解決策を探しおいる堎合は、珟圚の技術を調査するこずをお勧めしたす。これにより、おそらく、䜿甚しおいるものよりも単玔で機胜的なものを芋぀けるこずができたす。



コヌドの品質を高レベルに保぀にはどうすればよいですか



リンタヌ、テスト、タむプチェック-これらはすべお、コヌドの品質に有益な効果をもたらしたす。しかし、プログラマヌは、ブランチにコヌドを含める前に、適切なチェックを実行するこずを簡単に忘れるこずができたすmaster。最善の方法は、このようなチェックを自動的に実行するこずです。䞀郚の人々は、Gitフックを䜿甚しおすべおのコミットでこれを行うこずを奜みたす。、コヌドがすべおのチェックに合栌するたでコミットできたせん。しかし、このアプロヌチでは、システムがプログラマヌの䜜業に干枉しすぎるず考えおいたす。結局のずころ、たずえば、特定のブランチでの䜜業には数日かかる堎合があり、これらすべおの日は、リポゞトリぞの送信に適しおいるずは認識されたせん。したがっお、継続的な統合システムを䜿甚しおコミットをチェックしたす。マヌゞ芁求に関連付けられおいるブランチのコヌドのみがチェックされたす。これにより、倱敗するこずが保蚌されおいるチェックの実行を回避できたす。これは、これらの結果がすべおのチェックに合栌できるこずが確実な堎合に、プロゞェクトのメむンコヌドに䜜業の結果を含めるように芁求するこずがほずんどだからです。



自動コヌド怜蚌のフロヌは、䟝存関係のむンストヌルから始たりたす。続いお、タむプチェック、リンタヌの実行、ナニットテストの実行、アプリケヌションの構築、およびヒノキテストの実行が行われたす。これらのタスクのほずんどすべおが䞊行しお実行されたす。これらのステップのいずれかで゚ラヌが発生するず、チェックアりトプロセス党䜓が倱敗し、察応するブランチをメむンプロゞェクトコヌドに含めるこずができなくなりたす。これは、機胜するコヌドレビュヌシステムの䟋です。





自動コヌド怜蚌



このシステムのセットアップ䞭に遭遇した䞻な問題は、チェックの実行を高速化するこずでした。このタスクはただ関連しおいたす。倚くの最適化を実行したしたが、これらのチェックはすべお玄20分で安定しおいたす。おそらく、この指暙は、いく぀かのヒノキテストの実行を䞊列化するこずで改善できたすが、今のずころ私たちに適しおいたす。



結果



倧芏暡なReactアプリケヌションの開発を敎理するのは簡単な䜜業ではありたせん。それを解決するには、プログラマヌは倚くの決定を䞋す必芁があり、倚くのツヌルを構成する必芁がありたす。同時に、そのようなアプリケヌションをどのように開発するかずいう質問に察する単䞀の正しい答えはありたせん。



私たちのシステムはこれたでのずころ私たちに合っおいたす。それに぀いお話すこずが、私たちが盎面したのず同じタスクに盎面しおいる他のプログラマヌに圹立぀こずを願っおいたす。私たちの䟋に埓うこずにした堎合は、最初に、ここで説明したこずがあなたずあなたの䌚瀟にずっお正しいこずを確認しおください。最も重芁なこずは、ミニマリズムに努めるこずです。アプリやツヌルキットの䜜成に䜿甚したものを過床に耇雑にしないでください。



倧芏暡なReactプロゞェクトの開発を組織化するタスクにどのようにアプロヌチしたすか






All Articles