webpackでpugのmeta情報を動的に出し分ける方法

webpackのみでpugを含めた開発環境を作ろうとしたとき、問題になりやすいのがmeta情報の出しわけかと思います。
webpackで環境を作った場合、pugもloader経由になるので個別にdataを渡しにくいのが問題になるためです。

この問題をどう解決しているかネットで探ると、出てくるのが二つのパターンだと思います。

## パターン１　pugファイル上でJSONのキーを設定して出し分ける方法

https://tsudoi.org/guide2019/detail/3.html

こちらの記事にあるように各ページにjsonのキーを埋め込んで、JSONからデータを取得するもの

```js
- var page = pagelist['pagelist'];
```

このパターン比較的スマートだと思うのですが、各ページに自分でキーを埋め込む必要性があるので、コピペでそのまま変更忘れなどの**ヒューマンエラー**が発生する可能性があります。
gulp-dataだとこの辺を自動で解決できるので難を示す人もいるんじゃないでしょうか。


## パターン２　globuleなどを使いHtmlWebpackPluginでdataにJSON情報を埋め込む方法

[【脱gulp】webpackでpugを使う。jsonで一括ビルドも。](https://uemaweb.com/tech/2331/)

こちらの記事にあるように、各entryに対してHtmlWebpackPluginでJSONデータを埋め込んで取得すもの

```js
documents.forEach((document) => {
  const replaceJson = document.replace('_template', '_data').replace('.pug', '.json')
  const json = require(replaceJson)
  Object.keys(json).forEach((f) => {
    const fileName = f
    app.plugins.push(
      new HtmlWebpackPlugin({
        filename: `${dirName}/${fileName}.html`,
        template: document,
        data: json[f],
      })
    )
  })
}
```
この方法だと動的に埋め込まれるので、パターン１のようなヒューマンエラーは無く一見よさそうに見えるのですが、これにも欠点があります。
webpackのentryにpugを全部突っ込むので、コンソールに**大量のログ**が出ます。

自分も [Webpackを頑張って設定して、すごい静的サイトジェネレータとして使おう](https://qiita.com/toduq/items/2e0b08bb722736d7968c) を参考に作ったことあるのですが、ページが増えるほどビルドするたびに恐ろしいログが流れます（１ページ１行どころではないです。HtmlWebpackPluginを入れるとさらにヤバい事になります）。デプロイ位なら良いのですが開発中だとエラーを追うのも結構しんどいです。
pugを含める環境を作る場合は [webpackだけでpugをビルドする環境を作る](https://qiita.com/wintyo/items/50e5a95e7dc10f237c5d) にあるような、entryするjsの中で **pugをimportしてextructする形** にする方がお勧めです。
entryが少なくなり全体の流れるログをかなり減らす事が出来ます。


どちらも欠点があるので別の方法を紹介したいと思います。

## パターン３　pug-html-info-loader を使用してpugのローカル変数からJSONで出し分ける方法

パターン１で各ページに自分で埋め込まなきゃいけなかったものを、自動で埋め込めるようにする方法です。

既存にあるpug系loaderだとパス情報をうまく取得する方法が見つからなかったので、pug-html-loaderをカスタマイズして **[pug-html-info-loader](https://www.npmjs.com/package/pug-html-info-loader)** を作りました。

pug-html-loaderの代わりに使用すると、パス情報(pathInfo)をローカル変数として自動的にセットすることができます。
変更内容自体はpug-html-loaderに、ローカル変数を追加しているだけなので、使い方は一緒です。

### pug-html-info-loaderのローカル変数で取得できるpathInfoの情報
例
optionsでbasePathをsrc/baseDir/の位置に設定した場合に
src/baseDir/first/second/page.pug で取れるpathInfoの情報 

【 pathInfo.pug 】 → first/second/page.pug
【 pathInfo.html 】 → first/second/page.html
【 pathInfo.dir 】 → first/second/
【 pathInfo.parent 】 → second
【 pathInfo.basename 】 → page
【 pathInfo.htmlname 】 → page.html
【 pathInfo.pugname 】 → page.pug

この【 pathInfo.html 】などをキーにしたjsonなどを作成することで、動的にmeta情報や他に使用したい情報をpugから取得することが出来ます。他にもparentやbasenameをページのclassとして利用したりできると思います。

### 具体的なmetaの設定方法
各ページに設定するmetaのjsonを以下のような形で作ります。

【 global 】に共通のmeta情報
【 local [ **pathInfo.htmlになるキー** ]  】に個別のページmeta情報


```json:meta.json
{
  "global": {
    "title": "global title",
    "description": "global description",
    "og_url": "global og_url",
    "og_image": "global og_image",
    "og_siteName": "siteName",
    "og_type": "website",
  },
  "local": {
    "path/to/page1.html": {
      "title": "Page1 title",
      "description": "Page1 description",
      "og_url": "Page1 og_url",
      "og_image": "Page1 og_image"
    },
    "path/to/page2.html": {
      "title": "Page2 title",
      "description": "Page2 description",
      "og_url": "Page2 og_url",
      "og_image": "Page2 og_image"
    }
  }
}
```

webpackの設定

```js:webpack.conf.js
const path = require('path')
const metadata = require('./meta.json')

module.exports = {
  module: [{
    rules: [
      {
      test: /\.pug/,
      use: [
        'html-loader',
        {
          loader: 'pug-html-info-loader',
          options: {
            data: {
              globalConf:metadata['global'],
              localConf :metadata['local']
            }, //meta.jsonのglobalとlocalをそれぞれの変数としてセットする
            basePath: path.resolve(__dirname, 'src')
            // 基準になるパスの位置をsrcフォルダに設定
          }
        }
      ]
    }]
```




layout用のpugファイルを以下のようにします。

```js:layout.pug
- var config = localConf[pathInfo.html] ? localConf[pathInfo.html] : globalConf ;

doctype html
html(lang='ja')
  head
    meta(charset='utf-8')
    title #{config.title}
    meta(name='description', content=config.description)
    meta(property='og:title', content=config.title)
    meta(property='og:site_name', content=globalConf.og_siteName)
    meta(property='og:description', content=config.description)
    meta(property='og:url', content=config.og_url)
    meta(property='og:image', content=config.og_image)
    meta(property='og:type', content=globalConf.og_type)

```

このように設定することで、以下のように出し分けることが可能になります。

    【 localConf 】に【 pathInfo.html 】が設定されているページ → 個別meta情報
    【 localConf 】に【 pathInfo.html 】が設定されていないページ → 共通のmeta情報


### 組み込んだサンプル

[webpackのみでビルドする環境を作る（pug, sass, babel）](https://qiita.com/itomise/items/e43cb2cedc9d03de43b5)で紹介されている環境に、
pug-html-info-loader でmeta情報を動的に出す方法で改造したものをgitに上げてあります。
触ってみたい方は[ **こちら** ](https://github.com/BigFly3/webpack-template)を試してみてください。

JSONのlocalになる部分をspreadsheetからGASでjsonを作れる仕組みをつくっておくと、より使いやすくなると思います。