経緯
非エンジニアが管理しやすいように、ということで、vue.jsでYMLファイルを読み込んで設定ファイルとして使用したかったけれど、少し悩むところもあったので備忘録
結論
<!-- @/components/Hoge.vue -->
<script>
import yaml from "js-yaml"
export default {
data() {
return {
title: "",
image: ""
}
},
methods: {
loadConfig() {
try {
// .defaultが重要
const txt = require("raw-loader!@/assets/hogehoge.yml").default
const config = yaml.load(txt)
this.title = config["hoge"].title
// 画像パスの解決
this.image = require(`../assets/${config["hoge"].image}`)
} catch (error) {
console.log('YMLファイルの読み込みに失敗しました: ', error)
}
}
}
}
</script>
環境
windows10
Vue.js v3.2系
webpack v4
ymlサンプル
hoge:
title: "youkoso!!"
image: "hoge.png"
読み込みにはjs-yamlを使用
まずはjs-yamlをインストール
npm i js-yaml
次に公式の手順だと以下となる
const yaml = require('js-yaml');
const fs = require('fs');
// Get document, or throw exception on error
try {
const doc = yaml.load(fs.readFileSync('/home/ixti/example.yml', 'utf8'));
console.log(doc);
} catch (e) {
console.log(e);
}
が、残念ながらVue.jsではfsは使用できないらしい
※js-yamlはそもそもnode.js向け
fsの代わりに
next.jsだと下記引用のような方法もあるみたいですが、私の環境では使えませんでした。
https://stackoverflow.com/questions/71040231/typeerror-fs-readfilesync-is-not-a-function-in-next-js
ここでは代わりにraw-loaderを使用します。
まずはインストール
npm install raw-loader --save-dev
そしてconfigに以下を追加
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.yml$/i,
use: 'raw-loader',
},
],
},
};
公式だとtest: /\.txt$/i
ですが、今回はymlファイルの読み込みに使いたいだけなのでymlとしました。
raw-loaderを使ってみる
では準備もできたので早速反映
<!-- @/components/Hoge.vue -->
<template>
<div>
<h1>{{ title }}</h1>
<img :src="image" />
</div>
</template>
<script>
import yaml from "js-yaml"
export default {
data() {
return {
title: "",
image: ""
}
},
methods: {
loadConfig() {
try {
const config = yaml.load(require("raw-loader!@/assets/hogehoge.yml"))
console.log('config', config)
this.title = config["hoge"].title
this.image = config["hoge"].image
} catch (error) {
console.log('YMLファイルの読み込みに失敗しました: ', error)
}
}
}
}
</script>
これでようやく使えるかと思いきや、私の環境ではエラーが出ました。
ここにエラー書く
何か間違ったかと焦りましたが、ESLintのエラーでした。
.eslintrc.js
等設定ファイルに無視する設定を追記して、黙っていただきましょう。→参考
// .eslintrc.js
module.exports = {
rules: {
"import/no-webpack-loader-syntax": "off"
}
}
それでも読めない
ここまで設定してもYMLファイルの読み込みは失敗し、configの中身を確認してもlength: 1
の['object Module']
だけが返る状況…
調べたところ、require()
には.default
が必要になる場合があるみたいでした。
require("raw-loader!@/assets/hogehoge.yml").default
これでようやくYMLファイルの読み込みができるようになりました。
.default
が必要かどうかは、export default
とexport.default
の違いらしいですがよくわからず…
こちらは別の機会に調べたいと思います。笑
画像パスが解決できない
せっかくYMLが読めるようになりましたが、今度はYMLに書いた画像パスを解決できず、画像が表示されません…
原因は2つ
1つ目はwebpackが原因で静的アセットのパス解決ができていませんでした。
webpackも理解ができるよう、require()
してあげます。
2つ目は相対パスです。
今回のファイル構造は以下です。
src/
assets/
hoge.png
hogehoge.yml
components/
Hoge.vue
当初ymlの位置からのパスとして./hoge.png
としていたのですが、yml読み込みをしたHoge.vueからpngを探しに行くため、../assets/hoge.png
が正解でした。
今回はymlファイルの管理は非エンジニアが行う想定なので、記述時に混乱しないようにということも兼ねて、ymlにはファイル名だけを記載し、パスは読み込み時に追加する方式にしました。
// 画像パスの解決
this.image = require(`../assets/${config["hoge"].image}`)
これでようやく、YMLファイルの内容をVueから読み込み、画面に反映させることができました。
感想
まだまだわからないことだらけですね。