LoginSignup
2
1

More than 3 years have passed since last update.

SPAの知識ゼロの状態から、React+Reduxの開発環境構築までにやったこと

Last updated at Posted at 2020-02-17

Webアプリケーションを開発する際に、「今ならSPA(Single Page Application)っしょ」となり、フレームワークの選定からやらせてもらう機会があったので、そのときにやったことを共有します。

前提

本記事作成時の筆者のスキル

  • Webアプリケーションは作ったことがあるが、言語はJava
  • SPA is 何?
  • Javascriptはかじった程度の知識

フレームワークの選定

Googleトレンドや、実績からSPAのフレームワークを以下に絞りました。

  • React
  • AngularJS
  • Vue.js

その時人気だったReactにしておけばいいだろと、Reactにしました。
※近年、Vue.jsが勢力を伸ばしてきているらしいです。

React + α

Reactは様々なライブラリと組み合わせるのが普通のようです。
npm installでどんどんライブラリを追加していくことになりますが、ここでは開発手法に大きく関わるライブラリだけ。

執筆時点での最新バージョンはそれぞれ以下の通りです。あまり古くなっているようなら、参考にならないかもしれません。

プロダクト version
React 16.12.0
Redux 4.0.5
TypeScript 3.7.5
redux-saga 1.1.3
Material-UI 4.9.2
react-intl 3.12.0

エディター

これも流行りなのでVSCodeを使用しました。
結果的に、nodeやgitのコマンドもターミナルのペインで実行できるので、かなり使いやすかったです。

設定と拡張機能をチーム内で共有する

エディタの設定は、プロジェクト直下の.vscode/settings.jsonというファイルで共有できます。
拡張機能は、.vscode/extensions.jsonというファイルを置くことで、VSCode起動時にポップアップが出るようになります。
フォーマッター、保存時の自動フォーマットなどの設定は共有しておくと便利です。

プロジェクトの作成

create-react-appというコマンドを使います。これを使うと起動スクリプトやwebpackのコンフィグなどが隠された状態で、カスタマイズできないので、すぐにejectというコマンドで素のnodeで扱えるようにします。

npx create-react-app my-app
cd my-app
npm run eject

プロジェクトの設定

ディレクトリ構成を考える

こんな感じになりしました。「これが正解!」というパターンは無いようなので、あくまで一例として。

ディレクトリ構成(クリックで開く)
<root>          
├─public          画像ファイルなど。srcから見たとき、"/"がpublic直下
├─build           ビルドされたファイルが作成される先
├─config          create-react-appで勝手の作成される
├─scripts         create-react-appで勝手の作成される+自作のnpmスクリプトを作る場合はここ
├─node_modules          
└─src             src以外のファイルはほとんど触らない    
  ├─i18n          メッセージのyamlと、それを管理するJS
  ├─modules       actionとreducerをまとめたもの
  ├─containers    1画面1コンテナという考え方で、コンテナコンポーネントを作成する。
  ├─comopnents    コンポーネント。画面ごとにサブディレクトリを切る      
  ├─sagas         非同期処理を扱う処理 
  ├─scss          .scssファイル
  └─utils         共通で使う処理。Validatorなど

importを絶対パス指定でできるようにする

これデフォルトじゃないんかい。。。と思いながら設定しました。
方法はいくつかあるようですが、TypeScriptを使っているのでtsconfigで設定できる方法を採用しました。
これをやらないと、"../../../../"地獄になります。

いつもの
npm i --save tsconfig-paths
tsconfig.json
{
  "compilerOptions": {
    "baseUrl": "src"
     ~~~後略~~~
}

メッセージ管理方法を考える

yamlでメッセージ管理できるようにする

yaml-flat-loaderというライブラリを使用して、yamlをjsonとして読み込めるようにします。

いつもの
npm i --save-dev yaml-flat-loader
webpackconfig.jsのrulesに追記
{
  test: /\.yml$/,
  use: [{ loader: 'json-loader' }, { loader: 'yaml-flat-loader' }]
},

メッセージのキーを補完できるようにする

yamlでメッセージ管理する弊害として、コピペがし難いこともあり、補完できるように一手間加えました。
メッセージのキーをオブジェクトとして参照できるようにすることで、メッセージキーの変更やキーの指定ミスがコンパイルエラーになるというメリットもあります。
react-intlの正しい使い方をしているなら、こちらの記事が参考になりますが、JSでデフォルトメッセージを定義して、各言語はyamlというのは面倒です。
メッセージはyamlファイルだけで完結したいので、yamlファイルのキーをjsonにします。

スクリプトを作成し、messageKeysというオブジェクトが各ファイルから参照できるようにします。
ja.ymlに存在するキーをJSONにしています。

スクリプト詳細(クリックで開く)
まずは必要ライブラリのインストール
npm install --save-dev js-yaml
scripts/messageGen.js
'use strict';

var yaml = require('js-yaml');
var fs = require('fs');

// Get document, or throw exception on error
try {
  let doc = yaml.safeLoad(fs.readFileSync('src/i18n/ja.yml', 'utf8'));
  let str = "export const messageKeys =";
  str += JSON.stringify(keyToValue("", doc));
  str += ';\n';
  str += "export default messageKeys;"
  fs.writeFile("src/i18n/messageKeys.tsx", str, (err) => {
    if (err) {
      throw err;
    }
  });
} catch (e) {
  console.log(e);
}

function keyToValue(parentKey, param) {
  let ret = param;
  for (let [key, value] of Object.entries(param)) {
    if (typeof value === 'object') {
        keyToValue(parentKey + key.toString() + ".", value);
    } else if (typeof value === 'string') {
      ret[key] = parentKey + key;
    }
  }
  return ret;
}
package.json(抜粋)
"scripts": {
-  "start": "node scripts/start.js",
+  "start": "node scripts/messageGen.js && node scripts/start.js",
+  "message": "node scripts/messageGen.js"
},

使用例
import messageKeys from "src/i18n/messageKeys";
~~~中略コンポーネント内~~~
const intl = useIntl();
intl.formattedMassage({ id: messageKeys.some.message.id });

"npm run message"でsrc/i18n/ja.ymlに存在するキーをjsonにしてくれます。
※エディタ上で補完できるようにするには、messageKeys.jsを一度開く必要がありました。

スタイリング方法を考える

こちらの記事を参考に、"1. クラス名によるスタイリング"と"3. CSS Modules"で悩みましたが、CSS(SCSS)によるスタイリングを採用しました。
理由は、

  • 業務ロジックやイベント処理を記述しているコンポーネントファイルに、見た目のことまで書きたくない
  • 普通のSCSSの方が書ける人が多い
  • ぶっちゃけCSS Moduleよくわからなかった

あたりです。
ただし、これには以下のデメリットがあります。

  • 普通にscssをimportすると、Reactはstyleタグを生成するので影響範囲は全体ということになる
  • 上記動作により、複数回importされると無駄なstyleタグが増えることになる

よって、コンポーネントのrootとなる要素にclassを設定し、その下にネストしたSCSSを書くようにしました。
(結局は開発者の運用努力なので、改善すべき部分ではあります。)

結び

まだまだ色々なことをやった(ような気がします)が、以上が開発開始時の"進め方"を決める段階で時間をかけて考えた部分になります。
これからReactの開発を始める際の参考になれば幸いです。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1