0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Vue, YAML】Vue.jsでYMLファイルを読み込みする、画像パスを管理する

Posted at

経緯

非エンジニアが管理しやすいように、ということで、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 defaultexport.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から読み込み、画面に反映させることができました。

感想

まだまだわからないことだらけですね。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?