経緯
作業としては、もともとJavascript+jQuery で記述されていたあるWebアプリケーションをモダンなVueにリファクタリングしようとしていました。
このWebアプリケーションは、工場に納品する装置に付随して提供されるもので、納入先ごとにタイトルや、一部機能の有効無効を切り替える必要がありました。
従来の設定ファイルの運用としては、以下のとおり。
- 大まかに2つの設定ファイル(.json)で構成されていた。
- 1つは内部的な設定ファイル
- もう1つは納入先ごとに変更するための設定ファイル
新システムの前提条件
- Vue-CLI で作成した Vue2 のシステム
- Node.js ver.16.13.x
- Vuexは利用していない
困ったこと
- publicフォルダに置いた設定ファイルが、mounted()処理までに間に合わない
設定ファイルの配置場所
Vue-CLIで作成したプロジェクトでは、主にwebpackでビルド対象となる src/ フォルダと、対象とならない public/ フォルダがある。
内部的な設定ファイル(inner-config.json)は、バンドル対象の src/assets/ へ配置した。
一方、納入先ごとに変更するための設定ファイル(config.json)は、開発者以外が調整する項目なので、webpackのバンドル対象とはできず public/ へ配置した。
├ public/ ←このフォルダの下は、npm run build 後そのままコピーされる
│ ├ config.json
│ ├ index.html
│ └ favicon.ico
├ src/ ←このフォルダの下は、webpackによりバンドル(1つのファイルにまとめること)の対象となる
│ ├ assets/
│ │ └ inner-config.json
│ ├ view/
:
:
設定ファイルのロード
inner-config.json → importで即時に取得
src/ 以下にあるファイルは、import文で扱うことができる。webpackでバンドルされているということは、もうメモリ上に展開されているので、ロードに時間がかかるわけもなく、すぐに設定が使える。
import innerConfig from '@/assets/inner-config.json'
innerConfig.paramA ... // この時点で使える
config.json → axiosで非同期的に取得
一方、public/ 以下にあるファイルは、axiosを使って読みに行くのが一般的らしい。axiosといえば、非同期で動く。created()時にaxiosでキックしても、mounted()の処理が終わってからようやく読み込み結果が得られる状態だった。
axios
.get("config.json")
.then(response => {
response.data.paramB // このthen()に指定した無名関数は非同期で呼ばれる
})
UIの構築
各コンポーネントは、mounted()をきっかけに設定がある前提でUIを構築した。
起こったこと
上記の結果、public/ に配置した設定ファイルが、起動直後に読めず、表示が崩れた。
対策
index.htmlでscriptタグで読み、グローバル変数に用意する(不採用)
深くは検討していないが、従来できていたんだからできるのかもしれない。しかし、せっかくVueを使っているのに、古臭いコードがまぎれると汚くなるし、設計資料も多く残さにゃならないから、却下した。
UIの構築をaxios読み込み後にする(不採用)
これが、正解なんだろうが、起動までに毎回、若干時間がかかるのが許容できなかった。これも却下。
axios読み込み後にCookieに設定保存、2回目以降はCookieの設定を使う
以下の手順を採用した。
- デフォルト設定値用意
- < created() > 【Cookieに設定値がある場合】Cookieの設定値に上書き
- < created() > axiosで、config.jsonを読み込み開始
- < mounted() > 設定値をもとにUI構築
- < axios.then()のコールバック > 【Cookieの設定値とaxios読み込み設定値が異なる場合】Cookieに設定値を保存し、リロード
おわりに
今回は、結構作りこんだあとに対処したため、こんな処理に落ち着いた。webpackバンドルしていない設定値を同期でとる方法が他にあるなら、だれか教えてほしい。いや、本当に。