リアクトネイティブ(React Native)でrootからimportする

2019-06-05

リアクトネイティブ(React Native)プロジェクトでimportをする時、rootフォルダを基準にしてimportが出来るようにプロジェクトを設定してみましょう。

概要

このブログではリアクトネイティブ(React Native)だけの問題ではなく、Reactで開発する時、問題を解決してみようかと思います。Reactで開発する時、プロジェクトの構造を綺麗にしてもimportする時、長くなる../../../フォルダの参照問題は解決できないです。このブログでは長くなるこのフォルダの参照問題を少しでも解決してみようかと思って作成しました。リアクトネイティブ(React Native)の開発者だけではなくReactjs開発者にも参考になると嬉しいです。

フォルダの構造

私はリアクトネイティブ(React Native)で開発する時、下記のようなフォルダ構造を使っています。

|-- android/
|-- ios/
|-- src/
|   |-- @types/
|   |-- Assets/
|   |   |-- Images/
|   |-- Component/
|   |   |-- BannerContainer/
|   |   |   |-- index.tsx
|   |   |-- LoadingContainer/
|   |   |   |-- index.tsx
|   |-- Screen/
|   |   |-- Home/
|   |   |   |-- SomeContainer/
|   |   |   |   |-- index.tsx
|   |   |   |-- SomeContainer2/
|   |   |   |   |-- SomeContainerItem/
|   |   |   |   |   |-- index.tsx
|   |   |   |   |-- index.tsx
|   |   |   |-- index.tsx
|   |-- Util/
|-- index.js

最初はComponentContainerScreenで分けって開発しましたが、Containerが特定なScreenに従属的に使えって、色んなScreenで使う場合が少なかったです。それで色んなScreenで共通的使う部分をComponentに入れって、従属的なContainer(Component)はScreenフォルダの下に置いています。もちろん、Componentの下にもComponent(Container)に従属してるComponentが存在しています。

このようにした理由は二つぐらいあります。一つはScreenに従属されてるContainerを探すため、Containerフォルダまで探して、またComponentフォルダまで探さなきゃならない不便さがありました。今は従属されてるContainerはScreenフォルダ下にあるので探す時、楽になりました。もう一つはコピペーを楽にするためです。一人で臭味で色んなアプリを開発してるので一つのプロジェクトで作ったComponentをコピーして他のプロジェクトにペーストする場合があります。Containerフォルダを別で管理する時、Screenをコピーするようになったら、Screenをコピーしてそこに必要なContainerをコピーしてComponentもコピーする必要がありました。今はScreen一つだけコピーすればContainerが一緒にコピーされるのでコピペーがちょっと楽になりました。このような不便さを解決するため上のようなプロジェクトの構造を持てるようになりました。参考ですがReactjsは下記のよなフォルダ構造を使っています。

|-- android/
|-- ios/
|-- src/
|   |-- @types/
|   |-- Assets/
|   |   |-- Images/
|   |-- Component/
|   |   |-- BannerContainer/
|   |   |   |-- index.tsx
|   |   |-- LoadingContainer/
|   |   |   |-- index.tsx
|   |-- Feature/
|   |   |-- Login/
|   |   |   |-- SomeContainer/
|   |   |   |   |-- index.tsx
|   |   |   |-- SomeContainer2/
|   |   |   |   |-- SomeContainerItem/
|   |   |   |   |   |-- index.tsx
|   |   |   |   |-- index.tsx
|   |   |   |-- index.tsx
|   |-- Util/
|-- index.js

上のようにScreenで管理してるフォルダをFeatureの名前のフォルダで管理しています。皆さんはどんなフォルダ構造を使っていますか?色んな人たちが参考できるように一番下のコメントに皆さんのフォルダ構造を共有してみてください!(私も参考したいですT^T)

問題

このようにフォルダを持って流のでScreen(Feature)の下にContainerがあてContainerがまた他のContainerを持てるし最後のContainerがComponentを持てる場合importをする時、../../../が結構長くなるフォルダ参照問題が発生します。最近はvscodeが良くなって自動に追加してくれるけど、../../../の問題はまだのこています。

また、Screenに従属されてるContainerComponentが共通化されてComponentフォルダに移動する場合、逆にComponentScreenに従属されることになってScreenのフォルダに移動する場合、importのフォルダ参照の位置が変わって変更するのが大変です。

解決策

私はこの問題を解決するためbabel-plugin-root-importtypescriptの設定でrootフォルダから参照出来るように修正しました。例えば、../../../Component/BannerContainerの部分が~/Component/BannerContainerように参照できます。下記で設定する方法について説明します。

babel-plugin-root-import

rootフォルダから参照出来るようにするためbabel-plugin-root-importを下記のコマンドでインストールします。

npm install babel-plugin-root-import --save-dev

リアクトネイティブ(React Native)プロジェクトのbabel.config.jsを開いて下記のように修正します。

module.exports = {
  presets: ['module:metro-react-native-babel-preset'],
  plugins: [
    'babel-plugin-styled-components',
    [
      'babel-plugin-root-import',
      {
        rootPathPrefix: '~',
        rootPathSuffix: 'src',
      },
    ],
  ],
};

私のフォルダの構造を見れば分かると思いますが、私は全てのソースをsrcに入れって管理しています。したがって、私はrootフォルダではなくsrcフォルダを基準にして動作するように設定しました。

typescript

typescriptを使ってない方は上の設定だけで大丈夫です。私はリアクトネイティブ(React Native)プロジェクトでtypescriptを使って流のでtypescriptがrootフォルダを認識するように設定する必要があります。リアクトネイティブ(React Native)にtypescriptを提供する方法は下記のブログを参考してください。

リアクトネイティブ(React Native)プロジェクトのtsconfig.jsonファイルを開いて下記のように修正します。

{
  "compilerOptions": {
    ...
    "baseUrl": "./src", // all paths are relative to the baseUrl
    "paths": {
      "~/*": ["*"] // resolve any `~/foo/bar` to `<baseUrl>/foo/bar`
    }
  },
  ...
}

完了

これでリアクトネイティブ(React Native)プロジェクトでimportする時、長かった../../../../とはバイバイしました。もっとプロジェクトが綺麗に管理出来るように見えて嬉しいです。皆さんも遅くなる前この部分を追加することをお勧めします!

Buy me a coffeeBuy me a coffee
Posts