なぜ?
SPAで開発してると状態管理が大変になり、参照したい状態がどこにあるか探すのが大変。
そこで、状態のみを抽出して構造化したら全体像を把握できて探すのが楽になるのでは?
と思いやってみます。
どうやって?
AST(Abstract Structure Tree)を使って、静的構文解析をして状態を抽出します。
とりあえず、モジュールは考えないでやってみる。
環境
- Node.js(v10.15.3)
- babylon(6.18.0)
- @babel/traverse(7.4.3)
想定するファイルと構成
store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
account: {}
},
getters: {},
mutations: {},
actions: {}
});
期待する出力
state.json
{
'root': {
'account': {}
}
}
状態を抽出するコード
extract-state.js
const fs = require('fs')
const babylon = require('babylon')
const traverse = require('@babel/traverse').default
const IsParentState = Symbol('IsParentState')
const ast = babylon.parse(fs.readFileSync('./store/index.js', 'utf8'), {sourceType: 'module'})
const state = {
'root': {}
}
const visitor = {
ObjectExpression: {
enter(nodePath) {
// 親ノードがオブジェクトのプロパティかつ、キーがstate
if (nodePath.parent.type === 'ObjectProperty' && nodePath.parent.key.name === 'state') {
nodePath[IsParentState] = true
}
},
exit(nodePath) {
// state(Vuex)キーのvalueを評価して、出力用のstate.rootのvalueとする
if (nodePath[IsParentState]) {
const { value } = nodePath.evaluate()
Object.assign(state.root, value)
}
}
}
}
traverse(ast, visitor)
console.log(state)
実行
node extract-state.js
結果
{ root: { account: {} } }
store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
account: {},
isSignIn: false
},
getters: {},
mutations: {},
actions: {}
});
で実行すると、
{ root: { account: {}, isSignIn: false } }
となる。
今後の課題
- stateがショートハンドで初期化されてる場合、抽出できない
- stateキーがあるオブジェクトすべてを対象としてしまってるので正しく抽出できない場合がある
- モジュールの状態が抽出できてない
モジュールの状態が抽出できないと目的達成できないですが、時間切れなので
また別の機会に解決したいと思います。